1、 Scrapy选择器XPath和CSS
scrapy提取数据有自己的一套机制,他们被称为选择器(selector),通过特定的XPath或者CSS表达式来"选择""HTML文件中的某个部分"
Xpath是一门在XML文件中选择节点的语言,也可以用在HTML,CSS是一门将HTML文档样式化的语言,选择器由他定义,并于特定的HTML元素的样式相关联
scrapy的选择器构建与lxml库之上,这意味着他们的速度和解析准确性上非常相似。
(1)、 Xpath选择器
在Xpath中有7种类型的节点:元素,属性,文本,命名空间,处理指令,注释以及文档节点。XML文档是被作为节点数来对待的。
创建一个superHero.xml文档
<superHero>
<class>
<name lang="en">Tony Stark</name>
<alias>Iron Man</alias>
<sex>male</sex>
<birthday>1969</birthday>
<age>47</age>
</class>
<class>
<name lang="en">Peter Benjamin</name>
<alias>Spider Man</alias>
<sex>male</sex>
<birthday>unknown</birthday>
<age>unknown</age>
</class>
<class>
<name lang="en">Steven Rogers</name>
<alias>Captain Amercia</alias>
<sex>male</sex>
<birthday>19200704</birthday>
<age>96</age>
</class>
</superHero>
在这个superHero中,<superHero>是文档节点,<alias>是元素节点,lang="en"是属性节点。
Xpath使用路径表达式在XML文档中选取节点。下表列出了最常用的路径表达式
表达式 | 描述 |
nodeName | 选取此节点的所有节点 |
/ | 从根结点选取 |
// | 从匹配选择的当前节点选择文档中的节点,不考虑他们的位置 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取节点 |
* | 匹配任何元素节点 |
@* | 匹配任何元素节点 |
Node() | 匹配任何类型的节点 |
代码
>>> from scrapy.selector import Selector >>> with open(".\selectors/superHero.xml",'r') as f: ... body = f.read() ... >>> body '<superHero>\n<class>\n<name lang="en">Tony Stark</name>\n<alias>Iron Man</alias>\n <sex>male</sex>\n<birthday>1969</birthday>\n<age>47</age>\n</class>\n<class>\n<name lang="en">Peter Benjamin</name>\n<alias>Spider Man</alias>\n <sex>male</sex>\n<birthday>unknown</birthday>\n<age>unknown</age>\n</class>\n<class>\n<name lang="en">Steven Rogers</name>\n<alias>Captain Amercia</alias>\n <sex>male</sex>\n<birthday>19200704</birthday>\n <age>96</age>\n</class>\n</superHero>\n' >>> Selector(text=body).xpath('/*').extract() [u'<html><body><superhero><class><name lang="en">Tony Stark</name><alias>Iron Man</alias><sex>male</sex><birthday>1969</birthday><age>47</age></class><class><name lang="en">Peter Benjamin< /name><alias>Spider Man</alias><sex>male</sex><birthday>unknown</birthday><age>unknown</age></class><class><name lang="en">Steven Rogers</name><alias>Captain Amercia</alias><sex>male</sex> <birthday>19200704</birthday><age>96</age></class></superhero></body></html>'] |
提示:
选择器从根结点选择所有节点时得到的数据和直接从文件中读取的数据有点不一样,因为示例文件并不是一个标准的html文件,所以在选择器中被自动添加了html和body标签,也就是说在选择器看来,示例文件的根节点并不是superHero
代码示例
#!/usr/bin/env python # coding:utf-8
__author__ = 'cmustard'
from scrapy.selector import Selector
with open("superHero.xml","r") as f: body = f.read()
result = Selector(text=body).xpath('/*').extract() print result print(u"采集super中第一个class的内容") print Selector(text=body).xpath('/html/body/superhero/class[1]').extract()
print(u"采集super中最后一个class的内容") print Selector(text=body).xpath('/html/body/superhero/class[last()]').extract()
print(u"采集super中name属性为en的数据") print Selector(text=body).xpath('//name[@lang="en"]').extract()
print(u"采集super中倒数第二个class的name节点的文本") print Selector(text=body).xpath('/html/body/superhero/class[last()-1]/name/text()').extract()
print(u"以下展示的是嵌套选择器") subbody = Selector(text=body).xpath('/html/body/superhero/class[last()-1]').extract() print subbody # list
print Selector(text=subbody[0]).xpath('/html/body/class/sex/text()').extract() print Selector(text=subbody[0]).xpath('//class/sex/text()') |
(2)、CSS选择器
CSS规则由两个主要的部分构成:选择器,以及一条或多条声明
Selector {declaration1; declearation2;…declearationN } |
CSS常用的选择器
.class | .intro | 选择class='intro'的所有元素 |
#id | #firstname | 选择id='firstname'的所有元素 |
* | * | 选择所有元素 |
Element | P | 选择所有<p>元素 |
Element,element | Div,p | 选择所有<div>元素和所有<p>元素 |
Element,element | Div p | 选择<div>元素内部的所有p元素 |
[attribute] | [target] | 选择带有target属性的所有元素 |
[attribute=value] | [target=_blank] | 选择target="_blank"的所以元素 |
与Xpath相比较,CSS相对而言更加复杂
print Selector(text=body).css('class').extract() print(u'class 下的所有name节点') print Selector(text=body).css('class name').extract() # class 下的所有name节点
print Selector(text=body).css('class name').extract()[0] print(u'选择带有lang属性的所有元素') print Selector(text=body).css('[lang]').extract() # 选择带有lang属性的所有元素 |
(3)、其他选择器
Xpath选择器还有一个.re()方法,用于通过正则表达式来提前数据,然而,不同于使用.xpath()或者.css方法,.re()返回unicode字符串的列表,所以无法构造嵌套式的.re()调用
print(u'其他选择器') print Selector(text=body).xpath('/html/body/superhero/class[1]').re('>.*?<') |
2、爬虫示例