提问人:Olote 提问时间:5/6/2023 最后编辑:Olote 更新时间:5/6/2023 访问量:72
HtmlAgilityPack - 选择后代,直到元素与类
HtmlAgilityPack - Select descendant until element with class
问:
我在 C# 应用程序中使用 HtmlAgilityPack 来抓取一些 HTML 代码。但是我在选择特定标签时遇到了问题。
这是我拥有的 HTML:
<div class="Post">
<img src="image.png" alt="Alt Text">
<br>
<b>THIS TEXT IS WHAT I WANT</b>
<div class="DesktopElements">
<br>
Hello world
</div>
<br>
Some text here.
<br>
<b>Title</b>
<br>
Some more text here.
</div>
我试图做的是选择第一个“b”标签内的文本:,但前提是它位于类为“DesktopElements”的div之前。我不想在“DesktopElements”类之后选择任何内容。
如果标签存在,则此功能正常。但问题是,有时这个标签不会存在。<b>THIS TEXT IS WHAT I WANT</b>
<b>
<b>
到目前为止,我一直在尝试的是获取 的第一个后代,但正如您可能意识到的那样,如果标签不存在,它将不起作用。有时它在那里,有时它不在那里。<b>
<div class="Post">
因此,我基本上只需要检查 和 之间的标签,并选择其中的第一个(也是唯一的)。<b>
<div class="Post">
<div class="DesktopElements">
<b>
我该怎么做?
换句话说,有时它可能看起来像这样:
<div class="Post">
<img src="image.png" alt="Alt Text">
<br>
<div class="DesktopElements">
<br>
Hello world
</div>
<br>
Some text here.
<br>
<b>Title</b>
<br>
Some more text here.
</div>
如果是这样的话,我只是将“p.Title”设置为“none”。
这是我目前使用的代码:
p.Title = row.SelectSingleNode(".//div[@class='Post']").Descendants("b").Select(title => title.InnerText).Where(t => !string.IsNullOrWhiteSpace(t)).ToList().First();
这将捕获第一个标签的 InnerText 值,但如果之前没有“b”标签,它将选择下面的标签,上面写着这不是我要选择的。<b>
<div class="DesktopElements">
<b>
<b>Title</b>
答:
您可以使用 TakeWhile
只获取之前的节点,而不是只获取:<div class="DesktopElements">
Descendants("b")
var node = doc.DocumentNode.SelectSingleNode(".//div[@class='Post']")
.Descendants()
.TakeWhile(node => !node.HasClass("DesktopElements"))
.FirstOrDefault(node => node.Name == "b");
p.Title = node?.InnerText ?? "none";
请参阅示例小提琴。
评论
我假设你想要这个XPath:
//div[@class='Post']/div[@class='DesktopElements']/preceding-sibling::b
这将只选择那些成为之前并且是其子的b
div[@class='DesktopElements']
div[@class='Post']
编辑
在查看了共享的网址(在不再存在的评论中)后,我注意到没有类和 .
取而代之的是类:和Post
DesktopElements
PostText
ForumDesktopElements
不知道这怎么可能,但如果是这样的话,您将需要这个 XPath
//div[@class='PostText']/div[@class='ForumDesktopElements']/preceding-sibling::b
评论