【问题标题】:Get avaliable XPaths and its element names using HtmlAgilityPack使用 HtmlAgilityPack 获取可用的 XPath 及其元素名称
【发布时间】:2014-08-19 05:45:22
【问题描述】:

我正在使用一个函数从 HTML 中获取所有可用的 XPath 表达式,使用 HtmlAgilityPack 库。

问题是我得到了这种格式的表达式:

/html[1]/body[1]/div[1]/div[1]/div[1]/div[1]/h4[1]/a[1]

我会改进它以获得节点/元素的名称,如下所示:

/html/body/div[@class='infolinks']/div[@class='music']/div[@class='item']/div[@class='release']/h4[1]/a[@title]

但我不知道如何使用 HtmlAgilityPack 正确获取他们的名字。

我该怎么做?

注意:如果 XPath 的语法不好或者我理解错误,我不是 XPath 专家。


我正在尝试的网页源代码:

<div class="infolinks"><input type="hidden" name="IL_IN_TAG" value="1"/></div><div id="main">

    <div class="music">

        <h2 class="boxtitle">New releases \ <small>
            <a href="/newalbums" title="New releases mp3 downloads" rel="bookmark">see all</a></small>
        </h2>

        <div class="item">

            <div class="thumb">
                <a href="http://www.mp3crank.com/curt-smith/deceptively-heavy-121861" rel="bookmark" lang="en" title="Curt Smith - Deceptively Heavy album downloads"><img width="100" height="100" alt="Mp3 downloads Curt Smith - Deceptively Heavy" title="Free mp3 downloads Curt Smith - Deceptively Heavy" src="http://www.mp3crank.com/cover-album/Curt-Smith-Deceptively-Heavy-400x400.jpg"/></a>
            </div>

            <div class="release">
                <h3>Curt Smith</h3>
                <h4>
                    <a href="http://www.mp3crank.com/curt-smith/deceptively-heavy-121861" title="Mp3 downloads Curt Smith - Deceptively Heavy">Deceptively Heavy</a>
                </h4>
                <script src="/ads/button.js"></script>
            </div>

            <div class="release-year">
                <p>Year</p>
                <span>2013</span>
            </div>

            <div class="genre">
                <p>Genre</p>
                <a href="http://www.mp3crank.com/genre/indie" rel="tag">Indie</a><a href="http://www.mp3crank.com/genre/pop" rel="tag">Pop</a>
            </div>

        </div>

        <div class="item">

            <div class="thumb">
                <a href="http://www.mp3crank.com/wolf-eyes/lower-demos-121866" rel="bookmark" lang="en" title="Wolf Eyes - Lower Demos album downloads"><img width="100" height="100" alt="Mp3 downloads Wolf Eyes - Lower Demos" title="Free mp3 downloads Wolf Eyes - Lower Demos" src="http://www.mp3crank.com/cover-album/Wolf-Eyes-–-Lower-Demos.jpg" /></a>
            </div>

            <div class="release">
                <h3>Wolf Eyes</h3>
                <h4>
                    <a href="http://www.mp3crank.com/wolf-eyes/lower-demos-121866" title="Mp3 downloads Wolf Eyes - Lower Demos">Lower Demos</a>
                </h4>
                <script src="/ads/button.js"></script>
            </div>

            <div class="release-year">
                <p>Year</p>
                <span>2013</span>
            </div>

            <div class="genre">
                <p>Genre</p>
                <a href="http://www.mp3crank.com/genre/rock" rel="tag">Rock</a>
            </div>

        </div>

    </div>

</div>


获取XPaths的函数:

Public Function GetXPaths(ByVal Document As HtmlAgilityPack.HtmlDocument) As List(Of String)

    Dim XPathList As New List(Of String)
    Dim XPath As String = String.Empty

    For Each Child As HtmlAgilityPack.HtmlNode In Document.DocumentNode.ChildNodes

        If Child.NodeType = HtmlAgilityPack.HtmlNodeType.Element Then
            GetXPaths(Child, XPathList, XPath)
        End If

    Next ' child'

    Return XPathList

End Function

Private Sub GetXPaths(ByVal Node As HtmlAgilityPack.HtmlNode,
                      ByRef XPathList As List(Of String),
                      Optional ByVal XPath As String = Nothing)

    XPath = Node.XPath

    If Not XPathList.Contains(XPath) Then
        XPathList.Add(XPath)
    End If

    For Each Child As HtmlAgilityPack.HtmlNode In Node.ChildNodes

        If Child.NodeType = HtmlAgilityPack.HtmlNodeType.Element Then
            GetXPaths(Child, XPathList, XPath)

        End If

    Next ' child

End Sub

这些是我用来检索一些值的 XPath,我希望在上面的函数上获得或多或少相同的 XPath 完全限定表示。

Title = node.SelectSingleNode(".//div[@class='release']/h4/a[@title]").GetAttributeValue("title", "Unknown Title")
Cover = node.SelectSingleNode(".//div[@class='thumb']/a/img[@src]").GetAttributeValue("src", String.Empty)
Year = node.SelectSingleNode(".//div[@class='release-year']/span").InnerText
Genres = (From genre In node.SelectNodes(".//div[@class='genre']/a") Select genre.InnerText).ToArray
URL = node.SelectSingleNode(".//div[@class='release']/h4/a[@href]").GetAttributeValue("href", "Unknown URL")

【问题讨论】:

  • html、body、div 等是元素名称。你的意思是获取元素的类名(如果有的话)?
  • @har07 是的,这就是我的意思,感谢您的评论

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


【解决方案1】:

如果相应元素具有类属性,这会将类属性过滤器附加到 XPath:

Private Sub GetHtmlXPaths(ByVal Node As HtmlAgilityPack.HtmlNode,
                          ByRef XPathList As List(Of String),
                          Optional ByVal XPath As String = Nothing)

    XPath &= Node.XPath.Substring(Node.XPath.LastIndexOf("/"c))

    Const ClassNameFilter As String = "[@class='{0}']"
    Dim ClassName As String = Node.GetAttributeValue("class", String.Empty)

    If Not String.IsNullOrEmpty(ClassName) Then
        XPath &= String.Format(ClassNameFilter, ClassName)
    End If

    If Not XPathList.Contains(XPath) Then
        XPathList.Add(XPath)
    End If

    For Each Child As HtmlAgilityPack.HtmlNode In Node.ChildNodes

        If Child.NodeType = HtmlAgilityPack.HtmlNodeType.Element Then
            GetHtmlXPaths(Child, XPathList, XPath)
        End If

    Next Child

End Sub

【讨论】:

  • 该函数没有给出期望的结果,例如当多个具有相同类名的 div 时缺少 XPath(例如,我提供的源中的类名“Item”上面)其他 div 算作添加(不是误报添加),我冒昧地修改了您的解决方案来解决问题,抱歉,如果这让您感到恼火,您可以随时恢复我的修改(或改进它)。对不起我的英语,谢谢你的回答
  • 刚才在 XPath 中添加了一些东西,例如 div[@class='item'] 现在我添加了 div[1][@class='item']div[2][@class='item'],这些 xpath 使用 htmlagilitypath 可以按预期工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多