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&amp;keywords=Royal%20Scots%20Dragoon%20Guards&amp;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 的解析逻辑有效吗?