4

我正在使用 AngleSharp 解析网站内容,但我遇到了匿名块的问题。

查看示例代码:

var parser = new HtmlParser();
var document = parser.Parse(@"<body>
<div class='product'>
    <a href='#'><img src='img1.jpg' alt=''></a>
    Hello, world
    <div class='comments-likes'>1</div>
</div>
<div class='product'>
    <a href='#'><img src='img2.jpg' alt=''></a>
    Yet another helloworld
    <div class='comments-likes'>25</div>
</div>
<body>");

var products = document.QuerySelectorAll("div.product");
foreach (var product in products)
{
    var productTitle = product.Text();
    productTitle.Dump();
}

因此,productTitle 包含来自 div.comments-likes 的数字,输出为:

你好,世界1

又一个 helloworld 25

我尝试过类似product.FirstElementChild.NextElementSibling.Text();但链接元素的下一个兄弟是 div.comments-likes,而不是匿名块。表明:

1

25

因此,会跳过匿名块。:(

我发现的最佳解决方法是删除所有阻止块,例如:

product.QuerySelector(".comments-likes").Remove();
var productTitle = product.Text().Trim();

从匿名块中解析文本的更好方法是什么?

4

1 回答 1

3

文本被建模为TextNode,它是元素旁边的一种节点,注释节点,处理指令等。这就是为什么NextElementSibling您尝试在结果中不包含文本,因为它只打算返回元素,顾名思义。

div您可以通过遍历div'sChildNodes然后过滤来获取直接位于产品内的文本节点NodeType,例如:

var products = document.QuerySelectorAll("div.product");
foreach (var product in products)
{
    var productTitle = product.ChildNodes
                              .First(o => o.NodeType == AngleSharp.Dom.NodeType.Text 
                                            && o.TextContent.Trim() != "");
    Console.WriteLine(productTitle.TextContent.Trim());
}

dotnetfiddle demo

请注意,元素之间的换行符也是文本节点,因此我们需要在上面的演示中过滤掉它们。

于 2017-03-12T07:16:44.320 回答