【问题标题】:Xpath not working on HtmlAgilityPack documentXpath 不适用于 HtmlAgilityPack 文档
【发布时间】:2015-03-06 06:07:53
【问题描述】:

我有一个特殊的问题。当我尝试将 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 返回所需的文本。

使用的 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>

【问题讨论】:

  • InnerHtml 不包含与原始HtmlDocument 相同的 HTML 标记,请改为检查 OuterHtml。另外,发布失败的 XPath..
  • OuterHtml 也不起作用。这是 xpath://*[contains(text(),'Number of Discs:')]/following-sibling::text()
  • 我建议将 XPath 的第一位更改为://*[contains(.,'Number of Discs:')]。这只是一个猜测,请发布 HTML 的相关部分,以便我们测试并查看 XPath 失败的原因和原因
  • 谢谢。使用. 至少我在XPath //*[contains(.,'Number of Discs:')] 的第一条路径上得到一个匹配,但下一个匹配following-sibling::text() 返回一个空字符串。 html是&lt;li&gt;&lt;b&gt;Number of Discs:&lt;/b&gt; 1&lt;/li&gt;
  • @Kallol XPath 测试人员显示您的原始 XPath 对 HTML sn-p 张贴有效。因此,我几乎可以肯定您的实际 HTML 包含与此处发布的不同的标记。尝试将HtmlDocument保存到文件中,然后打开文件确认它是否包含不同的HTML..

标签: vb.net xpath html-agility-pack


【解决方案1】:
<li>
  <b>Number of Discs:</b>
 1
</li>'

也许这会有所帮助

//b[contains(text(), 'Number of Discs')]/../text()

我认为数字“属于” to li 节点,而不是 b。这就是为什么你不能说 follow-sibling::text()

【讨论】:

  • 是的,数字是 li 的文本节点 - 这就是为什么 following-sibling::text() 完全可以接受的原因。
【解决方案2】:

最初的问题HtmlDocument 是在针对 XPath 解析下载的 html 时,它没有返回任何匹配项。而当使用相同的 html 创建另一个 HtmlDocument 并使用相同的 XPath 解析时,它找到了匹配项。因此问题不在于实际的 XPath,否则它不会在第二个实例中工作(这就是为什么我没有在第一个实例中发布 XPath)。

在调用问题中发布的代码之前,运行以下代码以解析来自同一 HtmlDocument 的另一个(不同的)字段

        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.在上面问题中列出的解析逻辑运行之前,还有另一个解析逻辑运行了从HtmlNodeCollection匹配的clears()节点 2.这会影响下一个解析逻辑在其上运行的相同HtmlDocument(这是问题中列出的逻辑) 3.因此Xpath失败

还有一个问题是,如果 _pageHtml 因之前的 HtmlNodeCollection.Clear() 而发生变化,那么为什么我从 _pageHtml 获取 Html 并创建另一个 HtmlDocument 的代码,然后在这个新的 @987654335 上运行解析逻辑@工作?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-16
    • 2013-07-02
    • 1970-01-01
    • 2013-12-19
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多