Scrapy概述
Scrapy 是一个基于 Twisted 的异步处理框架,是纯 Python 实现的爬虫框架,其架构清晰, 模块之间的耦合程度低,可扩展性极强,可以灵活完成各种需求。 我们只需要定制开发几个模块就可以轻松实现一个爬虫。它可以用来抓取Web站点并从页面中提取结构化的数据,被广泛的用于数据挖掘、数据监测和自动化测试等领域。下图展示了Scrapy的基本架构,其中包含了主要组件和系统的数据处理流程(图中带数字的红色箭头)。
组件
- Scrapy引擎(Engine):Scrapy引擎是用来控制整个系统的数据处理流程。(数据流处理、触发事物、核心)
- 调度器(Scheduler):调度器从Scrapy引擎接受请求并排序列入队列,并在Scrapy引擎发出请求后返还给它们。
- 下载器(Downloader):下载器的主要职责是抓取网页并将网页内容返还给蜘蛛(Spiders)。
- 蜘蛛(Spiders):蜘蛛是有Scrapy用户自定义的用来解析网页并抓取特定URL返回的内容的类,每个蜘蛛都能处理一个域名或一组域名,简单的说就是用来定义特定网站的抓取和解析规则。(负责解析响应,生成提取结果和新的请求)
- 条目管道(Item Pipeline):条目管道的主要责任是负责处理有蜘蛛从网页中抽取的数据条目,它的主要任务是清理、验证和存储数据。当页面被蜘蛛解析后,将被发送到条目管道,并经过几个特定的次序处理数据。每个条目管道组件都是一个Python类,它们获取了数据条目并执行对数据条目进行处理的方法,同时还需要确定是否需要在条目管道中继续执行下一步或是直接丢弃掉不处理。条目管道通常执行的任务有:清理HTML数据、验证解析到的数据(检查条目是否包含必要的字段)、检查是不是重复数据(如果重复就丢弃)、将解析到的数据存储到数据库(关系型数据库或NoSQL数据库)中。
- 中间件(Middlewares):中间件是介于Scrapy引擎和其他组件之间的一个钩子框架,主要是为了提供自定义的代码来拓展Scrapy的功能,包括下载器中间件和蜘蛛中间件。
数据处理流程
Scrapy的整个数据处理流程由Scrapy引擎进行控制,通常的运转流程包括以下的步骤:
引擎询问蜘蛛需要处理哪个网站,并让蜘蛛将第一个需要处理的URL交给它。
引擎让调度器将需要处理的URL放在队列中。
引擎从调度那获取接下来进行爬取的页面。
调度将下一个爬取的URL返回给引擎,引擎将它通过下载中间件发送到下载器。
当网页被下载器下载完成以后,响应内容通过下载中间件被发送到引擎;如果下载失败了,引擎会通知调度器记录这个URL,待会再重新下载。
引擎收到下载器的响应并将它通过蜘蛛中间件发送到蜘蛛进行处理。
蜘蛛处理响应并返回爬取到的数据条目,此外还要将需要跟进的新的URL发送给引擎。
引擎将抓取到的数据条目送入条目管道,把新的URL发送给调度器放入队列中。
上述操作中的2-8步会一直重复直到调度器中没有需要请求的URL,爬虫停止工作。
安装Scrapy
推荐使用Anacinda安装:
conda install Scrapy
直接在已有的Python环境中安装Scrapy:
a. 安装lxml
pip install lxml
b.安装pyOpenSSL
下载wheel文件
使用pip install后接下载文件路径完成安装
c.安装Twisted
使用pip install后接下载文件路径完成安装
d.安装PyWin32
下载wheel文件
使用pip install后接下载文件路径完成安装
也可以尝试直接使用pip install pywin32
命令尝试,如果能够成功便无须下载wheel文件
e.执行pip install scrapy
简单使用
创建项目
scrapy startproject book
创建爬虫
scrapy genspider douban book.douban.com
genspider后的两个参数:第一个表示爬虫的名称,第二个表示网站的域名
使用编译器打开创建的项目
添加爬虫内容
爬取目标:编程类图书
分析网络请求:https://book.douban.com/tag/%E7%BC%96%E7%A8%8B?start=0&type=T(get请求、start后面的数字表示当前页数的20倍。通过循环生成页数即可模拟翻页发出的请求。因为内容比较多,本次只爬取前三十页作为演示)
分析网页结构:每一页有二十本图书的信息,每本图书信息保存在一个li标签中,所以首先拿到li标签,在进行下一步操作。继续获取图书链接,书籍名称,基本信息及简介。
爬取内容:图书链接,书籍名称,基本信息及简介。
def start_requests(self):
headers = {
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)',
'Accept': 'application/json, text/plain, */*',
'Accept-Encoding': 'gzip, deflate, sdch',
'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4,zh-TW;q=0.2,mt;q=0.2',
'Connection': 'keep-alive',
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
}
for i in range(33):
yield scrapy.Request(url='https://book.douban.com/tag/%E7%BC%96%E7%A8%8B?start={}&type=T'.format(i),
headers=headers,
method='GET',
callback=self.parse,
)
创建对象
class BookItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
book_link = scrapy.Field()
book_name = scrapy.Field()
book_info = scrapy.Field()
book_explain = scrapy.Field()
解析对象
def parse(self, response):
book_all = response.xpath('//*[@id="subject_list"]/ul/li')
for book_one in book_all:
book = BookItem()
book['book_link'] = book_one.xpath('./div[@class="info"]/h2/a/@href').extract_first().strip()
book['book_name'] = book_one.xpath('./div[@class="info"]/h2/a/@title').extract_first().strip()
book['book_info'] = book_one.xpath('./div[@class="info"]/div[@class="pub"]/text()').extract_first().strip()
book['book_explain'] = book_one.xpath('./div[@class="info"]/p/text()').extract_first().strip()
yield book
修改配置文件
ROBOTSTXT_OBEY = False
SPIDER_MIDDLEWARES = {
'book.middlewares.BookSpiderMiddleware': 543,
}
FEED_EXPORT_ENCODING = 'utf-8'
执行启动爬虫的命令,并保存爬取内容
scrapy crawl douban -o result.json
爬取内容部分展示