Scrapy 教程

Scrapy 选择器(Selector)


当抓取网页时,你做的最常见的任务是从HTML源码中提取数据。Scrapy 提取数据有自己的一套机制,被称作选择器,它通过指定的 XPath 或者 CSS 表达式来提取 HTML 中的数据。

XPath 是一门用来在 XML 文件中选择节点的语言,也可以用在 HTML 上。CSS 是一门将 HTML 文档样式化的语言。选择器由它定义,并与特定的 HTML 元素的样式相关连。

Scrapy 选择器构建于 lxml 库之上。

构造选择器

Scrapy 选择器是 Selector 通过传递文本或 TextResponse 对象构造的类的实例。它根据输入类型自动选择最佳的解析规则(XML 与 HTML)。

>>> from scrapy.selector import Selector
>>> from scrapy.http import HtmlResponse

以文字构造示例如下:

>>> body = '<html><body><span>good</span></body></html>'
>>> Selector(text=body).xpath('//span/text()').extract()
[u'good']

以 response 构造示例如下:

>>> response = HtmlResponse(url='http://example.com', body=body)
>>> Selector(response=response).xpath('//span/text()').extract()
[u'good']

为了方便起见,response 对象以 .selector 属性提供了一个 selector, 您可以随时使用该快捷方法:

>>> response.selector.xpath('//span/text()').extract()
[u'good']

嵌套选择器

选择器方法 .xpath() 或 .css() 返回相同类型的选择器列表,因此你也可以对这些选择器调用选择器方法。

xpath()

XPath 是用于选择 XML 文档中的节点的语言,其也可以与 HTML 一起使用。

XPath 常用的路径表达式

表达式 描述 实例
nodename 选取 nodename 节点的所有子节点 //div
/ 从根节点选取 /div
// 选取所有的节点,不考虑他们的位置 //div
. 选取当前节点 ./div
.. 选取当前节点的父节点 ..
@ 选取属性 //@calss

举例元素标签为 artical 标签:

语法 说明
artical 选取所有 artical 元素的子节点
/artical 选取根元素 artical
./artical 选取当前元素下的 artical
../artical 选取父元素下的 artical
artical/a 选取所有属于 artical 的子元素 a 元素
//div 选取所有 div 子元素,无论 div 在任何地方
artical//div 选取所有属于 artical 的 div 元素,无论 div 元素在 artical 的任何位置
//@class 选取所有名为 class 的属性的
a/@href 选取 a 标签的 href 属性
a/text() 选取 a 标签下的文本
string(.) 解析出当前节点下所有文字
string(..) 解析出父节点下所有文字

谓语指定的值

谓语被嵌在方括号内,用来查找某个特定的节点或包含某个指定的值的节点:

语法 说明
/artical/div[1] 选取所有属于 artical 子元素的第一个 div 元素
/artical/div[last()] 选取所有属于 artical 子元素的最后一个 div 元素
/artical/div[last()-1] 选取所有属于 artical 子元素的倒数第2个 div 元素
/artical/div[position()<3] 选取所有属于 artical 子元素的前2个 div 元素
//div[@class] 选取所有拥有属性为 class 的 div 节点
//div[@class=”main”] 选取所有 div 下 class 属性为 main 的 div 节点
//div[price>3.5] 选取所有 div 下元素值 price 大于3.5的节点

XPath 通配符

XPath 通过通配符来选取未知的 XML 元素:

表达式 结果
//* 选取所有元素
//div/* 选取所有属于 div 元素的所有子节点
//div[@*] 选取所有带属性的元素

XPath 取多个路径

使用 | 运算符可以选取多个路径:

表达式 结果
//div | //table 选取文档中所有的div和table节点
//div/a | //div/p 选取所有div元素的a和p 元素
artical/div/pl | //span 选取所有div下的pl和文档中所有span

XPath 轴

轴名称 表达式 描述
ancestor ./ancestor::* 选取当前节点的所有先辈节点(父、祖父)
ancestor-or-self ./ancestor-or-self::* 选取当前节点的所有先辈节点以及节点本身
descendant ./descendant::* 返回当前节点的所有后代节点(子节点、孙节点)
child ./child::* 返回当前节点的所有子节点
parent ./parent::* 选取当前节点的父节点
following ./following::* 选取文档中当前节点结束标签后的所有节点
following-sibling ./following-sibling::* 选取当前节点之后的兄弟节点
preceding ./preceding::* 选取文档中当前节点开始标签前的所有节点
preceding-sibling ./preceding-sibling::* 选取当前节点之前的兄弟节点
self ./self::* 选取当前节点
attribute ./attribute::* 选取当前节点的所有属性

XPath 功能函数

使用功能函数能够更好的进行模糊搜索:

函数 用法 解释
starts-with //div[starts-with(@id,”ma”)] 选取 id 值以 ma 开头的 div 节点
contains //div[contains(@id,”ma”)] 选取所有 id 值包含 ma 的 div 节点
and //div[contains(@id,”ma”) and contains(@id,”in”)] 选取 id 值包含 ma 和 in 的 div 节点
text() //div[contains(text(),”ma”)] 选取节点文本包含 ma 的 div 节点

css()

CSS 是一种用于将样式应用于 HTML 文档的语言。它定义了选择器以将这些样式与特定的 HTML 元素相关联。

语法 说明
* 选择所有节点
#container 选择 id 为 container 的节点
.container 选择所有 class 包含 container 的节点
div,p 选择所有 div 元素所有 p 元素
li a 选取所有 li 下所有 a 节点
ul + p 选取 ul 后面的第一个 p 元素
div#container > ul 选取 id 为 container 的 div 的第一个ul子元素
ul ~p 选取与 ul 相邻的所有 p 元素
a[title] 选取所有有 title 属性的 a 元素
a[href=”http://baidu.com”] 选取所有 href 属性为 http://baidu.com 的 a 元素
a[href*=”baidu”] 选取所有 href 属性值中包含 baidu 的 a 元素
a[href^=”http”] 选取所有 href 属性值中以 http 开头的 a 元素
a[href$=”.jpg”] 选取所有 href 属性值中以 .jpg 结尾的 a 元素
input[type=radio]:checked 选择选中的 radio 的元素
div:not(#container) 选取所有 id 为非 container 的 div 属性
li:nth-child(3) 选取第三个 li 元素
li:nth-child(2n) 选取第偶数个 li 元素
a::attr(href) 选取 a 标签的 href 属性
a::text 选取 a 标签下的文本