使用 HttpAgilityPack 抓取产品页面 - 未获取所有产品
Scraping product page with HttpAgilityPack - Not getting all products
上下文:
我正在用 C# 开发一个桌面应用程序,用于从少数域中的各个网页中抓取/分析产品信息。我使用 HtmlAgilityPack 来捕获和解析页面以获取所需的数据。我为不同的域编写不同的解析规则。
问题:
来自一个特定域的页面在通过浏览器显示时可能会显示 60-80 种产品。但是,当我通过 HtmlAgilityPack 进行解析时,我最多只能获得 20 个产品。查看 Firefox "View Page Source" 中的原始 html,似乎也只有 20 个相关产品 div 存在。我的结论是,其余产品必须通过脚本加载,也许是为了减轻服务器上的负载。事实上,我有时可以在浏览器中看到这种情况,因为在加载 20 个以上的产品时会有短暂的停顿,然后再加载 20 个等等。
问题:
在所有脚本编写完成后,如何通过 HtmlAgilityPack 或其他方式访问完整的产品 div 集?
您可以使用 System.Windows.Forms
中的 WebBrowser
来加载数据,并使用 agility pack 来解析它。它看起来像这样:
var browser = new WebBrowser();
browser.Navigate("http://whatever.com");
while (true)
{
if(browser.ReadyState == WebBrowserReadyState.Complete && browser.IsBusy != true)
{
break;
}
//not for production
Thread.Sleep(1000)
}
var doc = new HtmlAgilityPack.HtmlDocument();
var dom = (IHTMLDocument3)browser.Document.DomDocument;
StringReader reader = new StringReader(dom.documentElement.outerHTML);
doc.Load(reader);
有关详细信息,请参阅 here
好的,我已经使用 Selenium 包(可通过 NuGet 获得)进行一些工作。代码如下所示:
private HtmlDocument FetchPageWithSelenium(string url)
{
IWebDriver driver = new FirefoxDriver();
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
driver.Navigate().GoToUrl(url);
// Scroll to the bottom of the page and pause for more products to load.
// Do it four times as there may be 4x20 products to retrieve.
js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight);");
Thread.Sleep(2000);
js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight);");
Thread.Sleep(2000);
js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight);");
Thread.Sleep(2000);
js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight);");
HtmlDocument webPage = new HtmlDocument();
webPage.LoadHtml(driver.PageSource.ToString());
driver.Quit();
return webPage;
}
此 returns 一个 HtmlAgilityPack HtmlDocument 准备好进行进一步分析,首先通过反复滚动到底部强制页面完全加载。两个未解决的问题:
- 代码启动 Firefox,然后在完成后再次停止。这有点笨拙,我宁愿所有这些都发生在无形中。建议您可以通过使用 PhantomJS 驱动程序而不是 Firefox 驱动程序来避免这种情况。这并没有帮助,因为它只是弹出一个 Windows 控制台 window。
- 由于加载浏览器和脚本加载补充内容时暂停所花费的时间,它有点慢。不过我可能可以忍受。
我将尝试重新编写 @swestner 代码以在 WPF 应用程序中获取它 运行 并查看哪个是更简洁的解决方案。
上下文:
我正在用 C# 开发一个桌面应用程序,用于从少数域中的各个网页中抓取/分析产品信息。我使用 HtmlAgilityPack 来捕获和解析页面以获取所需的数据。我为不同的域编写不同的解析规则。
问题:
来自一个特定域的页面在通过浏览器显示时可能会显示 60-80 种产品。但是,当我通过 HtmlAgilityPack 进行解析时,我最多只能获得 20 个产品。查看 Firefox "View Page Source" 中的原始 html,似乎也只有 20 个相关产品 div 存在。我的结论是,其余产品必须通过脚本加载,也许是为了减轻服务器上的负载。事实上,我有时可以在浏览器中看到这种情况,因为在加载 20 个以上的产品时会有短暂的停顿,然后再加载 20 个等等。
问题:
在所有脚本编写完成后,如何通过 HtmlAgilityPack 或其他方式访问完整的产品 div 集?
您可以使用 System.Windows.Forms
中的 WebBrowser
来加载数据,并使用 agility pack 来解析它。它看起来像这样:
var browser = new WebBrowser();
browser.Navigate("http://whatever.com");
while (true)
{
if(browser.ReadyState == WebBrowserReadyState.Complete && browser.IsBusy != true)
{
break;
}
//not for production
Thread.Sleep(1000)
}
var doc = new HtmlAgilityPack.HtmlDocument();
var dom = (IHTMLDocument3)browser.Document.DomDocument;
StringReader reader = new StringReader(dom.documentElement.outerHTML);
doc.Load(reader);
有关详细信息,请参阅 here
好的,我已经使用 Selenium 包(可通过 NuGet 获得)进行一些工作。代码如下所示:
private HtmlDocument FetchPageWithSelenium(string url)
{
IWebDriver driver = new FirefoxDriver();
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
driver.Navigate().GoToUrl(url);
// Scroll to the bottom of the page and pause for more products to load.
// Do it four times as there may be 4x20 products to retrieve.
js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight);");
Thread.Sleep(2000);
js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight);");
Thread.Sleep(2000);
js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight);");
Thread.Sleep(2000);
js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight);");
HtmlDocument webPage = new HtmlDocument();
webPage.LoadHtml(driver.PageSource.ToString());
driver.Quit();
return webPage;
}
此 returns 一个 HtmlAgilityPack HtmlDocument 准备好进行进一步分析,首先通过反复滚动到底部强制页面完全加载。两个未解决的问题:
- 代码启动 Firefox,然后在完成后再次停止。这有点笨拙,我宁愿所有这些都发生在无形中。建议您可以通过使用 PhantomJS 驱动程序而不是 Firefox 驱动程序来避免这种情况。这并没有帮助,因为它只是弹出一个 Windows 控制台 window。
- 由于加载浏览器和脚本加载补充内容时暂停所花费的时间,它有点慢。不过我可能可以忍受。
我将尝试重新编写 @swestner 代码以在 WPF 应用程序中获取它 运行 并查看哪个是更简洁的解决方案。