Updated scanner tests to work with user english locale pages.
This commit is contained in:
@@ -13,7 +13,8 @@ public class DLSiteHtmlDocument
|
|||||||
public DLSiteHtmlDocument(HtmlDocument document)
|
public DLSiteHtmlDocument(HtmlDocument document)
|
||||||
{
|
{
|
||||||
_workColumns = document.DocumentNode.SelectNodes("//dl[@class='work_1col']");
|
_workColumns = document.DocumentNode.SelectNodes("//dl[@class='work_1col']");
|
||||||
_workColumnRights = document.DocumentNode.SelectNodes("//td[@class='work_1col_right']");
|
//_workColumnRights = document.DocumentNode.SelectNodes("//td[@class='work_1col_right']");
|
||||||
|
_workColumnRights = document.DocumentNode.SelectNodes("//td[contains(@class, 'work_1col_right')]");
|
||||||
_workThumbs = document.DocumentNode.SelectNodes("//div[@class='work_thumb']");
|
_workThumbs = document.DocumentNode.SelectNodes("//div[@class='work_thumb']");
|
||||||
|
|
||||||
PageTotalNode = document.DocumentNode.SelectNodes("//div[@class='page_total']/strong")[0];
|
PageTotalNode = document.DocumentNode.SelectNodes("//div[@class='page_total']/strong")[0];
|
||||||
|
|||||||
@@ -11,17 +11,18 @@ public class DLSiteHtmlNode
|
|||||||
public HtmlNode ProductNode { get; private set; }
|
public HtmlNode ProductNode { get; private set; }
|
||||||
public HtmlNode ProductLinkNode { get; private set; }
|
public HtmlNode ProductLinkNode { get; private set; }
|
||||||
public HtmlNode ProductTextNode { get; private set; }
|
public HtmlNode ProductTextNode { get; private set; }
|
||||||
public HtmlNode DescriptionNode { get; private set; }
|
public HtmlNode? DescriptionNode { get; private set; }
|
||||||
public HtmlNode MakerNode { get; private set; }
|
public HtmlNode MakerNode { get; private set; }
|
||||||
public HtmlNode MakerLinkNode { get; private set; }
|
public HtmlNode MakerLinkNode { get; private set; }
|
||||||
public HtmlNode SalesDateNode { get; private set; }
|
public HtmlNode? ExpectedDateNode { get; private set; }
|
||||||
public HtmlNode ExpectedDateNode { get; private set; }
|
public HtmlNode? WorkInfoBox { get; private set; }
|
||||||
|
public HtmlNode? SalesDateNode { get; private set; }
|
||||||
public HtmlNode DownloadsNode { get; private set; }
|
public HtmlNode DownloadsNode { get; private set; }
|
||||||
public HtmlNode StarRatingNode { get; private set; }
|
public HtmlNode? StarRatingNode { get; private set; }
|
||||||
public HtmlNode ImageNode { get; private set; }
|
public HtmlNode ImageNode { get; private set; }
|
||||||
public List<HtmlNode> GenreNodes { get; private set; }
|
public HtmlNode[] GenreNodes { get; private set; }
|
||||||
public List<HtmlNode> SearchTagNodes { get; private set; }
|
public HtmlNode[] SearchTagNodes { get; private set; }
|
||||||
public List<HtmlNode> CreatorNodes { get; private set; }
|
public HtmlNode[] CreatorNodes { get; private set; }
|
||||||
|
|
||||||
public DLSiteHtmlNode(HtmlNode leftNode, HtmlNode rightNode, HtmlNode thumbNode)
|
public DLSiteHtmlNode(HtmlNode leftNode, HtmlNode rightNode, HtmlNode thumbNode)
|
||||||
{
|
{
|
||||||
@@ -33,35 +34,44 @@ public class DLSiteHtmlNode
|
|||||||
ProductLinkNode = ProductNode.SelectNodes(".//a")[0];
|
ProductLinkNode = ProductNode.SelectNodes(".//a")[0];
|
||||||
ProductTextNode = GetProductTextNode();
|
ProductTextNode = GetProductTextNode();
|
||||||
|
|
||||||
DescriptionNode = LeftNode.SelectNodes(".//dd[@class='work_text']")[0];
|
//DescriptionNode = LeftNode.SelectNodes(".//dd[@class='work_text']")[0];
|
||||||
|
DescriptionNode = LeftNode.SelectNodes(".//dd[@class='work_text']")?.FirstOrDefault();
|
||||||
|
|
||||||
MakerNode = LeftNode.SelectNodes(".//dd[@class='maker_name']")[0];
|
MakerNode = LeftNode.SelectNodes(".//dd[@class='maker_name']")[0];
|
||||||
MakerLinkNode = MakerNode.SelectNodes(".//a[contains(@href, 'maker_id')]")[0];
|
MakerLinkNode = MakerNode.SelectNodes(".//a[contains(@href, 'maker_id')]")[0];
|
||||||
|
|
||||||
ExpectedDateNode = GetExpectedDateNode();
|
//ExpectedDateNode = GetExpectedDateNode();
|
||||||
|
ExpectedDateNode = ProductNode.SelectNodes(".//p[@class='expected_date']")?.FirstOrDefault();
|
||||||
|
|
||||||
InitializeGenreNodes();
|
GenreNodes = GetGenreNodes();
|
||||||
InitializeSearchTagNodes();
|
SearchTagNodes = GetSearchTagNodes();
|
||||||
InitializeCreatorNodes();
|
CreatorNodes = GetCreatorNodes();
|
||||||
InitializeSalesAndDownloadsNodes();
|
WorkInfoBox = RightNode.SelectNodes(".//ul[@class='work_info_box']")?.FirstOrDefault();
|
||||||
InitializeStarRatingNode();
|
SalesDateNode = WorkInfoBox?.SelectNodes(".//li[@class='sales_date']")?.FirstOrDefault();
|
||||||
InitializeImageNode();
|
|
||||||
|
// TODO: Fix!
|
||||||
|
//DownloadsNode = RightNode.SelectSingleNode(".//span[@class='_dl_count_" + works[rightsIndex].ProductId + "']");
|
||||||
|
DownloadsNode = RightNode.SelectSingleNode(".//span[contains(@class, '_dl_count_')]");
|
||||||
|
|
||||||
|
//InitializeSalesAndDownloadsNodes();
|
||||||
|
StarRatingNode = GetStarRatingNode();
|
||||||
|
ImageNode = GetImageNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeGenreNodes()
|
private HtmlNode[] GetGenreNodes()
|
||||||
{
|
{
|
||||||
HtmlNode genreNode = LeftNode.SelectNodes(".//dd[@class='work_genre']")[0];
|
HtmlNode genreNode = LeftNode.SelectNodes(".//dd[@class='work_genre']")[0];
|
||||||
|
|
||||||
GenreNodes = [.. genreNode.SelectNodes(".//span")];
|
return [.. genreNode.SelectNodes(".//span")];
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeSearchTagNodes()
|
private HtmlNode[] GetSearchTagNodes()
|
||||||
{
|
{
|
||||||
HtmlNodeCollection searchTagNodes = LeftNode.SelectNodes(".//dd[@class='search_tag']");
|
HtmlNodeCollection searchTagNodes = LeftNode.SelectNodes(".//dd[@class='search_tag']");
|
||||||
|
|
||||||
if (searchTagNodes == null || searchTagNodes.Count == 0)
|
if (searchTagNodes == null || searchTagNodes.Count == 0)
|
||||||
{
|
{
|
||||||
SearchTagNodes = [];
|
return [];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -69,56 +79,64 @@ public class DLSiteHtmlNode
|
|||||||
|
|
||||||
if (searchTagNodesLinks == null || searchTagNodesLinks.Count == 0)
|
if (searchTagNodesLinks == null || searchTagNodesLinks.Count == 0)
|
||||||
{
|
{
|
||||||
SearchTagNodes = [];
|
return [];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SearchTagNodes = [.. searchTagNodesLinks];
|
return [.. searchTagNodesLinks];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeCreatorNodes()
|
private HtmlNode[] GetCreatorNodes()
|
||||||
{
|
{
|
||||||
HtmlNodeCollection creatorNodes = MakerNode.SelectNodes(".//a[contains(@href, 'keyword_creater')]");
|
HtmlNodeCollection creatorNodes = MakerNode.SelectNodes(".//a[contains(@href, 'keyword_creater')]");
|
||||||
|
|
||||||
if (creatorNodes == null || creatorNodes.Count == 0)
|
if (creatorNodes == null || creatorNodes.Count == 0)
|
||||||
{
|
{
|
||||||
CreatorNodes = [];
|
return [];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CreatorNodes = [.. creatorNodes];
|
return [.. creatorNodes];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeSalesAndDownloadsNodes()
|
//private void InitializeSalesAndDownloadsNodes()
|
||||||
{
|
//{
|
||||||
HtmlNodeCollection workInfoBox = RightNode.SelectNodes(".//ul[@class='work_info_box']");
|
// HtmlNodeCollection workInfoBox = RightNode.SelectNodes(".//ul[@class='work_info_box']");
|
||||||
|
|
||||||
if (workInfoBox != null)
|
// if (workInfoBox != null)
|
||||||
{
|
// {
|
||||||
HtmlNodeCollection salesDateNodes = workInfoBox[0].SelectNodes(".//li[@class='sales_date']");
|
// HtmlNodeCollection salesDateNodes = workInfoBox[0].SelectNodes(".//li[@class='sales_date']");
|
||||||
|
|
||||||
if (salesDateNodes != null && salesDateNodes.Count > 0)
|
// if (salesDateNodes != null && salesDateNodes.Count > 0)
|
||||||
{
|
// {
|
||||||
SalesDateNode = salesDateNodes[0];
|
// SalesDateNode = salesDateNodes[0];
|
||||||
}
|
// }
|
||||||
|
|
||||||
// TODO: Fix!
|
// // TODO: Fix!
|
||||||
//DownloadsNode = RightNode.SelectSingleNode(".//span[@class='_dl_count_" + works[rightsIndex].ProductId + "']");
|
// //DownloadsNode = RightNode.SelectSingleNode(".//span[@class='_dl_count_" + works[rightsIndex].ProductId + "']");
|
||||||
DownloadsNode = RightNode.SelectSingleNode(".//span[contains(@class, '_dl_count_')]");
|
// DownloadsNode = RightNode.SelectSingleNode(".//span[contains(@class, '_dl_count_')]");
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
private void InitializeStarRatingNode()
|
//private HtmlNode? GetSalesDateNode()
|
||||||
|
//{
|
||||||
|
// if (WorkInfoBox is null)
|
||||||
|
// return null;
|
||||||
|
|
||||||
|
// return WorkInfoBox.SelectNodes(".//li[@class='sales_date']").FirstOrDefault();
|
||||||
|
//}
|
||||||
|
|
||||||
|
private HtmlNode? GetStarRatingNode()
|
||||||
{
|
{
|
||||||
var ratingsNode = RightNode.SelectSingleNode(".//li[@class='work_rating']");
|
var ratingsNode = RightNode.SelectSingleNode(".//li[@class='work_rating']");
|
||||||
|
|
||||||
if (ratingsNode == null)
|
if (ratingsNode == null)
|
||||||
return;
|
return null;
|
||||||
|
|
||||||
StarRatingNode = ratingsNode.SelectSingleNode(".//div[contains(@class, 'star_rating')]");
|
return ratingsNode.SelectSingleNode(".//div[contains(@class, 'star_rating')]");
|
||||||
}
|
}
|
||||||
|
|
||||||
private HtmlNode GetProductTextNode()
|
private HtmlNode GetProductTextNode()
|
||||||
@@ -133,24 +151,24 @@ public class DLSiteHtmlNode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HtmlNode GetExpectedDateNode()
|
//private HtmlNode? GetExpectedDateNode()
|
||||||
{
|
//{
|
||||||
HtmlNodeCollection expectedDateNodes = ProductNode.SelectNodes(".//p[@class='expected_date']");
|
// HtmlNodeCollection expectedDateNodes = ProductNode.SelectNodes(".//p[@class='expected_date']").FirstOrDefault();
|
||||||
|
|
||||||
if (expectedDateNodes != null && expectedDateNodes.Count > 0)
|
// if (expectedDateNodes != null && expectedDateNodes.Count > 0)
|
||||||
{
|
// {
|
||||||
return expectedDateNodes[0];
|
// return expectedDateNodes[0];
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
private void InitializeImageNode()
|
private HtmlNode GetImageNode()
|
||||||
{
|
{
|
||||||
HtmlNode linkNode = ThumbNode.SelectNodes(".//a")[0];
|
HtmlNode linkNode = ThumbNode.SelectNodes(".//a")[0];
|
||||||
|
|
||||||
ImageNode = linkNode.SelectNodes(".//img")[0];
|
return linkNode.SelectNodes(".//img")[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ namespace JSMR.Infrastructure.Scanning;
|
|||||||
|
|
||||||
public static class ScannerUtilities
|
public static class ScannerUtilities
|
||||||
{
|
{
|
||||||
public static List<string> GetStringListFromNodes(List<HtmlNode> nodes)
|
public static List<string> GetStringListFromNodes(HtmlNode[] nodes)
|
||||||
{
|
{
|
||||||
return nodes
|
return nodes
|
||||||
.Where(node => string.IsNullOrEmpty(node.InnerHtml) == false)
|
.Where(node => string.IsNullOrEmpty(node.InnerHtml) == false)
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ public abstract class VoiceWorksScanner(IHtmlLoader htmlLoader) : IVoiceWorksSca
|
|||||||
return work;
|
return work;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AgeRating GetAgeRating(List<HtmlNode> genreNodes)
|
private static AgeRating GetAgeRating(HtmlNode[] genreNodes)
|
||||||
{
|
{
|
||||||
List<string> genres = ScannerUtilities.GetStringListFromNodes(genreNodes);
|
List<string> genres = ScannerUtilities.GetStringListFromNodes(genreNodes);
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ public class DLSiteClientTests
|
|||||||
result["RJ01230163"].HasTrial.ShouldBeTrue();
|
result["RJ01230163"].HasTrial.ShouldBeTrue();
|
||||||
result["RJ01230163"].HasDLPlay.ShouldBeTrue();
|
result["RJ01230163"].HasDLPlay.ShouldBeTrue();
|
||||||
result["RJ01230163"].HasReviews.ShouldBeTrue();
|
result["RJ01230163"].HasReviews.ShouldBeTrue();
|
||||||
result["RJ01230163"].SupportedLanguages.ShouldBe([Language.English]);
|
result["RJ01230163"].SupportedLanguages.Length.ShouldBe(1);
|
||||||
|
result["RJ01230163"].SupportedLanguages.Select(x => x.Language).ShouldContain(Language.English);
|
||||||
result["RJ01230163"].DownloadCount.ShouldBe(659);
|
result["RJ01230163"].DownloadCount.ShouldBe(659);
|
||||||
result["RJ01230163"].WishlistCount.ShouldBe(380);
|
result["RJ01230163"].WishlistCount.ShouldBe(380);
|
||||||
}
|
}
|
||||||
@@ -71,13 +72,13 @@ public class DLSiteClientTests
|
|||||||
voiceWorkDetails.DownloadCount.ShouldBe(100);
|
voiceWorkDetails.DownloadCount.ShouldBe(100);
|
||||||
voiceWorkDetails.HasTrial.ShouldBe(true);
|
voiceWorkDetails.HasTrial.ShouldBe(true);
|
||||||
voiceWorkDetails.HasDLPlay.ShouldBe(true);
|
voiceWorkDetails.HasDLPlay.ShouldBe(true);
|
||||||
voiceWorkDetails.AI.ShouldBe(Application.Common.AIGeneration.None);
|
voiceWorkDetails.AI.ShouldBe(AIGeneration.None);
|
||||||
|
|
||||||
voiceWorkDetails.Series.ShouldNotBeNull();
|
voiceWorkDetails.Series.ShouldNotBeNull();
|
||||||
voiceWorkDetails.Series.Identifier.ShouldBe("SE0001");
|
voiceWorkDetails.Series.Identifier.ShouldBe("SE0001");
|
||||||
voiceWorkDetails.Series.Name.ShouldBe("Series 1");
|
voiceWorkDetails.Series.Name.ShouldBe("Series 1");
|
||||||
|
|
||||||
voiceWorkDetails.SupportedLanguages.Length.ShouldBe(1);
|
voiceWorkDetails.SupportedLanguages.Length.ShouldBe(1);
|
||||||
voiceWorkDetails.SupportedLanguages[0].ShouldBe(Application.Common.Language.Japanese);
|
voiceWorkDetails.SupportedLanguages[0].Language.ShouldBe(Language.Japanese);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Integrations\DLSite\Product-Info.json" />
|
<EmbeddedResource Include="Integrations\DLSite\Product-Info.json" />
|
||||||
|
<EmbeddedResource Include="Scanning\English-Page-Updated.html" />
|
||||||
|
<EmbeddedResource Include="Scanning\Japanese-Page.html" />
|
||||||
<EmbeddedResource Include="Scanning\English-Page.html" />
|
<EmbeddedResource Include="Scanning\English-Page.html" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
150
JSMR.Tests/Scanning/English-Page-Updated.html
Normal file
150
JSMR.Tests/Scanning/English-Page-Updated.html
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<div data-toggle="found" class="sort_box border_b pb10">
|
||||||
|
<div class="status_select">
|
||||||
|
Reorder :
|
||||||
|
<select name="order" id="query_order" class="_change_submit"><!----><!----><option value="trend">Sort by popularity</option><option value="release_d">Release date - New to Old</option><option value="release">Release date - Old to New</option><option value="dl_d">Best Selling</option><option value="price">Price - Low to High</option><option value="price_d">Price - High to Low</option><option value="rate_d">Rating - High to Low</option><option value="review_d">Reviews - High to Low</option></select>
|
||||||
|
</div>
|
||||||
|
<div class="page_total">
|
||||||
|
<strong>626609</strong>
|
||||||
|
<span> total. Showing: </span>
|
||||||
|
<strong>1~30</strong>
|
||||||
|
</div>
|
||||||
|
<div class="display_type_select">
|
||||||
|
<span>Display :</span>
|
||||||
|
<ul>
|
||||||
|
<li class="on display_normal">
|
||||||
|
<a>1カラム表示</a>
|
||||||
|
</li>
|
||||||
|
<li class="display_block">
|
||||||
|
<a href="#">画像表示</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="display_num_select">
|
||||||
|
<ul>
|
||||||
|
<li class="on">
|
||||||
|
<a>30</a>
|
||||||
|
</li>
|
||||||
|
<li class="">
|
||||||
|
<a href="#">50</a>
|
||||||
|
</li>
|
||||||
|
<li class="">
|
||||||
|
<a href="#">100</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<span>Items per page :</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="search_result_list">
|
||||||
|
<table class="work_1col_table n_worklist">
|
||||||
|
<tbody>
|
||||||
|
<tr data-list_item_product_id="RJ01455722" class="bg_trans ">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="work_1col_thumb is_overseas">
|
||||||
|
<div class="work_thumb">
|
||||||
|
|
||||||
|
<a href="https://www.dlsite.com/maniax/work/=/product_id/RJ01455722.html" id="_link_RJ01455722" class="work_thumb_inner"><img alt="[ENG Sub] Welcome to Soleil! [Translators Unite]" data-src="//img.dlsite.jp/modpub/images2/work/doujin/RJ325000/RJ324248_img_main.jpg" class="lazy" src="//img.dlsite.jp/modpub/images2/work/doujin/RJ325000/RJ324248_img_main.jpg" lazy="loaded"> <div class="work_img_popover"><img src="//img.dlsite.jp/modpub/images2/work/doujin/RJ325000/RJ324248_img_main.jpg" alt="[ENG Sub] Welcome to Soleil! [Translators Unite]"></div></a>
|
||||||
|
|
||||||
|
<div class="work_category type_SOU"><a href="https://www.dlsite.com/maniax/fsr/=/work_type/SOU">Voice / ASMR</a></div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="is_overseas">
|
||||||
|
|
||||||
|
<dl class="work_1col">
|
||||||
|
<dt class="work_name">
|
||||||
|
<span class="period_date">Oct. 30, 13:59 (JST) Discounted for a limited time.</span>
|
||||||
|
|
||||||
|
<div class="icon_wrap">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<a href="https://www.dlsite.com/maniax/work/=/product_id/RJ01455722.html" title="[ENG Sub] Welcome to Soleil!">
|
||||||
|
[ENG Sub] Welcome to Soleil!
|
||||||
|
</a>
|
||||||
|
</dt>
|
||||||
|
|
||||||
|
<dd class="maker_name">
|
||||||
|
<a href="https://www.dlsite.com/maniax/circle/profile/=/maker_id/RG60289.html">Translators Unite</a>
|
||||||
|
|
||||||
|
<span class="separator">/</span>
|
||||||
|
<span class="author"><a href="https://www.dlsite.com/home/fsr/=/keyword_creater/%22%E6%B2%BC%E5%80%89%E6%84%9B%E7%BE%8E%22" class="">沼倉愛美</a></span>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd class="work_price_wrap">
|
||||||
|
|
||||||
|
<span class="work_price ">
|
||||||
|
|
||||||
|
<span class="work_price_parts"><span class="work_price_prefix">$</span> <span class="work_price_base">5.90</span> <span class="work_price_suffix"></span></span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="strike ">
|
||||||
|
|
||||||
|
<span class="work_price_parts"><span class="work_price_prefix">$</span> <span class="work_price_base">13.10</span> <span class="work_price_suffix"></span></span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="icon_campaign type_sale">55%OFF</span>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dd class="work_genre">
|
||||||
|
<span class="icon_GEN" title="All Ages">All Ages</span><span class="icon_TRI" title="Trial version">Trial version</span>
|
||||||
|
<span style="display: none;"></span>
|
||||||
|
|
||||||
|
<input type="hidden" class="__product_attributes" name="__product_attributes" id="_RJ01455722" value="RG60289,male,SOU,SND,DLP,REV,TRI,ENG,497,496,051,056,442,503,008,013" disabled="disabled">
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dd class="search_tag">
|
||||||
|
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/051/from/work.genre">Moe</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/056/from/work.genre">Healing</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/496/from/work.genre">Binaural</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/497/from/work.genre">ASMR</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/442/from/work.genre">Ear Cleaning</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/008/from/work.genre">Slice of Life / Daily Living</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/013/from/work.genre">Heartwarming</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/503/from/work.genre">Whispering</a>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="work_1col_right is_overseas">
|
||||||
|
|
||||||
|
<ul class="work_info_box">
|
||||||
|
<li class="sales_date">Release date: Oct/16/2025</li>
|
||||||
|
<li class="work_dl clear">
|
||||||
|
<div class="_work_dl_RJ01455722">Purchased: <span class="_dl_count_RJ01455722">1</span></div>
|
||||||
|
</li>
|
||||||
|
<li class="work_review clear">
|
||||||
|
</li>
|
||||||
|
<li class="work_rating"><div class="star_rating star_50">(3,420)</div></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="work_btn_box"><div hidden="hidden" class="ga4_event_item_RJ01455722" data-product_id="RJ01455722" data-work_name="[ENG Sub] Welcome to Soleil!" data-maker_id="RG60289" data-work_type="SOU" data-options="SND#DLP#REV#TRI#ENG" data-price="891" data-official_price="1980"></div> <ul class="work_btn_list btn_free_sample"><li class="work_btn_list_item"><p class="work_cart_xs"><a href="/maniax/cart/=/product_id/RJ01455722.html" class="btn_cart disabled">Add to Cart</a></p></li> <li class="work_btn_list_item"><p class="work_favorite_xs"><a href="/maniax/mypage/wishlist/=/product_id/RJ01455722.html" class="btn_favorite disabled">Favorites</a></p></li> <li class="work_btn_list_item"><li><p class="work_free_sample"><a href="#" class="btn_free_sample disabled _sample_none" data-product-id="RJ01455722">Samples</a></p></li></li></ul> <!----></div>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
157
JSMR.Tests/Scanning/Japanese-Page.html
Normal file
157
JSMR.Tests/Scanning/Japanese-Page.html
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<div data-toggle="found" class="sort_box border_b pb10">
|
||||||
|
<div class="status_select">
|
||||||
|
Reorder :
|
||||||
|
<select name="order" id="query_order" class="_change_submit"><!----><!----><option value="trend">Sort by popularity</option><option value="release_d">Release date - New to Old</option><option value="release">Release date - Old to New</option><option value="dl_d">Best Selling</option><option value="price">Price - Low to High</option><option value="price_d">Price - High to Low</option><option value="rate_d">Rating - High to Low</option><option value="review_d">Reviews - High to Low</option></select>
|
||||||
|
</div>
|
||||||
|
<div class="page_total">
|
||||||
|
<strong>626609</strong>
|
||||||
|
<span> total. Showing: </span>
|
||||||
|
<strong>1~30</strong>
|
||||||
|
</div>
|
||||||
|
<div class="display_type_select">
|
||||||
|
<span>Display :</span>
|
||||||
|
<ul>
|
||||||
|
<li class="on display_normal">
|
||||||
|
<a>1カラム表示</a>
|
||||||
|
</li>
|
||||||
|
<li class="display_block">
|
||||||
|
<a href="#">画像表示</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="display_num_select">
|
||||||
|
<ul>
|
||||||
|
<li class="on">
|
||||||
|
<a>30</a>
|
||||||
|
</li>
|
||||||
|
<li class="">
|
||||||
|
<a href="#">50</a>
|
||||||
|
</li>
|
||||||
|
<li class="">
|
||||||
|
<a href="#">100</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<span>Items per page :</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="search_result_list">
|
||||||
|
<table class="work_1col_table n_worklist">
|
||||||
|
<tbody>
|
||||||
|
<!-- RJ00000001 -->
|
||||||
|
<tr data-list_item_product_id="RJ01462066" class=" ">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="work_1col_thumb ">
|
||||||
|
<div class="work_thumb">
|
||||||
|
|
||||||
|
<a href="https://www.dlsite.com/maniax/work/=/product_id/RJ01462066.html" id="_link_RJ01462066" class="work_thumb_inner"><img alt="小悪魔ドSメンズエステ嬢の暴発解禁キワキワ施術 [シルトクレーテ]" data-src="//img.dlsite.jp/resize/images2/work/doujin/RJ01463000/RJ01462066_img_main_240x240.jpg" class="lazy" src="//img.dlsite.jp/resize/images2/work/doujin/RJ01463000/RJ01462066_img_main_240x240.jpg" lazy="loaded"> <div class="work_img_popover"><img src="data:image/gif;base64,R0lGODlhAQABAGAAACH5BAEKAP8ALAAAAAABAAEAAAgEAP8FBAA7" alt="小悪魔ドSメンズエステ嬢の暴発解禁キワキワ施術 [シルトクレーテ]"></div></a>
|
||||||
|
|
||||||
|
<div class="work_category type_SOU"><a href="https://www.dlsite.com/maniax/fsr/=/work_type/SOU">ボイス・ASMR</a></div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="">
|
||||||
|
|
||||||
|
<dl class="work_1col">
|
||||||
|
<dt class="work_name">
|
||||||
|
<span class="period_date">2025年11月11日 23時59分 割引終了</span>
|
||||||
|
|
||||||
|
<div class="icon_wrap">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<span class="icon_lead_01 type_exclusive" title="専売">専売</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<a href="https://www.dlsite.com/maniax/work/=/product_id/RJ01462066.html" title="小悪魔ドSメンズエステ嬢の暴発解禁キワキワ施術">
|
||||||
|
小悪魔ドSメンズエステ嬢の暴発解禁キワキワ施術
|
||||||
|
</a>
|
||||||
|
</dt>
|
||||||
|
|
||||||
|
<dd class="maker_name">
|
||||||
|
<a href="https://www.dlsite.com/maniax/circle/profile/=/maker_id/RG40741.html">シルトクレーテ</a>
|
||||||
|
|
||||||
|
<span class="separator">/</span>
|
||||||
|
<span class="author"><a href="https://www.dlsite.com/maniax/fsr/=/keyword_creater/%22%E6%9F%9A%E6%9C%A8%E3%81%A4%E3%81%B0%E3%82%81%22" class="">柚木つばめ</a></span>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd class="work_price_wrap">
|
||||||
|
|
||||||
|
<span class="work_price ">
|
||||||
|
|
||||||
|
<span class="work_price_parts"><span class="work_price_prefix">$</span> <span class="work_price_base">8.74</span> <span class="work_price_suffix"></span></span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="strike ">
|
||||||
|
|
||||||
|
<span class="work_price_parts"><span class="work_price_prefix">$</span> <span class="work_price_base">10.92</span> <span class="work_price_suffix"></span></span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="icon_campaign type_sale">20%OFF</span>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd class="work_text">リピート指名していたオキニ嬢の在籍店が閉店し途方に暮れていた貴方だったが、ある日彼女の個人SNSで別のお店のリンクを発見する。大慌てで当日夜の予約を確保し、今度こそ抜いてくれないかと淡い期待を胸に駅近くのマンションの一室へ…。</dd>
|
||||||
|
|
||||||
|
<dd class="work_genre">
|
||||||
|
<span class="icon_TRI" title="体験版">体験版</span>
|
||||||
|
<span style="display: none;"></span>
|
||||||
|
|
||||||
|
<input type="hidden" class="__product_attributes" name="__product_attributes" id="_RJ01462066" value="RG40741,adl,male,SOU,JPN,SND,TRI,DLP,REV,496,124,125,122,144,152,523,528" disabled="disabled">
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dd class="search_tag">
|
||||||
|
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/496/from/work.genre">バイノーラル/ダミヘ</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/124/from/work.genre">手コキ</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/125/from/work.genre">足コキ</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/122/from/work.genre">パイズリ</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/144/from/work.genre">言葉責め</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/152/from/work.genre">焦らし</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/523/from/work.genre">乳首責め</a>
|
||||||
|
<a href="https://www.dlsite.com/maniax/fsr/=/genre/528/from/work.genre">本番なし</a>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="work_1col_right ">
|
||||||
|
|
||||||
|
<ul class="work_info_box">
|
||||||
|
<li class="sales_date">販売日: 2025年10月15日</li>
|
||||||
|
<li class="work_dl clear">
|
||||||
|
<div class="_work_dl_RJ01462066">販売数: <span class="_dl_count_RJ01462066">1,220</span></div>
|
||||||
|
</li>
|
||||||
|
<li class="work_review clear">
|
||||||
|
<span class="work_to_review">
|
||||||
|
<div title="レビューあり">
|
||||||
|
<a href="https://www.dlsite.com/maniax/work/reviewlist/=/product_id/RJ01462066.html">(2)</a>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li class="work_rating"><div class="star_rating star_50">(31)</div></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="work_btn_box"><div hidden="hidden" class="ga4_event_item_RJ01462066" data-product_id="RJ01462066" data-work_name="小悪魔ドSメンズエステ嬢の暴発解禁キワキワ施術" data-maker_id="RG40741" data-work_type="SOU" data-options="JPN#SND#TRI#DLP#REV" data-price="1320" data-official_price="1650"></div> <ul class="work_btn_list btn_free_sample"><li class="work_btn_list_item"><p class="work_cart_xs"><a href="/maniax/cart/=/product_id/RJ01462066.html" class="btn_cart">カートに入れる</a></p></li> <li class="work_btn_list_item"><p class="work_favorite_xs"><a href="/maniax/mypage/wishlist/=/product_id/RJ01462066.html" class="btn_favorite">お気に入りに追加</a></p></li> <li class="work_btn_list_item"><li><p class="work_free_sample"><a href="#" class="btn_free_sample" data-product-id="RJ01462066">無料サンプル</a></p></li></li></ul> <!----></div>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -5,7 +5,7 @@ using JSMR.Tests.Utilities;
|
|||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
|
|
||||||
namespace JSMR.Tests.Integrations.DLSite;
|
namespace JSMR.Tests.Scanning;
|
||||||
|
|
||||||
public class VoiceWorkScannerTests
|
public class VoiceWorkScannerTests
|
||||||
{
|
{
|
||||||
@@ -14,6 +14,45 @@ public class VoiceWorkScannerTests
|
|||||||
return await ResourceHelper.ReadAsync($"JSMR.Tests.Scanning.{resourceName}");
|
return await ResourceHelper.ReadAsync($"JSMR.Tests.Scanning.{resourceName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Scan_With_Japanese_Locale()
|
||||||
|
{
|
||||||
|
string html = await ReadResourceAsync("Japanese-Page.html");
|
||||||
|
|
||||||
|
IHttpService httpService = Substitute.For<IHttpService>();
|
||||||
|
|
||||||
|
httpService.GetStringAsync(Arg.Any<string>(), CancellationToken.None)
|
||||||
|
.Returns(Task.FromResult(html));
|
||||||
|
|
||||||
|
HtmlLoader loader = new(httpService);
|
||||||
|
JapaneseVoiceWorksScanner scanner = new(loader);
|
||||||
|
|
||||||
|
VoiceWorkScanOptions options = new(
|
||||||
|
PageNumber: 1,
|
||||||
|
PageSize: 100,
|
||||||
|
ExcludeAIGeneratedWorks: true,
|
||||||
|
ExcludePartiallyAIGeneratedWorks: true,
|
||||||
|
ExcludedMakerIds: []
|
||||||
|
);
|
||||||
|
|
||||||
|
var result = await scanner.ScanPageAsync(options, CancellationToken.None);
|
||||||
|
|
||||||
|
result.Count.ShouldBe(1);
|
||||||
|
|
||||||
|
result[0].ExpectedDate.ShouldBeNull();
|
||||||
|
result[0].SalesDate.ShouldBe(new DateOnly(2025, 10, 15));
|
||||||
|
result[0].ProductId.ShouldBe("RJ01462066");
|
||||||
|
result[0].ProductName.ShouldBe("小悪魔ドSメンズエステ嬢の暴発解禁キワキワ施術");
|
||||||
|
result[0].Description.ShouldBe("リピート指名していたオキニ嬢の在籍店が閉店し途方に暮れていた貴方だったが、ある日彼女の個人SNSで別のお店のリンクを発見する。大慌てで当日夜の予約を確保し、今度こそ抜いてくれないかと淡い期待を胸に駅近くのマンションの一室へ…。");
|
||||||
|
result[0].Maker.ShouldBe("シルトクレーテ");
|
||||||
|
result[0].MakerId.ShouldBe("RG40741");
|
||||||
|
result[0].Creators.ShouldBe(["柚木つばめ"]);
|
||||||
|
result[0].Genres.ShouldBe(["体験版"]);
|
||||||
|
result[0].Tags.ShouldBe(["バイノーラル/ダミヘ", "手コキ", "足コキ", "パイズリ", "言葉責め", "焦らし", "乳首責め", "本番なし"]);
|
||||||
|
result[0].Type.ShouldBe(DLSiteWorkType.Released);
|
||||||
|
result[0].Downloads.ShouldBe(1220);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Scan_With_English_Locale()
|
public async Task Scan_With_English_Locale()
|
||||||
{
|
{
|
||||||
@@ -57,4 +96,43 @@ public class VoiceWorkScannerTests
|
|||||||
result[1].ProductId.ShouldBe("RJ00000002");
|
result[1].ProductId.ShouldBe("RJ00000002");
|
||||||
result[1].Type.ShouldBe(DLSiteWorkType.Announced);
|
result[1].Type.ShouldBe(DLSiteWorkType.Announced);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Scan_With_Updated_English_Locale()
|
||||||
|
{
|
||||||
|
string html = await ReadResourceAsync("English-Page-Updated.html");
|
||||||
|
|
||||||
|
IHttpService httpService = Substitute.For<IHttpService>();
|
||||||
|
|
||||||
|
httpService.GetStringAsync(Arg.Any<string>(), CancellationToken.None)
|
||||||
|
.Returns(Task.FromResult(html));
|
||||||
|
|
||||||
|
HtmlLoader loader = new(httpService);
|
||||||
|
EnglishVoiceWorksScanner scanner = new(loader);
|
||||||
|
|
||||||
|
VoiceWorkScanOptions options = new(
|
||||||
|
PageNumber: 1,
|
||||||
|
PageSize: 100,
|
||||||
|
ExcludeAIGeneratedWorks: true,
|
||||||
|
ExcludePartiallyAIGeneratedWorks: true,
|
||||||
|
ExcludedMakerIds: []
|
||||||
|
);
|
||||||
|
|
||||||
|
var result = await scanner.ScanPageAsync(options, CancellationToken.None);
|
||||||
|
|
||||||
|
result.Count.ShouldBe(1);
|
||||||
|
|
||||||
|
result[0].ExpectedDate.ShouldBeNull();
|
||||||
|
result[0].SalesDate.ShouldBe(new DateOnly(2025, 10, 16));
|
||||||
|
result[0].ProductId.ShouldBe("RJ01455722");
|
||||||
|
result[0].ProductName.ShouldBe("[ENG Sub] Welcome to Soleil!");
|
||||||
|
result[0].Description.ShouldBe(string.Empty); // Waiting on this to get fixed on the site
|
||||||
|
result[0].Maker.ShouldBe("Translators Unite");
|
||||||
|
result[0].MakerId.ShouldBe("RG60289");
|
||||||
|
result[0].Creators.ShouldBe(["沼倉愛美"]);
|
||||||
|
result[0].Genres.ShouldBe(["All Ages", "Trial version"]);
|
||||||
|
result[0].Tags.ShouldBe(["Moe", "Healing", "Binaural", "ASMR", "Ear Cleaning", "Slice of Life / Daily Living", "Heartwarming", "Whispering"]);
|
||||||
|
result[0].Type.ShouldBe(DLSiteWorkType.Released);
|
||||||
|
result[0].Downloads.ShouldBe(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user