Ich versuche, Produktnamen von einer Website zu entfernen. Seltsamerweise schiebe ich nur zufällig 12 Gegenstände. Ich habe sowohl HtmlAgilityPack als auch HTTPClient ausprobiert und bekomme die gleichen zufälligen Ergebnisse. Hier ist mein Code für 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())
;
[UPDATE 1] @CodingKuma schlug vor, Selenium Webdriver zu versuchen. Hier ist mein Code mit 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();
Ich habe diesen Code ausprobiert, aber immer noch kein Glück. Es gibt über 20 Elemente auf dieser Seite, aber ich scheine nur eine zufällige 12. Wie kann ich alle Elemente auf dieser Website kratzen?
Seit der v1.5.0-beta92
HtmlAgilityPack verfügt über eine FromBrowser
Methode, mit der Sie warten können, bis alle gewünschten Elemente fertig sind.
Dokumentation: 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);
Der Trick dabei ist, etwas zu finden, das Ihnen sagt, wann die Seite fertig ist, da die Bibliothek es unmöglich weiß.
Es gibt also einige Probleme, die verhindern, dass die Zählung korrekt ist.
Die Seite hat einen Lazy Loader. Sie müssen nach unten scrollen, um die Ladung der Gegenstände über 12 auszulösen.
Die Seite verwendet AJAX-Aufrufe, um die Elemente über 12 zu laden.
Sie müssen also zur Seite navigieren, zum Ende der Seite blättern, auf die Fertigstellung von AJAX warten und dann die Seite scrappen. Der folgende Code ist getestet und gibt 20 Elemente zurück.
Das Skript
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());
}
Unterstützungsfunktion
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);
}
Ausgabe
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