public MangaObject ParseMangaObject(String content) { Int32 MangaInformationContentStart = content.IndexOf("<!-- Intro Series -->"), MangaInformationContentEnd = content.IndexOf("<!-- **END: Intro Series -->", MangaInformationContentStart); String MangaInformationContent = content.Substring(MangaInformationContentStart, MangaInformationContentEnd - MangaInformationContentStart); Int32 MangaChaptersContentStart = content.IndexOf("<!-- Main Content -->"), MangaChaptersContentEnd = content.IndexOf("<!-- **END: Main Content -->", MangaChaptersContentStart); String MangaChaptersContent = content.Substring(MangaChaptersContentStart, MangaChaptersContentEnd - MangaChaptersContentStart); HtmlDocument MangaObjectDocument = new HtmlDocument(); MangaObjectDocument.LoadHtml(MangaInformationContent); HtmlNode MangaObjectNode = MangaObjectDocument.DocumentNode.SelectSingleNode(".//div/div"); String MangaName = String.Empty, Description = String.Empty; List <String> AlternateNames = new List <String>(), AuthorsArtists = new List <String>(), Genres = new List <String>(); foreach (HtmlNode DetailNode in MangaObjectNode.SelectNodes(".//div[2]/div[contains(@class,'row')]")) { HtmlNode DetailTypeNode = DetailNode.SelectSingleNode(".//div[1]/b[1] | .//div[1]/strong[1]"), DetailTextNode = (DetailTypeNode != null) ? DetailTypeNode.NextSibling : null, DetailDescriptionNode = (DetailTextNode != null) ? DetailTextNode.NextSibling : null, MangaNameNode = DetailNode.SelectSingleNode(".//div[1]/h1"); HtmlNodeCollection DetailLinkNodes = DetailNode.SelectNodes(".//div[1]/a"); String DetailType = (DetailTypeNode != null) ? DetailTypeNode.InnerText.Trim().TrimEnd(':') : "MangaName", DetailValue = String.Empty; String[] DetailValues = { }; if (DetailLinkNodes != null) { DetailValues = (from HtmlNode LinkNode in DetailLinkNodes select HtmlEntity.DeEntitize(LinkNode.InnerText.Trim())).ToArray(); } else if (MangaNameNode != null) { DetailValue = HtmlEntity.DeEntitize(MangaNameNode.InnerText.Trim()); } else if (DetailDescriptionNode != null) { DetailValue = HtmlEntity.DeEntitize(DetailDescriptionNode.InnerText.Trim()); } else if (DetailTextNode != null) { DetailValue = HtmlEntity.DeEntitize(DetailTextNode.InnerText.Trim()); } switch (DetailType) { default: break; case "MangaName": MangaName = DetailValue; break; case "Alternate Names": AlternateNames = (from String AltName in DetailValue.Split(',') select HtmlEntity.DeEntitize(AltName.Trim())).ToList(); break; case "Author": AuthorsArtists = DetailValues.ToList(); break; case "Genre": Genres = DetailValues.ToList(); break; case "Description": Description = DetailValue; break; } } String Cover = ExtensionDescriptionAttribute.RootUrl + MangaObjectNode.SelectSingleNode(".//div[1]/img/@src").Attributes["src"].Value; List <ChapterObject> Chapters = new List <ChapterObject>(); MangaObjectDocument.LoadHtml(MangaChaptersContent); HtmlNodeCollection RawChapterList = MangaObjectDocument.DocumentNode.SelectNodes(".//div[contains(@class,'row')]"); foreach (HtmlNode RawChapterNode in RawChapterList.Skip(1)) { HtmlNode ChapterNumberNode = RawChapterNode.SelectSingleNode(".//div[1]/a"), ReleaseDate = RawChapterNode.SelectSingleNode(".//div[2]/time"); String ChapterNumber = Regex.Match(ChapterNumberNode.InnerText, @"\d+(\.\d+)?").Value; String[] ChapterSub = ChapterNumber.Trim().Split('.'); DateTime Released = DateTime.Now; String ReleasedTxt = ReleaseDate.InnerText.ToLower(); if (ReleasedTxt.StartsWith("today")) { Released = DateTime.Today; } else if (ReleasedTxt.StartsWith("yesterday")) { Released = DateTime.Today.AddDays(-1); } else if (ReleasedTxt.EndsWith("ago")) { Int32 tDelta = 0; Int32.TryParse(ReleasedTxt.Split(' ')[0], out tDelta); if (ReleasedTxt.Contains("hours")) { Released = Released.AddHours(0 - tDelta); } if (ReleasedTxt.Contains("minutes")) { Released = Released.AddMinutes(0 - tDelta); } if (ReleasedTxt.Contains("seconds")) { Released = Released.AddSeconds(0 - tDelta); } } else { Released = DateTime.ParseExact(ReleasedTxt, "MM/dd/yyyy", CultureInfo.InvariantCulture); } ChapterObject Chapter = new ChapterObject() { Name = HtmlEntity.DeEntitize(RawChapterNode.SelectSingleNode(".//div[1]/gray").InnerText), Chapter = UInt32.Parse(ChapterSub[0]), Locations = { new LocationObject() { ExtensionName = ExtensionDescriptionAttribute.Name, ExtensionLanguage = ExtensionDescriptionAttribute.Language, Url = ExtensionDescriptionAttribute.RootUrl + ChapterNumberNode.Attributes["href"].Value }, }, Released = Released }; if (ChapterSub.Length == 2) { Chapter.SubChapter = UInt32.Parse(ChapterSub[1]); } Chapters.Add(Chapter); } Chapters.Reverse(); MangaObject MangaObj = new MangaObject() { Name = HtmlEntity.DeEntitize(MangaName), Description = HtmlEntity.DeEntitize(Description), AlternateNames = AlternateNames.ToList(), CoverLocations = { new LocationObject() { Url = Cover, ExtensionName = ExtensionDescriptionAttribute.Name, ExtensionLanguage = ExtensionDescriptionAttribute.Language } }, Authors = AuthorsArtists.ToList(), Artists = AuthorsArtists.ToList(), Genres = Genres.ToList(), Released = Chapters.First().Released, Chapters = Chapters }; MangaObj.AlternateNames.RemoveAll(an => an.ToLower().Equals("none")); MangaObj.Genres.RemoveAll(g => g.ToLower().Equals("none")); return(MangaObj); }
public List <SearchResultObject> ParseSearch(String content) { List <SearchResultObject> SearchResults = new List <SearchResultObject>(); HtmlDocument SearchResultDocument = new HtmlDocument(); SearchResultDocument.LoadHtml(content); HtmlNode MainContainer = SearchResultDocument.DocumentNode.SelectSingleNode("//div[contains(@class,'mainContainer')]"); HtmlNodeCollection SearchResultNodes = MainContainer.SelectNodes(".//div[contains(@class,'well')]/div[contains(@class,'row') and (contains(@class,'available') or contains(@class,'unavailable'))]"); if (!Equals(SearchResultNodes, null)) { foreach (HtmlNode SearchResultNode in SearchResultNodes) { String ImgUrl = ExtensionDescriptionAttribute.RootUrl + SearchResultNode.SelectSingleNode(".//img").Attributes["src"].Value.Substring(2), Name = String.Empty, Link = String.Empty; LocationObject Cover = new LocationObject() { Url = ImgUrl, ExtensionName = ExtensionDescriptionAttribute.Name, ExtensionLanguage = ExtensionDescriptionAttribute.Language }; List <String> AlternateNames = new List <String>(), AuthorsArtists = new List <String>(), Genres = new List <String>(); foreach (HtmlNode DetailNode in SearchResultNode.SelectNodes(".//div[2]/div[contains(@class,'row')]")) { HtmlNode DetailTypeNode = DetailNode.SelectSingleNode(".//div[1]/b[1] | .//div[1]/strong[1]"), DetailTextNode = (DetailTypeNode != null) ? DetailTypeNode.NextSibling : null, DetailDescriptionNode = (DetailTextNode != null) ? DetailTextNode.NextSibling : null, MangaNameNode = DetailNode.SelectSingleNode(".//div[1]/h1/a"); HtmlNodeCollection DetailLinkNodes = DetailNode.SelectNodes(".//div[1]/a"); String DetailType = (DetailTypeNode != null) ? DetailTypeNode.InnerText.Trim().TrimEnd(':') : "MangaName", DetailValue = String.Empty; String[] DetailValues = { }; if (DetailLinkNodes != null) { DetailValues = (from HtmlNode LinkNode in DetailLinkNodes select LinkNode.InnerText).ToArray(); } else if (MangaNameNode != null) { DetailValue = HtmlEntity.DeEntitize(MangaNameNode.InnerText.Trim()); } else if (DetailDescriptionNode != null) { DetailValue = HtmlEntity.DeEntitize(DetailDescriptionNode.InnerText.Trim()); } else if (DetailTextNode != null) { DetailValue = HtmlEntity.DeEntitize(DetailTextNode.InnerText.Trim()); } switch (DetailType) { default: break; case "MangaName": Name = DetailValue; Link = MangaNameNode.Attributes["href"].Value; if (Link.StartsWith("../manga/?series=")) { Link = Link.Substring("../manga/?series=".Length); } else if (Link.StartsWith("../read-online/")) { Link = Link.Substring("../read-online/".Length); } else { Link = Name.Replace(" ", String.Empty); } break; case "Alternate Names": AlternateNames = (from String AltName in DetailValue.Split(',') select AltName.Trim()).ToList(); break; case "Author": AuthorsArtists = DetailValues.ToList(); break; case "Genre": Genres = DetailValues.ToList(); break; } } SearchResults.Add(new SearchResultObject() { Cover = Cover, Name = Name, Url = String.Format("{0}/read-online/{1}", ExtensionDescriptionAttribute.RootUrl, Link), ExtensionName = ExtensionDescriptionAttribute.Name, ExtensionLanguage = ExtensionDescriptionAttribute.Language, Rating = -1, Artists = AuthorsArtists, Authors = AuthorsArtists }); } } return(SearchResults); }
public MangaObject ParseMangaObject(string Content) { HtmlDocument MangaObjectDocument = new HtmlDocument(); MangaObjectDocument.LoadHtml(Content); HtmlNode MangaNode = MangaObjectDocument.DocumentNode.SelectSingleNode(".//section[contains(@class, 'manga')]"); String Name = HtmlEntity.DeEntitize(MangaNode.SelectSingleNode(".//div/div[1]/h1/a").InnerText); Name = Name.Substring(0, Name.LastIndexOf(' ')); HtmlNode AlternateNamesNode = MangaNode.SelectSingleNode(".//div/table/tr/td[2]/table/tr[4]/td"); List <String> AlternateNames = (from AltName in HtmlEntity.DeEntitize(AlternateNamesNode.InnerText).Split(';') select AltName.Trim()).ToList(); List <String> Authors = (from Node in MangaNode.SelectNodes(".//div/table/tr/td[2]/table/tr[5]/td/a") select HtmlEntity.DeEntitize(Node.InnerText)).ToList(); List <String> Artists = (from Node in MangaNode.SelectNodes(".//div/table/tr/td[2]/table/tr[6]/td/a") select HtmlEntity.DeEntitize(Node.InnerText)).ToList(); List <String> Genres = (from Node in MangaNode.SelectNodes(".//div/table/tr/td[2]/table/tr[7]/td/a") select HtmlEntity.DeEntitize(Node.InnerText)).ToList(); // Detect type MangaObjectType MangaType = MangaObjectType.Unknown; String mType = MangaNode.SelectSingleNode(".//div/table/tr/td[2]/table/tr[8]/td").InnerText.ToLower(); if (mType.Contains("japanese manga")) { MangaType = MangaObjectType.Manga; } else if (mType.Contains("korean manhwa")) { MangaType = MangaObjectType.Manhwa; } // Get description String Description = HtmlEntity.DeEntitize(MangaNode.SelectSingleNode(".//div/p").InnerText); // Chapters List <ChapterObject> Chapters = new List <ChapterObject>(); foreach (HtmlNode ChapterVersionNode in MangaNode.SelectNodes(".//*[@id='list']/div[starts-with(@id, 'stream_')]")) { foreach (HtmlNode VolumeNode in ChapterVersionNode.SelectNodes(".//div[contains(@class, 'volume')]")) { UInt32 Volume = 0; HtmlNode VolumeNameNode = VolumeNode.SelectSingleNode(".//h4"); if (!Equals(VolumeNameNode, null)) { String[] idParts = VolumeNameNode.GetAttributeValue("id", "v-1-").Split('-'); UInt32.TryParse(idParts[2], out Volume); } foreach (HtmlNode ChapterNode in ChapterVersionNode.SelectNodes(".//div/ul/li")) { HtmlNode InfoNode = ChapterNode.SelectSingleNode(".//a"); String ChapterName = HtmlEntity.DeEntitize(InfoNode.InnerText), Url = InfoNode.GetAttributeValue("href", null); UInt32 Chapter = 0, SubChapter = 0; Match match = Regex.Match(ChapterName, @"(vol\.(?<Volume>\d+)\s)?ch\.(?<Chapter>\d+)(\.(?<SubChapter>\d+))?"); if (match.Success) { if (match.Groups["Volume"].Success) { UInt32.TryParse(match.Groups["Volume"].Value, out Volume); } if (match.Groups["Chapter"].Success) { UInt32.TryParse(match.Groups["Chapter"].Value, out Chapter); } if (match.Groups["SubChapter"].Success) { UInt32.TryParse(match.Groups["SubChapter"].Value, out SubChapter); } } if (Equals(Url, null)) { continue; } Url = String.Format("{0}{1}", ExtensionDescriptionAttribute.RootUrl, Url); ChapterObject NewChapterObject = new ChapterObject() { Name = ChapterName, Volume = Volume, Chapter = Chapter, SubChapter = SubChapter, Locations = { new LocationObject() { Enabled = true, ExtensionName = ExtensionDescriptionAttribute.Name, ExtensionLanguage = ExtensionDescriptionAttribute.Language, Url = Url } } }; ChapterObject ExistingChapterObject = Chapters.FirstOrDefault(o => { if (!Int32.Equals(o.Chapter, NewChapterObject.Chapter)) { return(false); } if (!Int32.Equals(o.SubChapter, NewChapterObject.SubChapter)) { return(false); } return(true); }); if (Equals(ExistingChapterObject, null)) { Chapters.Add(NewChapterObject); } else { ExistingChapterObject.Merge(NewChapterObject); } } } } Chapters = Chapters.OrderBy(c => c.Chapter).ThenBy(c => c.SubChapter).ThenBy(c => c.Volume).ToList(); return(new MangaObject() { Name = Name, AlternateNames = AlternateNames, Description = Description, Authors = Authors, Artists = Artists, Genres = Genres, MangaType = MangaType, Chapters = Chapters }); }