当抓取网页时,你做的最常见的任务是从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 标签下的文本 |