Example #1
0
// Given a show pointer, appends all the seasons/episodes found for the show
func (show *CrunchyrollShow) ScrapeEpisodes(showURL string, cookies []*http.Cookie) error {
	// Gets the HTML of the show page
	showResponse, err := anirip.GetHTTPResponse("GET",
		showURL,
		nil,
		nil,
		cookies)
	if err != nil {
		return err
	}

	// Creates a goquery document for scraping
	showDoc, err := goquery.NewDocumentFromResponse(showResponse)
	if err != nil {
		return anirip.Error{Message: "There was an error while accessing the show page", Err: err}
	}

	// Scrapes the show metadata from the show page
	showMetaDataJSON := showDoc.Find("script#liftigniter-metadata").First().Text()

	// Parses the metadata json to a ShowMetaData object
	showMetaData := new(ShowMetaData)
	if err := json.Unmarshal([]byte(showMetaDataJSON), showMetaData); err != nil {
		return anirip.Error{Message: "There was an error while parsing show metadata", Err: err}
	}

	// Sets Title, and Path and URL on our show object
	show.Title = showMetaData.Name
	show.URL = showMetaData.URL
	show.Path = strings.Replace(show.URL, "http://www.crunchyroll.com", "", 1) // Removes the host so we have just the path

	// Searches first for the search div
	showDoc.Find("ul.list-of-seasons.cf").Each(func(i int, seasonList *goquery.Selection) {
		seasonList.Find("li.season").Each(func(i2 int, episodeList *goquery.Selection) {
			// Adds a new season to the show containing all information
			seasonTitle, _ := episodeList.Find("a").First().Attr("title")

			// Adds the title minus any "Episode XX" for shows that only have one season
			show.Seasons = append(show.Seasons, CrunchyrollSeason{
				Title: strings.SplitN(seasonTitle, " Episode ", 2)[0],
			})

			// Within that season finds all episodes
			episodeList.Find("div.wrapper.container-shadow.hover-classes").Each(func(i3 int, episode *goquery.Selection) {
				// Appends all new episode information to newly appended season
				episodeTitle := strings.TrimSpace(strings.Replace(episode.Find("span.series-title.block.ellipsis").First().Text(), "\n", "", 1))
				episodeNumber, _ := strconv.ParseFloat(strings.Replace(episodeTitle, "Episode ", "", 1), 64)
				episodePath, _ := episode.Find("a").First().Attr("href")
				episodeID, _ := strconv.Atoi(episodePath[len(episodePath)-6:])
				show.Seasons[i2].Episodes = append(show.Seasons[i2].Episodes, CrunchyrollEpisode{
					ID:     episodeID,
					Title:  episodeTitle,
					Number: episodeNumber,
					Path:   episodePath,
					URL:    "http://www.crunchyroll.com" + episodePath,
				})
			})
		})
	})

	// Re-arranges seasons and episodes in the shows object so we have first to last
	tempSeasonArray := []CrunchyrollSeason{}
	for i := len(show.Seasons) - 1; i >= 0; i-- {
		// First sort episodes from first to last
		tempEpisodesArray := []CrunchyrollEpisode{}
		for n := len(show.Seasons[i].Episodes) - 1; n >= 0; n-- {
			tempEpisodesArray = append(tempEpisodesArray, show.Seasons[i].Episodes[n])
		}
		// Lets not bother appending anything if there are no episodes in the season
		if len(tempEpisodesArray) > 0 {
			tempSeasonArray = append(tempSeasonArray, CrunchyrollSeason{
				Title:    show.Seasons[i].Title,
				Length:   len(tempEpisodesArray),
				Episodes: tempEpisodesArray,
			})
		}
	}
	show.Seasons = tempSeasonArray

	// Assigns each season a number and episode a filename
	for s, season := range show.Seasons {
		show.Seasons[s].Number = s + 1
		for e, episode := range season.Episodes {
			show.Seasons[s].Episodes[e].FileName = anirip.GenerateEpisodeFileName(show.Title, show.Seasons[s].Number, episode.Number, "")
		}
	}

	// TODO Filter out episodes that aren't yet released (ex One Piece)
	return nil
}
Example #2
0
// Given a show pointer, appends all the seasons/episodes found for the show
func (show *DaisukiShow) ScrapeEpisodes(showURL string, cookies []*http.Cookie) error {
	// Gets the HTML of the show page
	showResponse, err := anirip.GetHTTPResponse("GET",
		showURL,
		nil,
		nil,
		cookies)
	if err != nil {
		return err
	}

	// Creates a goquery document for scraping episodes
	showDoc, err := goquery.NewDocumentFromResponse(showResponse)
	if err != nil {
		return anirip.Error{Message: "There was an error while accessing the show page", Err: err}
	}

	// Sets Title, AdID and Path in the case where the user passes a show URL
	if show.Title == "" {
		show.Title = showDoc.Find("h1#animeTitle").First().Text() // Scrapes the show title fromt he season body if it wasn't set by a search
	}
	if show.URL == "" {
		show.URL = showURL
	}
	if show.Path == "" {
		show.Path = strings.Replace(show.URL, "http://www.daisuki.net", "", 1) // Removes the host so we have just the path
	}
	if show.AdID == "" {
		show.AdID = strings.Replace(show.URL, "http://www.daisuki.net/us/en/anime/detail.", "", 1) // Removes the leading path
		show.AdID = strings.Replace(show.AdID, ".html", "", 1)                                     // Replaces the .html so we have just the AdID
	}

	// Searches first for the episodes/movies
	episodeMap := make(map[int]string)
	showDoc.Find("div#moviesBlock").Each(func(i int, season *goquery.Selection) {
		// Finds the non-movie/latest-or-first episode and adds it to our map
		season.Find("div#content0.content.clearFix.liquid").Each(func(i2 int, movieEpisode *goquery.Selection) {
			// Gets the episode number from that movie
			episodeThumb, exists := movieEpisode.Find("img").First().Attr("delay")
			episodeNumber, err := strconv.Atoi(movieEpisode.Find("p.episodeNumber").Text())
			if err == nil && exists && episodeThumb != "" {
				episodeMap[episodeNumber] = "/us/en/anime/watch." + strings.Split(episodeThumb, "/")[6] + "." + strings.Split(episodeThumb, "/")[7] + ".html"
			}
		})
		// Finds ALL non-movie/latest-or-first episodes
		season.Find("div#contentList0.contentList.clearFix.liquid div.item").Each(func(i2 int, episodeItem *goquery.Selection) {
			// Grabs episode information that isn't empty and has a url associated with an episode number
			episodeThumb, exists := episodeItem.Find("img").First().Attr("delay")
			episodeNumber, err := strconv.Atoi(episodeItem.Find("p.episodeNumber").Text())
			if err == nil && exists && episodeThumb != "" {
				episodeMap[episodeNumber] = "/us/en/anime/watch." + strings.Split(episodeThumb, "/")[6] + "." + strings.Split(episodeThumb, "/")[7] + ".html"
			}
		})
	})

	// Re-arranges seasons and episodes in the shows object so we have first to last
	show.Seasons = append(show.Seasons, DaisukiSeason{ // appends a new season that we'll append episodes to
		Title:  show.Title,
		Number: 1,
		Length: len(episodeMap),
	})
	for i := 0; i < len(episodeMap); i++ {
		show.Seasons[0].Episodes = append(show.Seasons[0].Episodes, DaisukiEpisode{
			Number: float64(i + 1),
			Path:   episodeMap[i+1],
			URL:    "http://www.daisuki.net" + episodeMap[i+1],
		})
	}

	// Assigns each season a number and episode a filename
	for s, season := range show.Seasons {
		for e, episode := range season.Episodes {
			// Generates a partial file name that we'll later improve on when we get the episode html
			show.Seasons[s].Episodes[e].FileName = anirip.GenerateEpisodeFileName(show.Title, show.Seasons[s].Number, episode.Number, "")
		}
	}
	return nil
}