在你抓取页面的时候,最普遍的任务就是从HTML源码中提取数据data了。python中提供了很多的第三方库提供对页面数据的提取和解析。
-
BeautifulSoup
-
lxml
Scrapy提供了Selector实现随Html文档内容的提取
-
XPath
-
CSS
Scrapy selector 继承 Selector类,
>>>from scrapy.selectro import Selector
>>>from scrapy.http import HtmlRespodse
>>> response = HtmlResponse(url='http://example.com', body=body)
>>>Selector(response=response).xpath('//span/text()').extract()
>>> response.selector.xpath('//span/text()').extract()
[u'good']
例子:http://doc.scrapy.org/en/latest/_static/selectors-sample1.html
<html>
<head>
<base href='http://example.com/' />
<title>Example website</title>
</head>
<body>
<div id='images'>
<a href='image1.html'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a>
<a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a>
</div>
</body>
</html>
首先利用scrapy 的shell获取网址
scrapy shell http://doc.scrapy.org/en/latest/_static/selectors-sample1.html
利用Xpath或者CSS来提取html文档中的内容
>>> response.xpath('//title/text()')
[<Selector (text) xpath=//title/text()>]
>>> response.css('title::text')
[<Selector (text) xpath=//title/text()>]
可以看到,xpath和css返回的是一个Selector的list实例,而不是一个字符串。
如果你要提取文本数据,需要在selector后加 .extract() 来提取数据。
如果你只想提取第一个匹配的元素,
.extract_first()
获取url和图片src链接
>>> response.xpath('//base/@href').extract()
[u'http://example.com/']
>>> response.css('base::attr(href)').extract()
[u'http://example.com/']
>>> response.xpath('//a[contains(@href, "image")]/@href').extract()
[u'image1.html',
u'image2.html',
>>> response.css('a[href*=image]::attr(href)').extract()
[u'image1.html',
u'image2.html']
>>> response.xpath('//a[contains(@href, "image")]/img/@src').extract()
[u'image1_thumb.jpg',
u'image2_thumb.jpg']
>>> response.css('a[href*=image] img::attr(src)').extract()
[u'image1_thumb.jpg',
u'image2_thumb.jpg']
( .xpath() 和 .css() ) 返回的是selector的一个list,所以可以嵌套使用他们,例如:
>>> links = response.xpath('//a[contains(@href, "image")]')
>>> links.extract()
[u'<a href="image1.html">Name: My image 1 <br><img src="image1_thumb.jpg"></a>',
u'<a href="image2.html">Name: My image 2 <br><img src="image2_thumb.jpg"></a>'
>>> for index, link in enumerate(links):
... args = (index, link.xpath('@href').extract(), link.xpath('img/@src').extract())
... print 'Link number %d points to url %s and image %s' % args
Link number 0 points to url [u'image1.html'] and image [u'image1_thumb.jpg']
Link number 1 points to url [u'image2.html'] and image [u'image2_thumb.jpg']
selector和正则表达式结合使用
在selector中也有正则表达式方法(.re()),但是 **.re() ** 不像 .xpath() 和 .css() 返回一个selector的list, .re() 返回的是一个Unicode的字符串。所以 .re() 不可嵌套使用。
>>> response.xpath('//a[contains(@href, "image")]/text()').re(r'Name:\s*(.*)')
[u'My image 1',
u'My image 2']
>>> response.xpath('//a[contains(@href, "image")]/text()').re_first(r'Name:\s*(.*)')
u'My image 1'
XPath 使用注意事项(相对路径)
注意: 如果你正在嵌套 selectors 和 使用 以 " / " 开始的 xpath 时,xpath 会相对整个document 而不是相对你的selector。
例如:
假设你想提取 在 <div> 标签中所有的 <p> 元素,首先,你先得到 <div> 元素
>>> divs = response.xpath('//div')
如果你使用下面这种方法,相对的是文档中所有的 <p> 元素,而不是 <div> 中的 <p> 元素,
>>> for p in divs.xpath('//p'): # this is wrong - gets all <p> from the whole document
... print p.extract()
正确的使用方法是这样:
>>> for p in divs.xpath('.//p'): # extracts all <p> inside
... print p.extract()
or
>>> for p in divs.xpath('p'):
... print p.extract()