XPath定位到文本长度大于等于200个字符的第一个元素

6
如何获取第一个内部文本(纯文本,舍弃其他子节点)长度为200或更多个字符的元素?
我正在尝试创建类似于Embed.ly的HTML解析器,我已经设置了一套回退系统,首先检查og:description,然后才会搜索此出现情况,然后只搜索description元标记。
这是因为大多数甚至包括的网站都在该标记中描述其站点,而不是当前页面的内容。
示例:
<html>
    <body>
        <div>some characters
            <p>200 characters <span>some more stuff</span></p>
        </div>
    </body>
</html>

我应该使用什么选择器来获取HTML片段中的 200个字符 部分? 我也不想要一些其他的东西,我不关心它是哪个元素(除了<script><style>),只要它是包含至少200个字符的第一个纯文本。
XPath查询应该长什么样?
3个回答

8

用途:

(//*[not(self::script or self::style)]/text()[string-length() > 200])[1]

注意:如果文档是XHTML文档(这意味着所有元素都在xhrml命名空间中),则上述表达式应指定为:

(//*[not(self::x:script or self::x:style)]/text()[string-length() > 200])[1]

前缀"x:"必须绑定到XHTML命名空间--"http://www.w3.org/1999/xhtml"(或者如许多XPath API所称,该命名空间必须用此前缀"注册")。


由于这是一个爬虫服务,我并不确定文档是否为XHTML格式。 - bevacqua
@Nico:那就试试不带前缀的方式——我相信HTML Agility Pack不需要这个。 - Dimitre Novatchev
是的,因为任何聪明的XPath引擎都会在找到/选择第一个(也是唯一必需的)节点后停止评估。您提供的表达式将遍历整个树,因为它选择了所有这样的节点。 - Dimitre Novatchev

2
我理解您的意思是这样的:

我是指像这样的内容:

root.SelectNodes("html/body/.//*[(name() !='script') and (name()!='style')]/text()[string-length() > 200]")

看起来工作得相当不错。


1
这个XPath表达式选择所有这样的文本节点--不仅仅是第一个。这将比必要的占用更多的空间和时间。在我的答案中,我提供了一个更精确和高效的XPath表达式。 - Dimitre Novatchev

0

HTML不是XML。你不应该使用XML解析器来解析HTML。它们是完全不同的两个东西,而且你的解析器在看到格式不正确的html时会崩溃。

你应该找一个开源的HTML解析器而不是自己编写。


我正在使用 HtmlAgilityPack,我不是在尝试解析HTML,我只是想获取至少包含200个字符的HTML的第一部分。 - bevacqua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接