HtmlAgilityPack & Selenium Webdriver가 임의의 결과를 반환합니다.

c# html-agility-pack selenium-webdriver web-crawler web-scraping

문제

나는 웹 사이트에서 제품 이름을 긁어 내려고하고있다. 이상하게도, 난 무작위로 12 항목을 긁어 모으는 것 같습니다. 나는 HtmlAgilityPack과 HTTPClient를 모두 시험해 보았고 동일한 랜덤 결과를 얻었다. HtmlAgilityPack에 대한 내 코드는 다음과 같습니다.

using HtmlAgilityPack;
using System.Net.Http;

var url = @"http://www.roots.com/ca/en/men/tops/shirts-and-polos/";
HtmlWeb web = new HtmlWeb();
var doc = web.Load(url, "GET", proxy, new NetworkCredential(PROXY_UID, PROXY_PWD, PROXY_DMN));
var nodes = doc.DocumentNode.Descendants("div")
            .Where(div => div.GetAttributeValue("class", string.Empty) == "product-name")
            .Select(div => div.InnerText.Trim())
            ;

[업데이트 1] @ 코딩 Kuma 제안 셀레늄 Webdriver. 다음은 Selenium Webdriver를 사용하는 코드입니다.

IWebDriver chromeDriver = new ChromeDriver(@"C:\TEMP\Projects\Chrome\chromedriver_win32");
chromeDriver.Url = "http://www.roots.com/ca/en/men/tops/shirts-and-polos/";
var items = chromeDriver.FindElements(By.ClassName("product-name"));
items.Count().Dump();
chromeDriver.Quit();

나는이 코드를 시도했지만 여전히 운이 없다. 해당 페이지에는 20 개가 넘는 항목이 있지만 무작위로만 나타납니다. 12. 해당 사이트의 모든 항목을 어떻게 긁을 수 있습니까?

전문가 답변

v1.5.0-beta92 이후,

HtmlAgilityPack에는 원하는 모든 요소가 준비 될 때까지 기다릴 수있는 FromBrowser 메서드가 있습니다.

문서 : http://html-agility-pack.net/from-browser

string url = "http://html-agility-pack/from-browser";

var web1 = new HtmlWeb();
var doc1 = web1.LoadFromBrowser(url, o =>
{
    var webBrowser = (WebBrowser) o;

    // WAIT until the dynamic text is set
    return !string.IsNullOrEmpty(webBrowser.Document.GetElementById("uiDynamicText").InnerText);
});
var t1 = doc1.DocumentNode.SelectSingleNode("//div[@id='uiDynamicText']").InnerText

var web2 = new HtmlWeb();
var doc2 = web2.LoadFromBrowser(url, html =>
{
    // WAIT until the dynamic text is set
    return !html.Contains("<div id=\"uiDynamicText\"></div>");
});
var t2 = doc2.DocumentNode.SelectSingleNode("//div[@id='uiDynamicText']").InnerText

Console.WriteLine("Text 1: " + t1);
Console.WriteLine("Text 2: " + t2);

여기서 트릭은 라이브러리가 알 수 없기 때문에 페이지가 준비되면 알려주는 것을 찾는 것입니다.


인기 답변

카운트가 정확하지 못하게하는 몇 가지 문제가 있습니다.

  1. 페이지에 게으른 로더가 있습니다. 12 개가 넘는 항목의로드를 트리거하려면 아래로 스크롤해야합니다.

  2. 이 페이지는 AJAX 호출을 사용하여 12 개가 넘는 항목을로드합니다.

따라서 페이지로 이동하고 페이지 하단으로 스크롤 한 다음 AJAX가 완료 될 때까지 기다린 다음 페이지를 긁어 내야합니다. 아래 코드는 테스트를 거쳐 20 개의 항목을 반환합니다.

스크립트

String url = "http://www.roots.com/ca/en/men/tops/shirts-and-polos/";
driver.navigate().to(url);
JavascriptExecutor js = ((JavascriptExecutor) driver);
int height = 1;
int lastHeight = 0;
while (lastHeight != height)
{
    lastHeight = height;
    js.executeScript("window.scrollTo(0, document.body.scrollHeight);");
    height = (int) (long) js.executeScript("return document.body.scrollHeight;");
}

waitForJSandJQueryToLoad(10);

List<WebElement> products = driver.findElements(By.cssSelector("div.product-name"));
System.out.println(products.size());
for (WebElement e : products)
{
    System.out.println(e.getText());
}

지원 기능

public boolean waitForJSandJQueryToLoad(int timeOut)
{
    WebDriverWait wait = new WebDriverWait(driver, timeOut);

    ExpectedCondition<Boolean> jQueryIsLoaded = new ExpectedCondition<Boolean>()
    {
        @Override
        public Boolean apply(WebDriver driver)
        {
            return (Boolean) ((JavascriptExecutor) driver).executeScript("return (window.jQuery != null) && (jQuery.active === 0);");
        }
    };

    ExpectedCondition<Boolean> jsIsLoaded = new ExpectedCondition<Boolean>()
    {
        @Override
        public Boolean apply(WebDriver driver)
        {
            return (Boolean) ((JavascriptExecutor) driver).executeScript("return document.readyState == 'complete'");
        }
    };

    return wait.until(jQueryIsLoaded) && wait.until(jsIsLoaded);
}

산출

20
Rideau Flannel Shirt
Westridge Denim Shirt
Rideau Flannel Shirt
Riverside Plaid Shirt
Riverside Plaid Shirt
Heritage Peppered Polo
Heritage Peppered Polo
Heritage Peppered Polo
Cedar Jersey Polo
Cedar Jersey Polo
Hope River Shirt
Hawthorne Surplus Shacket
Acadian Linen Shirt
Camp Short Sleeve Shirt
Foxley Short Sleeve Shirt
Heritage Peppered Polo
Foxley Short Sleeve Shirt
Waterway Indigo Shirt
Waterway Indigo Shirt
Resolute Flannel Shirt


아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.