如何从 HTML 节点集合中获取特定的跨度标签

How to get a specific span tag from a HTML Node collection

我试图从 HTML 节点集合中获取 div 内的每个第二个跨度标签,但由于某种原因,我只获取第一个跨度标签。我怀疑与我的 XPath 表达式有关,但我不确定。

Program.cs

static void Main(string[] args) {
    var doc = new HtmlDocument();
    doc.Load("test.html");
            
    var htmlNodes = doc.DocumentNode.SelectNodes("//body/div/div/div");
    foreach (var node in htmlNodes) {
        Console.WriteLine(node.ChildNodes[1].InnerText);
    }
}

HTML 文件

<doctype! html>

<html lang='pt-br'>
    <head>
        <title>Teste</title>
        <meta charset='utf-8'/>

        <!-- Bootstrap -->
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
        integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
        <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
        
        <!-- Custom CSS -->
        <link rel="stylesheet" type="text/css" href="./styles.css"/>
    </head>

    <body>
        <div class="container-fluid">
            <h1 class="title">Relatório</h1>

            <div id="infoField" class="container">
                <div>
                    <span>Matricula: </span>
                    <span>1111</span> <!-- Supposed to be this span tag -->
                </div>

                <div>
                    <span>Nome: </span>
                    <span>any</span> <!-- Supposed to be this span tag -->
                </div>

                <div>
                    <span>Sobrenome: </span>
                    <span>any</span> <!-- Supposed to be this span tag -->
                </div>

                <div>
                    <span>Porto: </span>
                    <span>2</span> <!-- Supposed to be this span tag -->
                </div> 
            </div>
        </div>
    </body>
</html>

返回值

Matricula:
Nome:
Sobrenome:
Porto:

我有预感 HtmlAgilityPack 正在读取内部 <div> 和第一个 <span>.

之间的文本节点

该文本节点将成为节点 0,使节点 1 (node.ChildNodes[1])成为您的第一个 <span>

发生这种情况是因为某些(大多数?)HTML 解析器将任何不是标签的内容都读取为文本,包括白色 space。在 HTML 和 <span> 之间有白色 space。

没有白色 space 和文本节点的唯一方法是将标签相互对齐,如下所示:

<div><span>Matricula:</span><span>1111</span></div>

如果包含 <div><span> 之间的文本节点,以及两个 <span> 标签之间的文本节点,则第二个 <span> 将是节点3. 所以,这条线可能会起作用:

Console.WriteLine(node.ChildNodes[3].InnerText);

但您可能不想在 HTML 中考虑文本节点和 space。您只需要 <span> 个标签!

刷新了我对 HtmlAgilityPack 的记忆,我认为这会更好地为您服务:

foreach (var node in htmlNodes) {
    Console.WriteLine(node.Elements("span")[1].InnerText);
}

参考:https://html-agility-pack.net/elements