我一直遇到Html Agility Pack的問題;我的XPath查詢只有在非常簡單時才能工作:
//*[@id='some_id']
要么
//input
但是,只要它們變得更複雜,那麼Html Agility Pack就無法處理它。這是一個演示問題的示例,我使用WebDriver導航到Google,並返回頁面源,傳遞給Html Agility Pack,WebDriver和HtmlAgilityPack都嘗試定位元素/節點(C#):
//The XPath query
const string xpath = "//form//tr[1]/td[1]//input[@name='q']";
//Navigate to Google and get page source
var driver = new FirefoxDriver(new FirefoxProfile()) { Url = "http://www.google.com" };
Thread.Sleep(2000);
//Can WebDriver find it?
var e = driver.FindElementByXPath(xpath);
Console.WriteLine(e!=null ? "Webdriver success" : "Webdriver failure");
//Can Html Agility Pack find it?
var source = driver.PageSource;
var htmlDoc = new HtmlDocument { OptionFixNestedTags = true };
htmlDoc.LoadHtml(source);
var nodes = htmlDoc.DocumentNode.SelectNodes(xpath);
Console.WriteLine(nodes!=null ? "Html Agility Pack success" : "Html Agility Pack failure");
driver.Quit();
在這種情況下,WebDriver成功找到了該項目,但Html Agility Pack沒有。
我知道,我知道,在這種情況下,很容易將xpath更改為可以工作的路徑: //輸入[@ name ='q'] ,但這只會修復這個特定的例子,這不是重點,我需要能夠完全或至少密切反映WebDriver的xpath引擎,甚至Firefox的FirePath或FireFinder附加組件的行為。
如果WebDriver可以找到它,那麼為什麼Html Agility Pack也找不到呢?
您遇到的問題是FORM元素。 HTML Agility Pack 以不同的方式處理該元素 - 默認情況下,它永遠不會報告它有子元素 。
在您給出的特定示例中,此查詢確實找到了目標元素:
.//div/div[2]/table/tr/td/table/tr/td/div/table/tr/td/div/div[2]/input
但是,這不是,所以很明顯表單元素會使解析器癱瘓:
.//form/div/div[2]/table/tr/td/table/tr/td/div/table/tr/td/div/div[2]/input
但是,這種行為是可配置的。如果在解析HTML之前放置此行,表單將為您提供子節點:
HtmlNode.ElementsFlags.Remove("form");