public async Task<AnimeDetail> GetAnimeDetailAsync(string login, string password, int animeId) { var cookies = await CookieHelper.GetCookies(login, password, UserAgent); RestClient.BaseUrl = new Uri(string.Format("http://myanimelist.net/anime/{0}", animeId)); var request = GetRestRequest(Method.GET, cookies); var result = await ExecuteTaskASync(request).ConfigureAwait(false); var animeDetail = new AnimeDetail(); var document = new HtmlDocument(); document.LoadHtml(result); SetId(document, animeDetail); SetRank(document, animeDetail); SetTitle(document, animeDetail); SetImageUrl(document, animeDetail); var leftColumnNodeset = document.DocumentNode.SelectSingleNode("//div[@id='content']//table//tr//td[@class='borderClass']"); if (leftColumnNodeset != null) { SetAnimeAlternativeTitles(leftColumnNodeset, animeDetail); SetType(document, animeDetail); SetNumberOfEpisodes(leftColumnNodeset, animeDetail); SetStatus(leftColumnNodeset, animeDetail); SetAiredDate(leftColumnNodeset, animeDetail); SetGenres(leftColumnNodeset, animeDetail); SetClassification(leftColumnNodeset, animeDetail); SetScore(leftColumnNodeset, animeDetail); SetPopularityRank(leftColumnNodeset, animeDetail); SetMembers(leftColumnNodeset, animeDetail); SetFavorite(leftColumnNodeset, animeDetail); SetPopularTags(leftColumnNodeset, animeDetail); } var rightColumnNodeset = document.DocumentNode.SelectSingleNode("//h2[text()='Synopsis']").ParentNode.ParentNode.ParentNode; if (rightColumnNodeset != null) { SetSynopsis(rightColumnNodeset, animeDetail); SetRelatedAnime(rightColumnNodeset, animeDetail); } SetWatchedStatus(document, animeDetail); SetWatchedEpisode(document, animeDetail); SetMyScore(document, animeDetail); SetListedAnimeId(document, animeDetail); return animeDetail; }
private static void SetGenres(HtmlNode leftColumnNodeset, AnimeDetail animeDetail) { var genre = leftColumnNodeset.SelectSingleNode("//span[text()='Genres:']"); if (genre != null) { animeDetail.Genres = genre.ParentNode.ChildNodes.Where(c => c.Name == "a").Select(x => x.InnerText.Trim()).ToList(); } }
private static void SetAiredDate(HtmlNode leftColumnNodeset, AnimeDetail animeDetail) { var aired = leftColumnNodeset.SelectSingleNode("//span[text()='Aired:']"); if (aired != null) { var airDateText = aired.NextSibling.InnerText; if (airDateText.Contains("to")) { var startDateText = airDateText.Substring(0, airDateText.IndexOf("to")).Trim(); var options = RegexOptions.None; var regex = new Regex(@"[ ]{2,}", options); startDateText = regex.Replace(startDateText, @" "); DateTime startDate; if (DateTime.TryParseExact(startDateText, "MMM d, yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out startDate)) { animeDetail.StartDate = startDate.ToString("d"); } else animeDetail.StartDate = startDateText; if (airDateText.Contains("?")) { animeDetail.EndDate = null; } else { var endDateText = airDateText.Substring(airDateText.IndexOf("to") + 2).Trim(); endDateText = regex.Replace(endDateText, @" "); DateTime endDate; if (DateTime.TryParseExact(endDateText, "MMM d, yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out endDate)) { animeDetail.EndDate = endDate.ToString("d"); } else { animeDetail.EndDate = endDateText; } } } else { var startDateText = airDateText.IndexOf("to") == -1 ? airDateText.Trim() : airDateText.Substring(0, airDateText.IndexOf("to")).Trim(); var options = RegexOptions.None; var regex = new Regex(@"[ ]{2,}", options); startDateText = regex.Replace(startDateText, @" "); DateTime startDate; if (DateTime.TryParseExact(startDateText, "MMM d, yyyy", CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault, out startDate)) animeDetail.StartDate = startDate.ToString("d"); else if (DateTime.TryParseExact(startDateText, "MMM yyyy", CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault, out startDate)) { animeDetail.StartDate = startDate.ToString("d"); } else animeDetail.StartDate = startDateText; animeDetail.EndDate = null; } } }
private static void SetRank(HtmlDocument document, AnimeDetail animeDetail) { var rankNode = document.DocumentNode.SelectSingleNode("//span[contains(.,'Rank')]"); if (rankNode != null) { if (rankNode.NextSibling.InnerText.ToUpper().Contains("N/A")) animeDetail.Rank = 0; else { var regex = Regex.Match(rankNode.NextSibling.InnerText, @"\d+"); animeDetail.Rank = Convert.ToInt32(regex.ToString()); } } }
private static void SetListedAnimeId(HtmlDocument document, AnimeDetail animeDetail) { var editDetailNode = document.DocumentNode.SelectSingleNode("//a[text()='Edit Details']"); if (editDetailNode != null) { var hrefValue = editDetailNode.Attributes["href"].Value; var regex = Regex.Match(hrefValue, @"\d+"); animeDetail.ListedAnimeId = Convert.ToInt32(regex.ToString()); } }
private static void SetType(HtmlDocument document, AnimeDetail animeDetail) { var type = document.DocumentNode.SelectSingleNode("//span[contains(.,'Type:')]"); if (type != null) animeDetail.Type = type.NextSibling.NextSibling.InnerText.Trim(); }
private static void SetImageUrl(HtmlDocument document, AnimeDetail animeDetail) { var imageNode = document.DocumentNode.SelectSingleNode("//div[@id='content']//tr//td//div//img"); if (imageNode != null) animeDetail.ImageUrl = imageNode.Attributes["src"].Value; }
private static void SetPopularTags(HtmlNode leftColumnNodeset, AnimeDetail animeDetail) { var popularTags = leftColumnNodeset.SelectSingleNode("//span[preceding-sibling::h2[text()='Popular Tags']]"); if (popularTags != null) { animeDetail.Tags = popularTags.ChildNodes.Where(c => c.Name == "a").Select(x => x.InnerText.Trim()).ToList(); } }
private static void SetFavorite(HtmlNode leftColumnNodeset, AnimeDetail animeDetail) { var favorite = leftColumnNodeset.SelectSingleNode("//span[text()='Favorites:']"); if (favorite != null) { int favoritedCount; if (Int32.TryParse(favorite.NextSibling.InnerText.Replace(",", ""), out favoritedCount)) animeDetail.FavoritedCount = favoritedCount; else { animeDetail.FavoritedCount = null; } } }
private void SetRelatedAnime(HtmlNode rightColumnNodeset, AnimeDetail animeDetail) { var relatedAnime = rightColumnNodeset.SelectSingleNode("//h2[text()='Related Anime']"); if (relatedAnime != null) { //Alternative var adaptation = Regex.Match( relatedAnime.ParentNode.InnerHtml.Substring(relatedAnime.ParentNode.InnerHtml.IndexOf("<h2>")), "Adaptation:+(.+?<br)"); if (!string.IsNullOrEmpty(adaptation.ToString())) { animeDetail.MangaAdaptations = new List<MangaSummary>(); SetMangaSummaryList(animeDetail.MangaAdaptations, adaptation.ToString()); } //Prequel var prequel = Regex.Match( relatedAnime.ParentNode.InnerHtml.Substring(relatedAnime.ParentNode.InnerHtml.IndexOf("<h2>")), "Prequel:+(.+?<br)"); if (!string.IsNullOrEmpty(prequel.ToString())) { animeDetail.Prequels = new List<AnimeSummary>(); SetAnimeSummaryList(animeDetail.Prequels, prequel.ToString()); } //Sequel var sequel = Regex.Match( relatedAnime.ParentNode.InnerHtml.Substring(relatedAnime.ParentNode.InnerHtml.IndexOf("<h2>")), "Sequel:+(.+?<br)"); if (!string.IsNullOrEmpty(sequel.ToString())) { animeDetail.Sequels = new List<AnimeSummary>(); SetAnimeSummaryList(animeDetail.Sequels, sequel.ToString()); } //Side story var sideStory = Regex.Match( relatedAnime.ParentNode.InnerHtml.Substring(relatedAnime.ParentNode.InnerHtml.IndexOf("<h2>")), "Side story:+(.+?<br)"); if (!string.IsNullOrEmpty(sideStory.ToString())) { animeDetail.SideStories = new List<AnimeSummary>(); SetAnimeSummaryList(animeDetail.SideStories, sideStory.ToString()); } //Parent story var parentStory = Regex.Match( relatedAnime.ParentNode.InnerHtml.Substring(relatedAnime.ParentNode.InnerHtml.IndexOf("<h2>")), "Parent story:+(.+?<br)"); if (!string.IsNullOrEmpty(parentStory.ToString())) { animeDetail.ParentStory = SetAnimeSummaryList(parentStory.ToString()); } //Spin off var spinOff = Regex.Match( relatedAnime.ParentNode.InnerHtml.Substring(relatedAnime.ParentNode.InnerHtml.IndexOf("<h2>")), "Spin-off:+(.+?<br)"); if (!string.IsNullOrEmpty(spinOff.ToString())) { animeDetail.SpinOffs = new List<AnimeSummary>(); SetAnimeSummaryList(animeDetail.SpinOffs, spinOff.ToString()); } //Summary var summary = Regex.Match( relatedAnime.ParentNode.InnerHtml.Substring(relatedAnime.ParentNode.InnerHtml.IndexOf("<h2>")), "Summary:+(.+?<br)"); if (!string.IsNullOrEmpty(summary.ToString()) && !summary.ToString().Contains("Summary:<br")) { animeDetail.Summaries = new List<AnimeSummary>(); SetAnimeSummaryList(animeDetail.Summaries, summary.ToString()); } //Alternative version var alternativeVersion = Regex.Match( relatedAnime.ParentNode.InnerHtml.Substring(relatedAnime.ParentNode.InnerHtml.IndexOf("<h2>")), "Alternative versions?:+(.+?<br)"); if (!string.IsNullOrEmpty(alternativeVersion.ToString())) { animeDetail.AlternativeVersions = new List<AnimeSummary>(); SetAnimeSummaryList(animeDetail.AlternativeVersions, alternativeVersion.ToString()); } } }
private static void SetSynopsis(HtmlNode rightColumnNodeset, AnimeDetail animeDetail) { var synopsis = rightColumnNodeset.SelectSingleNode("//h2[text()='Synopsis']"); if (synopsis != null) { animeDetail.Synopsis = Regex.Replace(HttpUtility.HtmlDecode(synopsis.NextSibling.InnerText), "<br>", ""); } }
private static void SetWatchedStatus(HtmlDocument document, AnimeDetail animeDetail) { var watchedStatusNode = document.DocumentNode.SelectNodes("//select[@id='myinfo_status']") .FirstOrDefault(c => c.InnerHtml.ToUpper().Contains("SELECTED")); if (watchedStatusNode != null) { var selectedOption = watchedStatusNode.ChildNodes.Where(c => c.Name.ToLowerInvariant() == "option"); var selected = from c in selectedOption from x in c.Attributes where x.Name.ToLowerInvariant() == "selected" select c; if (selected.FirstOrDefault() != null) animeDetail.WatchedStatus = selected.FirstOrDefault().NextSibling.InnerText; } }
private static void SetWatchedEpisode(HtmlDocument document, AnimeDetail animeDetail) { var watchedEpisodeNode = document.DocumentNode.SelectSingleNode("//input[@id='myinfo_watchedeps']"); if (watchedEpisodeNode != null) { var value = watchedEpisodeNode.Attributes.FirstOrDefault(c => c.Name.ToLowerInvariant() == "value"); if (value != null) { int watched; if (Int32.TryParse(value.Value, out watched)) animeDetail.WatchedEpisodes = watched; else { animeDetail.WatchedEpisodes = 0; } } } }
private static void SetMyScore(HtmlDocument document, AnimeDetail animeDetail) { var myScoreNode = document.DocumentNode.SelectSingleNode("//select[@id='myinfo_score']"); if (myScoreNode != null) { var selectedOption = myScoreNode.ChildNodes.Where(c => c.Name.ToLowerInvariant() == "option"); var selected = from c in selectedOption from x in c.Attributes where x.Name.ToLowerInvariant() == "selected" select c; if (selected.FirstOrDefault() != null) { var scoreNode = from c in selected.FirstOrDefault().Attributes where c.Name.ToLowerInvariant() == "value" select c; var score = scoreNode.FirstOrDefault(); if (score != null) animeDetail.Score = score.Value == null ? 0 : Convert.ToInt32(score.Value); } } }
private static void SetStatus(HtmlNode leftColumnNodeset, AnimeDetail animeDetail) { var status = leftColumnNodeset.SelectSingleNode("//span[text()='Status:']"); if (status != null) animeDetail.Status = status.NextSibling.InnerText; }
private static void SetMembers(HtmlNode leftColumnNodeset, AnimeDetail animeDetail) { var member = leftColumnNodeset.SelectSingleNode("//span[text()='Members:']"); if (member != null) { int memberCount; if (Int32.TryParse(member.NextSibling.InnerText.Replace(",", ""), out memberCount)) animeDetail.MembersCount = memberCount; else { animeDetail.MembersCount = null; } } }
private static void SetNumberOfEpisodes(HtmlNode leftColumnNodeset, AnimeDetail animeDetail) { var episode = leftColumnNodeset.SelectSingleNode("//span[text()='Episodes:']"); if (episode != null) { int episodes; if (Int32.TryParse(episode.NextSibling.InnerText.Replace(",", ""), out episodes)) animeDetail.Episodes = episodes; else { animeDetail.Episodes = null; } } }
private static void SetPopularityRank(HtmlNode leftColumnNodeset, AnimeDetail animeDetail) { var popularity = leftColumnNodeset.SelectSingleNode("//span[text()='Popularity:']"); if (popularity != null) { int popularityRank; if (Int32.TryParse(popularity.NextSibling.InnerText.Replace("#", "").Replace(",", ""), out popularityRank)) animeDetail.PopularityRank = popularityRank; else { animeDetail.PopularityRank = null; } } }
private static void SetAnimeAlternativeTitles(HtmlNode leftColumnNodeset, AnimeDetail animeDetail) { var englishAlternative = leftColumnNodeset.SelectSingleNode("//span[text()='English:']"); animeDetail.OtherTitles = new OtherTitles(); if (englishAlternative != null) { animeDetail.OtherTitles.English = englishAlternative.NextSibling.InnerText.Split(',').Select(p => p.Trim()).ToList(); } var japaneseAlternative = leftColumnNodeset.SelectSingleNode("//span[text()='Japanese:']"); if (japaneseAlternative != null) { animeDetail.OtherTitles.Japanese = japaneseAlternative.NextSibling.InnerText.Split(',').Select(p => p.Trim()).ToList(); } }
private static void SetScore(HtmlNode leftColumnNodeset, AnimeDetail animeDetail) { var score = leftColumnNodeset.SelectSingleNode("//span[text()='Score:']"); if (score != null) { double memberScore; if (double.TryParse(score.NextSibling.NextSibling.InnerText, NumberStyles.Any, CultureInfo.InvariantCulture, out memberScore)) animeDetail.MembersScore = memberScore; else { animeDetail.MembersScore = 0; } } }
private static void SetTitle(HtmlDocument document, AnimeDetail animeDetail) { var titleNode = document.DocumentNode.SelectSingleNode("//span[@itemprop='name']"); if (titleNode != null) animeDetail.Title = HttpUtility.HtmlDecode(titleNode.InnerText.Trim()); }
private static void SetClassification(HtmlNode leftColumnNodeset, AnimeDetail animeDetail) { var classification = leftColumnNodeset.SelectSingleNode("//span[text()='Rating:']"); if (classification != null) { animeDetail.Classification = Regex.Replace(classification.NextSibling.InnerText, @"\t|\n|\r", "").Trim(); } }
private static void SetId(HtmlDocument document, AnimeDetail animeDetail) { var animeIdInput = document.DocumentNode.SelectSingleNode("//input[@name='aid']"); if (animeIdInput != null) { animeDetail.Id = Convert.ToInt32(animeIdInput.Attributes["value"].Value); } else { var detailLink = document.DocumentNode.SelectSingleNode("//a[text()='Details']"); if (detailLink != null) { var regex = Regex.Match(detailLink.Attributes["href"].Value, @"\d+"); animeDetail.Id = Convert.ToInt32(regex.ToString()); } } }
public async Task<List<AnimeDetail>> FindTopAnimeAsync(int pageNumber, TopAnimeType topAnimeType) { //Need to be reviewed !!! RestClient.BaseUrl = new Uri("http://myanimelist.net/topanime.php"); var request = GetRestRequest(Method.GET); var animeType = GetTopAnimeType(topAnimeType); if (!string.IsNullOrEmpty(animeType)) request.AddParameter("type", animeType); if (pageNumber > 0) { var limit = pageNumber * 30; request.AddParameter("limit", limit); } var animeDetails = new List<AnimeDetail>(); var result = await ExecuteTaskASync(request).ConfigureAwait(false); var document = new HtmlDocument(); document.LoadHtml(result); var pageContent = document.DocumentNode.SelectNodes("//div[@id='content']//table//tr"); foreach (var row in pageContent) { var animeTitleNode = row.SelectSingleNode("//td//a//strong"); if (animeTitleNode == null) continue; var animeUrl = animeTitleNode.ParentNode.Attributes["href"].Value; if (!animeUrl.Contains("myanimelist.net/anime")) continue; var animeDetail = new AnimeDetail(); var stringToParse = animeUrl.Replace("http://myanimelist.net/anime/", ""); var animeIdString = stringToParse.Substring(0, stringToParse.IndexOf("/", StringComparison.Ordinal)); int animeId; if (Int32.TryParse(animeIdString, out animeId)) { animeDetail.Id = animeId; } else { animeDetail.Id = 0; } animeDetail.Title = HttpUtility.HtmlDecode(animeTitleNode.InnerText); var contentCell = row.SelectSingleNode("//div[@class='spaceit_pad']"); if (contentCell != null) { //Regex.Replace(classification.NextSibling.InnerText, @"\t|\n|\r", "").Trim(); var memberCell = contentCell.SelectSingleNode("//div[@class='spaceit_pad']//span[@class='lightLink']"); if (memberCell != null) { var membersString = memberCell.InnerText.Substring(0, memberCell.InnerText.IndexOf(" ", StringComparison.Ordinal)).Trim(); int memberCount; if (Int32.TryParse(membersString.Replace(",", ""), out memberCount)) { animeDetail.MembersCount = memberCount; } } var stats = Regex.Replace(contentCell.ChildNodes.First().InnerText, @"\t|\n|\r", "").Trim().Split(','); animeDetail.Type = stats[0]; var episodesString = stats[1].Substring(0, stats[1].IndexOf("eps", StringComparison.Ordinal)).Trim(); int episodesCount; if (Int32.TryParse(episodesString, out episodesCount)) { animeDetail.Episodes = episodesCount; } var scoreString = Regex.Match(stats[2], @"\d+\.\d+"); double score; if (Double.TryParse(scoreString.ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out score)) { animeDetail.MembersScore = score; } } } return animeDetails; }