首页 > 解决方案 > Scrapy 和 xpath 怪异——自动添加标签、轴和步骤?

问题描述

我无法理解如何将 xpaths 与 scrapy 一起使用的一些细节。例如:

我没有添加的额外 html-body 填充

from scrapy.selector import Selector
t = '<a href="123">qwer</a>'
sel = Selector(text=t)

sel.extract()
# returns: <html><body><a href="123">qwer</a></body></html>

html-body 标签填充来自哪里?

轴和台阶??

sel.xpath('html').extract()  # returns [], ok
sel.xpath('body').extract()  # returns '<body><a ...' ?????
sel.xpath('a').extract()     # returns [], ok?

为什么我可以选择“body”而不使用“/”?我对项目中的“div”元素有类似的行为。

还有以下内容:

sel.xpath('//body').extract()  # returns '<body>...', ok
sel.xpath('//body').xpath('/body').extract()
# this returns []. 

为什么 xpath 链返回的结果与第一行不同?两种情况下的选择器似乎相同?第二个 xpath 调用不应该在新根上工作吗?

标签: pythonxpathscrapy

解决方案


Scrapy Selector 使用lxml.html解析器来解析输入文本,当 lxml 接收到非完整的 html(html 片段)时,它总是将它包装成一个完整的 html 文档树,我相信(例如,Web 浏览器的工作方式相同)。

Xpath 表达式的工作方式与基本文件系统路径表达式非常相似,例如/home/john/Downloads/file.pdf(absolute path) 或Downloads/file.pdf(relative path and is same as ./Downloads/file.pdf)。

简单的 XPath 表达式如body也一样./body,表示从当前节点开始定位<body>元素,该元素应该是当前节点的直接子节点。点表示当前节点,单斜杠表示它下面的一个级别(双破折号表示下面的任何级别)。

默认情况下,您位于相对于 html 树根(<html>节点)的位置。根节点没有直接的子元素<html>,所以xpath('html')什么也没有。根节点确实有一个直接<body>子节点,因此xpath('body')产生它。根节点没有直接<a>子节点,因此不会xpath('a')产生任何结果(但是您可以通过 检索它xpath('.//a'))。

这种链接xpath('//body').xpath('/body')并不像您认为的那样工作。首先,以/or开始表达式//(两者都是绝对路径)指示评估器开始相对于文档的根进行查找,而不考虑您当前的位置。所以你的表达方式是:在文档中的任何地方找到 body 元素,然后找到必须位于最顶部的 body 元素(除了顶部只有一个元素,那就是<html>)。


推荐阅读