0

[这个问题有一个亲戚:Screen scraping with htmlAgilityPack and XPath ]

我有一些要解析的 HTML,其一般外观如下:

...
<tr>
<td><a href="" title="">Text Data here (1)</a></td>
<td>Text Data here(2)</td>
<td>Text Data here(3)</td>
<td>Text Data here(4)</td>
<td>Text Data here(5)</td>
<td>Text Data here(6)</td>
<td><a href="link here {1}" class="image"><img alt="" src="" /></a></td>
</tr>
<tr>
<td><a href="" title="">Text Data here (1)</a></td>
<td>Text Data here(2)</td>
<td>Text Data here(3)</td>
<td>Text Data here(4)</td>
<td>Text Data here(5)</td>
<td>Text Data here(6)</td>
<td><a href="link here {1}" class="image"><img alt="" src="" /></a></td>
</tr>
...

我正在寻找一种可以将其解析为有意义的块的方法,但我希望有选择性数据,例如前两个 td 数据和最后两个 td 数据:

(1), (2), (6), {1} CRLF
(1), (2), (6), {1}CRLF
等等

我尝试了两种方式:方式1:

var dataList = currentDoc.DocumentNode.Descendants("tr")
            .Select
             (
              tr => tr.Descendants("td").Select(td => td.InnerText).ToList()
             ).ToList();

它获取了 tds 的内部文本,但无法获取链接 {1}。在这里,创建了一个包含许多列表的列表。我可以使用嵌套的 foreach 来管理它。

方式2:

var dataList = currentDoc.DocumentNode
           .SelectNodes("//tr//td//text()|//tr//td//a//@href");

这确实为我提供了链接 {1} 和所有数据,但它变得杂乱无章。在这里,所有数据都以大块的形式存在。因为,一个 tr 中的数据是相对的,所以我现在放松了这种关系。

那么,如何获取我感兴趣的数据,只有前两列和后两列数据呢?

4

1 回答 1

0

以下代码将选择前两个<td>数据和后两个<td>节点数据:

html.DocumentNode.Descendants("tr")
    .Select(tr => 
       from td in tr.SelectNodes("td[position() < 3 or position() > last() - 2]")
       let a = td.SelectSingleNode("a[@href!='']")
       select a == null ? td.InnerText : a.Attributes["href"].Value);

此 xpath 按位置过滤节点:

td[position() < 3 or position() > last() - 2]
于 2013-03-14T12:15:28.357 回答