HtmlAgilityPack - 选择后代,直到元素与类

HtmlAgilityPack - Select descendant until element with class

提问人:Olote 提问时间:5/6/2023 最后编辑:Olote 更新时间:5/6/2023 访问量:72

问:

我在 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>

C# DOM XPath 节点 html-agility-pack

评论


答:

2赞 Xerillio 5/6/2023 #1

您可以使用 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";

请参阅示例小提琴

评论

0赞 Olote 5/6/2023
谢谢!我设法让它工作。首先,它返回了一些空字符串,但那是由于我愚蠢。谢谢!!它完美无缺!
2赞 Siebe Jongebloed 5/6/2023 #2

我假设你想要这个XPath:

//div[@class='Post']/div[@class='DesktopElements']/preceding-sibling::b

这将只选择那些成为之前并且是其子的bdiv[@class='DesktopElements']div[@class='Post']

编辑

在查看了共享的网址(在不再存在的评论中)后,我注意到没有类和 . 取而代之的是类:和PostDesktopElementsPostTextForumDesktopElements

不知道这怎么可能,但如果是这样的话,您将需要这个 XPath

//div[@class='PostText']/div[@class='ForumDesktopElements']/preceding-sibling::b