Xpath 不适用于 HtmlAgilityPack 文档
Xpath not working on HtmlAgilityPack document
我有一个特殊的问题。当我尝试将 Xpath 应用于 HtmlAgility.HtmlDocument
时,它不起作用。但是当我使用同一文档的内部 html 并创建另一个 HtmlAgility.HtmlDocument
对象时,找到了匹配项。任何想法将不胜感激。
Dim ret As String = Nothing
Dim tmpHtmlNode As HtmlNode = _pageHTML.DocumentNode.SelectSingleNode(token.MatchingXPath)
If tmpHtmlNode IsNot Nothing AndAlso tmpHtmlNode.InnerText IsNot Nothing Then ' THIS FETCHES NULL'
ret = tmpHtmlNode.InnerText.Trim
End If
Dim x As New HtmlAgilityPack.HtmlDocument
x.LoadHtml(_pageHTML.DocumentNode.InnerHtml)
Dim node As HtmlNode = Nothing
node = x.DocumentNode.SelectSingleNode(token.MatchingXPath)
Console.WriteLine(node.InnerText) ' THIS WORKS'
在上面的代码中,tmpHtmlNode
在计算 XPath 后为 NULL。而 node
下面 return 所需的文本。
使用的 Xpath 是 "//*[contains(text(),'Number of Discs:')]/following-sibling::text()"
,预期匹配的 Html 部分是:
<h2>Product Details</h2>
<div class="content">
<ul>
<li><b>Performer:</b> <a href="/s/ref=dp_db_clas_perf?ie=UTF8&keywords=Royal%20Scots%20Dragoon%20Guards&search-alias=classical">Royal Scots Dragoon Guards</a></li>
<li><b>Audio CD</b> (March 24, 1992)</li>
<li><b>Number of Discs:</b> 1</li>
<li><b>Label:</b> RCA</li>
<li><b>ASIN:</b> B000002WEN</li>
<li><b>Average Customer Review:</b>
<li id="SalesRank">
<b>Amazon Best Sellers Rank:</b>
#68,703 in Music (<a href="http://www.amazon.com/best-sellers-music-albums/zgbs/music/ref=pd_dp_ts_m_1">See Top 100 in Music</a>)
</li>
</ul>
<span class="tiny">
<ul class="noteBullets">
</ul>
</span>
</div>
<li>
<b>Number of Discs:</b>
1
</li>'
也许这会有所帮助
//b[contains(text(), 'Number of Discs')]/../text()
我认为数字 "belongs" 是 to li 节点,而不是 b。这就是为什么你不能说 following-sibling::text()
最初的问题 HtmlDocument
是当下载的 html 根据 XPath 进行解析时,它没有返回任何匹配项。而当使用相同的 html 创建另一个 HtmlDocument
并使用相同的 XPath 进行解析时,它找到了匹配项。因此,问题不在于实际的 XPath,否则它不会在第二个实例中工作(这就是为什么我在第一个实例中没有 post XPath)。
在调用问题中的代码 post 之前,下面的代码是 运行 从同一个 HtmlDocument
[=25= 解析另一个(不同的)字段]
Dim ret As List(Of String) = Nothing
Dim tmpHtmlNodes As HtmlNodeCollection = _pageHTML.DocumentNode.SelectNodes(token.MatchingXPath)
If tmpHtmlNodes IsNot Nothing AndAlso tmpHtmlNodes.Count > 0 Then
For Each tmpHtmlNode As HtmlNode In tmpHtmlNodesx
If tmpHtmlNode IsNot Nothing AndAlso tmpHtmlNode.InnerText IsNot Nothing Then
If ret Is Nothing Then ret = New List(Of String)
ret.Add(tmpHtmlNode.InnerText.Trim)
tmpHtmlNode = Nothing
End If
Next
End If
tmpHtmlNodes.Clear()
Return ret
此字段的解析逻辑中有行 tmpHtmlNodes.Clear()
,这是罪魁祸首。这会更改 HtmlDocument
并导致下一次解析调用失败,因为它无法找到已被 clear()
移除的节点。
总结一下这个问题:
1. 在上述问题运行中列出的解析逻辑之前,还有一个解析逻辑运行s which clears()
nodes that had matched from a HtmlNodeCollection
2.这影响下一个解析逻辑运行s的相同HtmlDocument
(这是问题中列出的逻辑)
3. 因此 Xpath 失败
还有一个问题是,如果 _pageHtml
由于较早的 HtmlNodeCollection.Clear()
而发生更改,那么为什么我从 _pageHtml
中获取 Html 并创建另一个 HtmlDocument
然后 运行 这个新 HtmlDocument
的解析逻辑有效吗?
我有一个特殊的问题。当我尝试将 Xpath 应用于 HtmlAgility.HtmlDocument
时,它不起作用。但是当我使用同一文档的内部 html 并创建另一个 HtmlAgility.HtmlDocument
对象时,找到了匹配项。任何想法将不胜感激。
Dim ret As String = Nothing
Dim tmpHtmlNode As HtmlNode = _pageHTML.DocumentNode.SelectSingleNode(token.MatchingXPath)
If tmpHtmlNode IsNot Nothing AndAlso tmpHtmlNode.InnerText IsNot Nothing Then ' THIS FETCHES NULL'
ret = tmpHtmlNode.InnerText.Trim
End If
Dim x As New HtmlAgilityPack.HtmlDocument
x.LoadHtml(_pageHTML.DocumentNode.InnerHtml)
Dim node As HtmlNode = Nothing
node = x.DocumentNode.SelectSingleNode(token.MatchingXPath)
Console.WriteLine(node.InnerText) ' THIS WORKS'
在上面的代码中,tmpHtmlNode
在计算 XPath 后为 NULL。而 node
下面 return 所需的文本。
使用的 Xpath 是 "//*[contains(text(),'Number of Discs:')]/following-sibling::text()"
,预期匹配的 Html 部分是:
<h2>Product Details</h2>
<div class="content">
<ul>
<li><b>Performer:</b> <a href="/s/ref=dp_db_clas_perf?ie=UTF8&keywords=Royal%20Scots%20Dragoon%20Guards&search-alias=classical">Royal Scots Dragoon Guards</a></li>
<li><b>Audio CD</b> (March 24, 1992)</li>
<li><b>Number of Discs:</b> 1</li>
<li><b>Label:</b> RCA</li>
<li><b>ASIN:</b> B000002WEN</li>
<li><b>Average Customer Review:</b>
<li id="SalesRank">
<b>Amazon Best Sellers Rank:</b>
#68,703 in Music (<a href="http://www.amazon.com/best-sellers-music-albums/zgbs/music/ref=pd_dp_ts_m_1">See Top 100 in Music</a>)
</li>
</ul>
<span class="tiny">
<ul class="noteBullets">
</ul>
</span>
</div>
<li>
<b>Number of Discs:</b>
1
</li>'
也许这会有所帮助
//b[contains(text(), 'Number of Discs')]/../text()
我认为数字 "belongs" 是 to li 节点,而不是 b。这就是为什么你不能说 following-sibling::text()
最初的问题 HtmlDocument
是当下载的 html 根据 XPath 进行解析时,它没有返回任何匹配项。而当使用相同的 html 创建另一个 HtmlDocument
并使用相同的 XPath 进行解析时,它找到了匹配项。因此,问题不在于实际的 XPath,否则它不会在第二个实例中工作(这就是为什么我在第一个实例中没有 post XPath)。
在调用问题中的代码 post 之前,下面的代码是 运行 从同一个 HtmlDocument
[=25= 解析另一个(不同的)字段]
Dim ret As List(Of String) = Nothing
Dim tmpHtmlNodes As HtmlNodeCollection = _pageHTML.DocumentNode.SelectNodes(token.MatchingXPath)
If tmpHtmlNodes IsNot Nothing AndAlso tmpHtmlNodes.Count > 0 Then
For Each tmpHtmlNode As HtmlNode In tmpHtmlNodesx
If tmpHtmlNode IsNot Nothing AndAlso tmpHtmlNode.InnerText IsNot Nothing Then
If ret Is Nothing Then ret = New List(Of String)
ret.Add(tmpHtmlNode.InnerText.Trim)
tmpHtmlNode = Nothing
End If
Next
End If
tmpHtmlNodes.Clear()
Return ret
此字段的解析逻辑中有行 tmpHtmlNodes.Clear()
,这是罪魁祸首。这会更改 HtmlDocument
并导致下一次解析调用失败,因为它无法找到已被 clear()
移除的节点。
总结一下这个问题:
1. 在上述问题运行中列出的解析逻辑之前,还有一个解析逻辑运行s which clears()
nodes that had matched from a HtmlNodeCollection
2.这影响下一个解析逻辑运行s的相同HtmlDocument
(这是问题中列出的逻辑)
3. 因此 Xpath 失败
还有一个问题是,如果 _pageHtml
由于较早的 HtmlNodeCollection.Clear()
而发生更改,那么为什么我从 _pageHtml
中获取 Html 并创建另一个 HtmlDocument
然后 运行 这个新 HtmlDocument
的解析逻辑有效吗?