Scrapy Selectors,从网页中提取数据有很多方法。Scrapy
使用了一种基于XPATH
和 CSS
表达式机制:Scrapy Selectors
,这里给出XPath表达式的例子及对应的含义。
Selectors 简介
从网页中提取数据有很多方法。Scrapy
使用了一种基于 XPath 和 CSS 表达式机制:Scrapy Selectors
,这里给出XPath表达式的例子及对应的含义:
/html/head/title
: 选择HTML文档中<head>
标签内的<title>
元素/html/head/title/text()
: 选择上面提到的<title>
元素的文字//td
: 选择所有的<td>
元素//div[@class="mine"]
: 选择所有具有class="mine"
属性的div
元素
上边仅仅是几个简单的XPath例子,XPath实际上要比这强大的多。为了配合XPath,Scrapy除了提供了 Selector
之外,还提供了方法来避免每次从response中提取数据时生成selector的麻烦。
Selector有四个基本的方法(点击相应的方法可以看到详细的API文档):
xpath()
: 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表 。css()
: 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表.extract()
: 序列化该节点为unicode字符串并返回list。re()
: 根据传入的正则表达式对数据进行提取,返回unicode字符串list列表。
在Shell中尝试Selector选择器
为了介绍Selector的使用方法,接下来我们将要使用内置的 Scrapy shell
。Scrapy Shell
需要您预装好IPython
(一个扩展的Python终端)。
您需要进入项目的根目录,执行下列命令来启动shell:
scrapy shell "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/"
如图所示:
注解
当您在终端运行Scrapy时,请一定记得给url地址加上引号,否则包含参数的url(例如 &
字符)会导致Scrapy运行失败。
shell的输出类似:
[ ... Scrapy log here ... ]
2014-01-23 17:11:42-0400 [default] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> (referer: None)
[s] Available Scrapy objects:
[s] crawler <scrapy.crawler.Crawler object at 0x3636b50>
[s] item {}
[s] request <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>
[s] response <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>
[s] settings <scrapy.settings.Settings object at 0x3fadc50>
[s] spider <Spider 'default' at 0x3cebf50>
[s] Useful shortcuts:
[s] shelp() Shell help (print this help)
[s] fetch(req_or_url) Fetch request (or URL) and update local objects
[s] view(response) View response in a browser
In [1]:
当shell载入后,您将得到一个包含response
数据的本地 response
变量。输入 response.body
将输出response的包体, 输出 response.headers
可以看到response的包头。
更为重要的是,当输入 response.selector
时,您将获取到一个可以用于查询返回数据的selector
(选择器),以及映射到 response.selector.xpath()
、 response.selector.css()
的快捷方法: response.xpath()
和 response.css()
。
同时,shell根据response提前初始化了变量 sel
。该selector根据response的类型自动选择最合适的分析规则(XML vs HTML)。
让我们来试试:
In [1]: response.xpath('//title')
Out[1]: [<Selector xpath='//title' data=u'<title>Open Directory - Computers: Progr'>]
In [2]: response.xpath('//title').extract()
Out[2]: [u'<title>Open Directory - Computers: Programming: Languages: Python: Books</title>']
In [3]: response.xpath('//title/text()')
Out[3]: [<Selector xpath='//title/text()' data=u'Open Directory - Computers: Programming:'>]
In [4]: response.xpath('//title/text()').extract()
Out[4]: [u'Open Directory - Computers: Programming: Languages: Python: Books']
In [5]: response.xpath('//title/text()').re('(\w+):')
Out[5]: [u'Computers', u'Programming', u'Languages', u'Python']
提取数据
现在,我们来尝试从这些页面中提取些有用的数据。您可以在终端中输入 response.body
来观察HTML源码并确定合适的XPath表达式。不过,这任务非常无聊且不易,您可以考虑使用Firefox
的Firebug
扩展来使得工作更为轻松。详情请参考后续章节 。
在查看了网页的源码后,您会发现网站的信息是被包含在 第二个 <ul>
元素中。我们可以通过这段代码选择该页面中网站列表里所有 <li>
元素:
response.xpath('//ul/li')
网站的描述:
response.xpath('//ul/li/text()').extract()
网站的标题:
response.xpath('//ul/li/a/text()').extract()
网站的链接:
response.xpath('//ul/li/a/@href').extract()
之前提到过,每个 .xpath()
调用返回selector组成的list,因此我们可以拼接更多的 .xpath()
来进一步获取某个节点。我们将在下边使用这样的特性:
for sel in response.xpath('//ul/li'):
title = sel.xpath('a/text()').extract()
link = sel.xpath('a/@href').extract()
desc = sel.xpath('text()').extract()
print title, link, desc
在我们的spider
中加入这段代码:
import scrapy
class DmozSpider(scrapy.Spider):
name = "dmoz"
allowed_domains = ["dmoz.org"]
start_urls = [
"http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
"http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
]
def parse(self, response):
for sel in response.xpath('//ul/li'):
title = sel.xpath('a/text()').extract()
link = sel.xpath('a/@href').extract()
desc = sel.xpath('text()').extract()
print title, link, desc
现在尝试再次爬取dmoz.org
,您将看到爬取到的网站信息被成功输出:
scrapy crawl dmoz