小编典典

带子项的XPath文本

scrapy

鉴于此html:

<ul>
    <li>This is <a href="#">a link</a></li>
    <li>This is <a href="#">another link</a>.</li>
</ul>

如何使用XPath获得以下结果:

[
    'This is a link',
    'This is another link.'
]

我尝试过的

//ul/li/text()

但是,这给了我['This is ', 'This is .'](withoug的文本a标签

也:

string(//ul/li)

但这给了我['This is a link'](所以只有第一个要素)

//ul/li/descendant-or-self::text()

但这给了我 ['This is ', 'a link', 'This is ', 'another link', '.']

还有其他想法吗?


阅读 421

收藏
2020-04-09

共1个答案

小编典典

XPath通常无法选择不存在的内容。这些东西在你的HTML中不存在:

[
    'This is a link',
    'This is another link.'
]

从概念上讲,它们可能存在于更高的抽象级别上,即浏览器对源代码的呈现,但严格来说,即使它们是分开的,例如在颜色和功能上也是如此。

在DOM级别上,只有单独的文本节点,并且XPath可以为你服务。

因此,你有三个选择。

  1. 选择text()节点并在Python代码中将其各个值连接起来。
  2. 选择<li>元素,然后为每个元素进行评估string(.)normalize-space(.)使用Scrapynormalize-space()将以你期望的方式处理空白。
  3. 选择<li>元素并访问其.text属性-在内部查找所有后代文本节点并为你加入它们。
    就我个人而言,我将使用//ul/li我的基本XPath表达式作为后者,因为这将导致更简洁的解决方案。

正如@paul在评论中指出的那样,Scrapy提供了一个很好的流利界面,可以在一行代码中执行多个处理步骤。以下代码实现了变体#2:

selector = scrapy.Selector(text='''<ul>
    <li>This is <a href="#">a link</a></li>
    <li>This is <a href="#">another link</a>.</li>
</ul>''')

selector.css('ul > li').xpath('normalize-space()').extract()
# --> [u'This is a link', u'This is another link.']
2020-04-09