HtmlAgilityPack:如何解释 HTML 中的非标记文本

发布于 2024-11-17 05:47:21 字数 1054 浏览 4 评论 0原文

知道标题有点模糊,这里有一个例子,

<DIV>
 <DIV>title1</DIV>
 line1<br/>
 line2<br/>
 <DIV>title2</DIV>
 line2.1<br/>
 line2.2<br/>
</DIV>

How can I fetch line1
gt;line2
gt;
for title1, and line2.1
line2.2
? 我同时使用 HtmlAgilityPack 和 SharpQuery。

谢谢。

可能的解决方案

经过更多研究和尝试,我设法使用 LinePosition"//div/text()" 获取这些内容

public static HtmlNodeCollection getNodes(string html, string xpath)
{
    if (html.Length <= 0) { return null; }
    HtmlDocument doc = new HtmlDocument();
    doc.LoadHtml(html);
    return doc.DocumentNode.SelectNodes(xpath);
}

foreach (HtmlNode node in getNodes(html, "//div"){
    foreach (HtmlNode plain_node in getNodes(html, "//div/text()")
    {
        if (plain_node.LinePosition <= node.LinePosition)
        {
            currentHtml += plain_n.InnerHtml + "<br/>";
        }
    }
}

还有其他更好的方法吗?

Know that the title is kind of vague, here is an example,

<DIV>
 <DIV>title1</DIV>
 line1<br/>
 line2<br/>
 <DIV>title2</DIV>
 line2.1<br/>
 line2.2<br/>
</DIV>

How can I fetch line1<br/>line2<br/> for title1, and line2.1<br/>line2.2<br/> for title2?
I'm using HtmlAgilityPack and SharpQuery together.

Thanks.

Possible Resolution

After researched and tried more, I managed to fetch these by using LinePosition and "//div/text()"

public static HtmlNodeCollection getNodes(string html, string xpath)
{
    if (html.Length <= 0) { return null; }
    HtmlDocument doc = new HtmlDocument();
    doc.LoadHtml(html);
    return doc.DocumentNode.SelectNodes(xpath);
}

foreach (HtmlNode node in getNodes(html, "//div"){
    foreach (HtmlNode plain_node in getNodes(html, "//div/text()")
    {
        if (plain_node.LinePosition <= node.LinePosition)
        {
            currentHtml += plain_n.InnerHtml + "<br/>";
        }
    }
}

Any other better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

神经暖 2024-11-24 05:47:21

html 匹配问题很少有一种独特的解决方案。尽管您的解决方案现在可以很好地使用您的示例,但 //div 表达式将递归地搜索 root 下的所有 div 元素。

这意味着如果原始的 Html 以某种方式演变,您可能会捕获太多的东西或分析太多的节点(对于大文档来说,性能可能是 // 等问题)。

我建议像这样的东西,这更具区分性:

        HtmlDocument doc = new HtmlDocument();
        doc.Load(yourHtmlFile);

        foreach (HtmlNode node in doc.DocumentNode.SelectNodes("/div/div[starts-with(text(), 'title')]/following-sibling::text()[normalize-space(.) != '']"))
        {
            Console.WriteLine(node.InnerText.Trim());
        }

这意味着

  • 从根搜索 div 元素
  • 然后在下面搜索 div 元素
  • 过滤(使用 [...])这些元素并仅选择那些具有以 'title' 开头的内部 text
  • 然后搜索 text 类型的所有后续同级元素
  • 过滤这些元素并仅选择那些不为空或空格的元素仅

请参阅此链接以获取有关 XPATH 轴

There is rarely one unique solution to an html matching problem. Although your solution works fine now and with your sample, the //div expression will search all div elements under root, recursively.

It means if the original Html evolves somehow, you may catch too many things or analyze too many nodes (performance may be an issue with things like // for big documents).

I would suggest something like this, which is more discriminant:

        HtmlDocument doc = new HtmlDocument();
        doc.Load(yourHtmlFile);

        foreach (HtmlNode node in doc.DocumentNode.SelectNodes("/div/div[starts-with(text(), 'title')]/following-sibling::text()[normalize-space(.) != '']"))
        {
            Console.WriteLine(node.InnerText.Trim());
        }

It means

  • Search div elements from the root
  • Then search div elements underneath
  • Filter (using [...]) these elements and only select those with an inner text that start with 'title'
  • Then search all following sibling elements of type text
  • Filter these elements and only select those which are not empty or whitespace only

See this link for some help on XPATH Axes.

丿*梦醉红颜 2024-11-24 05:47:21

假设结构始终相同,您可以获取 div,然后获取它们的 NextSiblings

Assuming the structure is always the same you could get the divs and then get both of their NextSiblings

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文