前言
——不要重复造轮子。
我曾经自己写过在网上爬取网页的应用python爬虫,做的无非是将各种网站抽取资料入库整理。
但是,我面临过的问题(线程数量控制、文档解析、持久化等等),都需要一一自己解决,做下去之后,发现自己其实是在做一个一个的轮子,代码很多,而且写得不好。
其实轮子早有人造,而且造的很好,对于上述的一些问题,我们都可以用 Scrapy http://scrapy.org/ 这个轮子来解决,然后专注于我们实现的逻辑。
下面我们来过一下 scrapy 的教程,等这些一件件神器都玩弄于股掌之中时,就可以锻造自己的神器了!
教程地址:http://doc.scrapy.org/en/1.0/
为了让速度跑得快一些,这次对于叙述性的内容直接略过,只留重点。
Scrapy 一瞥(Scrapy at a glance)
source: http://doc.scrapy.org/en/1.0/intro/overview.html
首先我们需要装上,我的是 ubuntu,参照 http://doc.scrapy.org/en/1.0/topics/ubuntu.html#topics-ubuntu 其他请自行看文档。
安装完确保运行 scrapy --version
能够得到正确的显示。
scrapy 貌似不支持 py3,这是一个极为蛋疼的问题,不过这里先不管。
首先直接上一个例子:
import scrapy
class StackOverflowSpider(scrapy.Spider):
name = 'stackoverflow'
start_urls = ['http://stackoverflow.com/questions?sort=votes']
def parse(self, response):
for href in response.css('.question-summary h3 a::attr(href)'):
full_url = response.urljoin(href.extract())
yield scrapy.Request(full_url, callback=self.parse_question)
def parse_question(self, response):
yield {
'title': response.css('h1 a::text').extract()[0],
'votes': response.css('.question .vote-count-post::text').extract()[0],
'body': response.css('.question .post-text').extract()[0],
'tags': response.css('.question .post-tag::text').extract(),
'link': response.url,
}
随便放到一个脚本文件里面 stackoverflow_spider.py
,执行:
scrapy runspider stackoverflow_spider.py -o top-stackoverflow-questions.json
等待片刻,就可以发现输出的 top-stackoverflow-questions.json
文件已经把内容爬好放好了。
主要的工作流程:
- 执行命令
scrapy runspider somfile.py
,先查看蜘蛛定义,然后用爬虫引擎执行; - 从
start_urls
开始,每抓到一个,调用默认的parse
方法; - 抓到
start_urls
用 parse 方法解析,然后从内容抽取链接再抓; - 再抓动作是通过
yield scrapy.Request(full_url, callback=self.parse_question)
实现的; - 于是再抓的回调就不是
parse
方法,而是parse_question
方法; parse_question
yield 出来的东西会放到结果集里面最终被输出出来;
后面的话主要是介绍 scrapy 的一些特性,简要列举:
- 异步,并发,所以快
- 灵活可配置,例如延时、限制域名或者 IP 的线程,甚至是自动限流
- 内置的 HTML/XML 解析器,支持 CSS 和 XPATH 方式
- 交互的控制台便于调试
- 原生支持各种导出(JSON/CSV/XML)以及各种存储引擎
- 原生编码支持,自动检测
- 强扩展性,允许在此基础上做插件
- 广泛的内生扩展和中间件来处理这些问题:
- cookie / session
- HTTP 特性,例如压缩、验证、缓存
- UA 欺骗
- robots.txt
- 抓取深度限制
- 更多
后面就是具体的教程
PS:关于 Python3 支持
http://www.zhihu.com/question/29412307
https://github.com/scrapy/scrapy/issues/263
目前 scrapy 真的只能支持 2(截至发稿 2015 年 11 月 30 日)
但是团队已经在努力将这个事情在日程上推进,而且就最近的消息看来,日子应该不远了,因为最大的障碍,依赖项 twisted 的 py3 版本已经推出,请边学边静候佳音。