HTML XPath:使用多个标签提取混合的文本?

时间:2012-05-16 11:58:22

标签: html xpath scrapy

目标:从特定元素(例如li)中提取文本,同时忽略各种混合标记,即展平第一级子项并简单地单独返回每个扁平子项的连接文本。

示例:

<div id="mw-content-text"><h2><span class="mw-headline" >CIA</span></h2>
    <ol>
    <li>Central <a href="/Intelligence_Agency.html">Intelligence Agency</a>.</li>
    <li>Culinary <a href="/Institute.html">Institute</a> of <a href="/America.html">America</a>.</li>
    </ol>

    </Div>  

所需文字:

  • 中央情报局
  • 美国烹饪学院

除了周围的锚标签阻止简单检索。

要分别返回每个li标签,我们使用简单的方法:

//div[contains(@id,"mw-content-text")]/ol/li

但也包括周围的锚标签等。

//div[contains(@id,"mw-content-text")]/ol/li/text()

仅返回li的直接子元素的文本元素,即“Central”,“。”......

然后寻找自我和后代的文本元素似乎是合乎逻辑的

//div[contains(@id,"mw-content-text")]/ol/li[descendant-or-self::text]

但是什么都没有返回!

有什么建议吗?我正在使用Python,所以我愿意使用其他模块进行后期处理。

(我正在使用符合XPath 1.0标准的Scrapy HtmlXPathSelector)

3 个答案:

答案 0 :(得分:25)

你几乎就在那里。

中存在一个小问题
//div[contains(@id,"mw-content-text")]/ol/li[descendant-or-self::text]

更正后的表达

//div[contains(@id,"mw-content-text")]/ol/li[descendant-or-self::text()]

但是,有一个更简单的表达式可以精确生成指定li下所有文本节点的所需连接:

string(//div[contains(@id,"mw-content-text")]/ol/li)

答案 1 :(得分:5)

我认为以下内容会返回正确的结果:

//div[contains(@id,"mw-content-text")]/ol/li//text()

注意text()之前的双斜杠。这意味着必须返回li以下任何级别的文本节点。

答案 2 :(得分:2)

字符串连接很棘手。这是使用lxml

的快速解决方案
>>> from lxml import etree
>>> doc = etree.HTML("""<div id="mw-content-text"><h2><span class="mw-headline" >CIA</span></h2>
...     <ol>
...     <li>Central <a href="/Intelligence_Agency.html">Intelligence Agency</a>.</li>
...     <li>Culinary <a href="/Institute.html">Institute</a> of <a href="/America.html">America</a>.</li>
...     </ol>
...
...     </Div>""")
>>> for element in doc.xpath('//div[@id="mw-content-text"]/ol/li'):
...   print "".join(element.xpath('descendant-or-self::text()'))
...
Central Intelligence Agency.
Culinary Institute of America.

请注意//可能性能不佳/意外执行,应尽可能避免,但使用示例HTML片段很难做到。