从页面中提取数据的核心技术是HTTP文本解析,在python中常用的模块处理:
BeautifulSoup 非常流行的解析库,API简单,但解析的速度慢。
lxml 是一套使用c语言编写的xml解析库,解析速度快,API相对比较复杂。
Scrapy中的Selector类是基于lxml库建立的,并且简化了API接口。在使用的过程中先使用xpath或者css选择器选中页面中要提取的数据,然后进行提取。
提取数据
调用Selector或者SelectList对象的以下几种方法可将选中的内容进行提取
extract() 返回选中内容的Unicode字符串。
extract_first() SelectorList专有,返回其中第一个Selector对象调用extract方法。通常SelectorList中只含有一个Selector对象的时候选择调用该方法。
re() 使用正则表达式来提取选中内容中的某部分。
举个例子
selector.xpath('.//b/text()') .extract #[‘价格:99.00元’,‘价格:88.00元’,‘价格:88.00元’]
selector.xpath('.//b/text()').re('\d+\.\d+') #[ '99.00','88.00','88.00']
re_first() 返回SelectorList对象中的第一个Selector对象调用re方法。
selector.xpath('.//b/text()').re_first('\d+\.\d+') # '99.00'
实际的开发过程中,几乎不需要手动创建Selector对象,,Response对象以自身参数自动创建Selector对象
response.xpath('.//h1/text').extract() # [ 'song','shi','chao']
response.css('li::text').extract() # [ 'song','shi','chao']
xpath选择器
xpath即xml路径语言,用来确定xml文档中某个部分的语言,xml文档(html属于xml)是一系列节点构成的树。
基础语法
/ 选中文档的根 描述一个从根开始的绝对路径 ./表示从当前节点选取 (比如提取了一部分,还需要从提取出来里面进行提取就会使用,如果不加 . 会从整个文档中开始提取)
. 选中当前节点 用来描述相对路径
.. 选中当前节点的父节点 用来描述相对路径
ELEMENT 选中子节点中所有的ELEMENT元素节点
//ELEMENT 选中子孙节点中所有的ELEMENT元素节点
* 选中所有元素子节点
text() 选中所有文本子节点
@ATTR 选中名为ATTR的属性节点
@* 选中所有的属性节点
[谓语] 谓语用来查找某个特定的节点或者包含某个特定值的节点
举例
response.xpath('/html/body/div') #选取body下的所有div
response.xpath('//a') #选中文档所有a
response.xpath('/html/body//div') #选中body下的所有节点中的div,无论在什么位置
response.xpath('//a/text()') #选取所有a的文本
response.xpath('/html/div/*') #选取div的所有元素子节点
response.xpath('//div/*/img') #选取div孙节点的所有img
response.xpath('//img/@src') #选取所有img的src属性
response.xpath('//a[1]/img/@*') #选取第一个a下img的所有属性
response.xpath('//a[2]') #所有a中的第2个
response.xpath('//a[last()]') #所有a中的最后一个 ('/a[last()-1]')#倒第二个 ('//a[position()<=3]')#使用position函数选中前三个 ('//div[@id]')#选中所有含有id属性的div ('//div[@id="song"]')#选中所有id属性为song的div
response.xpath('//p[contains(@class,'song')]') #选择class属性中含有‘song’的p元素
response.xpath('//div/a | //div/p') 或者,页面中可能是a可能是p
css选择器
css即层叠样式表,选择器不如xpath强大,原理就是选择的时候翻译成xpath表达式在调用xpath方法。
* 选择所有节点
#container 选择id为container的节点
.container 选择class包含container的节点
li a 选择 所有 li 下的所有 a 节点
ul + p 选择所有ul后面的第一个p元素
#container > ul 选择id为container的第一个ul节点
a[class] 选取所有有class属性的a元素
a[href="http://b.com"] 含有href="http://b.com"的a元素
a[href*='job'] 包含job的a元素
a[href^='https'] 开头是https的a元素
a[href$='cn'] 结尾是cn的a元素
response.css('div a::text').extract() 所有div下所有a的文本
response.css('div a::attr(href)').extract() href的值
response.css('div>a:nth-child(1)') 选中每个div的第一个a > 会设定只在子节点中找,不会到孙节点中
response.css('div:not(#container)') 选取所有id不是container的div
response.css('div:first-child>a:last-child') 第一个div中最后一个a