Python进阶之Scrapy框架入门
1. Scrapy入门
1.1 什么是Scrapy
- Scrapy是一个适用爬取网站数据、提取结构性数据的应用程序框架,它可以应用在广泛领域:Scrapy 常应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。通常我们可以很简单的通过 Scrapy 框架实现一个爬虫,抓取指定网站的内容或图片。
- Scrapy使用了Twisted异步网络框架,可以大大提高数据抓取的效率
- 异步:调用在发出之后,这个调用就直接返回,不管有无结果
- 非阻塞:关注的是程序在等待调用结果时的状态,指在不能立刻得到结果之前,该调用不会阻塞当前线程
- 异步过程使得程序充分利用了阻塞等待的时间,使得程序在同样的时间可以干更多的事情,从而提高了执行效率
1.2 Scrapy架构
-
一个标准的Scrapy架构由Scrapy Engine(引擎),Scheduler(调度器),Downloader(下载器),Spider(爬虫),Item Pipeline(管道),Downloader Middlewares(下载中间件),Spider Middlewares(Spider中间件)组成,如下图:
-
Scrapy Engine(引擎):负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。
-
Scheduler(调度器):它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。
-
Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理。
-
Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器)。
-
Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方。
-
Downloader Middlewares(下载中间件):一个可以自定义扩展下载功能的组件。
-
Spider Middlewares(Spider中间件):一个可以自定扩展和操作引擎和Spider中间通信的功能组件。
1.3 安装Scrapy
-
下载:
-
安装:
- 在windows下安装:
- 命令行安装:
pip install Scrapy
- whl安装,先安装scrapy的whl,再安装对应的twisted的whl
pip install xxxxxxx.whl
- 安装指南
- 在windows下安装:
-
技术文档
2. Scrapy项目初探
2.1 创建一个Scrapy项目
-
创建Scrapy项目,startproject后的项目名称可以按照需要指定
scrapy startproject mySpider
运行后提示:
You can start your first spider with:
cd mySpider
scrapy genspider example example.com -
创建爬虫,命令行运行cd mySpider进入爬虫目录后
scrapy genspider demo "demo.cn"
- demo为爬虫项目名称,在”./mySpider/spiders/“目录生成一个名为demo.py的文件
- "demo.cn"为需要爬取的网站域名
运行后提示:
Created spider ‘demo’ using template ‘basic’ in module:
mySpider.spiders.demo -
完善数据,完善爬虫项目数据,把爬虫代码添加到demo.py中
-
保存数据,修改pipelines.py,把数据保存的代码添加到文件中
- 1 可能会有多个spider,不同的pipeline处理不同的item的内容
- 2 一个spider的内容可以要做不同的操作,比如存入不同的数据库中
注意:- pipeline的权重越小优先级越高
- pipeline中process_item方法名不能修改为其他的名称
2.2 运行爬虫
-
在命令中运行爬虫, # xxx是爬虫的名字,与爬虫项目名保持一致
scrapy crawl XXX
-
在pycharm中运行爬虫,
from scrapy import cmdline cmdline.execute("scrapy crawl xxx".split())
3. Scrapy抓取豆瓣数据实例
- 通过一个抓取豆瓣的scrapy项目,简单介绍scrapy项目的开发逻辑
3.1 创建项目和爬虫
- 创建scrapy项目
scrapy startproject spider
- 进入项目目录
cd spider
- 创建爬虫项目
scrapy genspider douban “douban.com”
3.2 douban.py
- 注意:
- parse中的response是一个可以使用xpath的对象,可以直接获取html数据
- 利用Scrapy里边的extract_first()或get()取数据
- get()获取有标签的数据
- extract_first()获取文本数据,注意加(),否则会输出错误数据
- bound method SelectorList.get of - 抓取结果保存成字典方便引用和保存
- 返回数据用生成器形式yield返回,尽量不用return.这样可以节省内存资源
import scrapy
# from scrapy.http.response.html import HtmlResponse
class DoubanSpider(scrapy.Spider):
name = 'douban'
# 允许的域名范围,不需要加协议名
allowed_domains = ['douban.com']
# 可以修改
start_urls = ['http://douban.com/']
def parse(self, response):
# print('-' * 50)
# print(response)
# print(type(response))
# print('-' * 50)
# response状态码200,说明已经抓到了html
li_list = response.xpath('//div[@class="side-links nav-anon"]/ul//li')
# 定义字典收集数据
item = {}
for li in li_list:
# 利用Scrapy里边的extract_first()和get()取数据
# get()获取有标签的数据
# extract_first()获取文本数据,注意加(),否则会输出错
# bound method SelectorList.get of
# 发现输出缺少购书单,购书单在em标签下
item['name'] = li.xpath('a/em/text()').extract_first()
# 增加判断,如果找不到则执行下边的代码
if item['name'] == None:
# 其他标签都在a标签下
item['name'] = li.xpath('a/text()').extract_first()
# print(item)
# 用yield生成器返回数据,节省内存资源
yield item
# print(li_list)
3.3 settings.py
- 注意:
- 设定LOG-LEVEL可以简化日志输出内容,调试时更为方便
- 设定DEFAULT_REQUEST_HEADERS请求头
- 根据实际需要确定ROBOTSTXT_OBEY = True是否要注释掉
- 使用pipeline的时候要在settings里把# Configure item pipelines下边的ITEM_PIPELINES代码打开
BOT_NAME = 'spider'
SPIDER_MODULES = ['spider.spiders']
NEWSPIDER_MODULE = 'spider.spiders'
# 日志输出简化
LOG_LEVEL = 'WARNING'
# Override the default request headers:
DEFAULT_REQUEST_HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3820.400 QQBrowser/10.6.4255.400',
'Accept-Language': 'en',
}
# Obey robots.txt rules
# 注释掉了遵守robots协议
# ROBOTSTXT_OBEY = True
# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'spider.pipelines.SpiderPipeline': 300,
'spider.pipelines.SpiderPipeline1': 301,
}
3.4 pipeline.py
- 注意:
- 使用pipeline的时候要在settings里把# Configure item pipelines下边的ITEM_PIPELINES代码打开
- ensure_ascii = False使json.dumps()处理支持为中文输出
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
# 注意使用pipeline要在设置里边打开ITEM_PIPELINES setting
import json
class SpiderPipeline:
def __init__(self):
self.f = open('douban.json','w',encoding='utf-8')
# 爬虫的打开方法
def open_spider(self,item):
print('爬虫开始了')
def process_item(self, item, spider):
# print(item)
# json.dumps() 将字典形式数据转化成字符串 默认使用ascii编码
# ensure_ascii = False 使item_json为中文形式
# json.loads() 将字符串形式数据转化为字典
# 把item字典数据转化为item_json字符串
item['hello'] = 'world'
item_json = json.dumps(item,ensure_ascii=False)
self.f.write(item_json+'\n')
return item
# 爬虫关闭的方法
def close_spider(self,item):
print('爬虫结束了')
self.f.close()
# 用第二个pipeline进行打印结果
# pipeline的优先级按照settings里的ITEM_PIPELINES中的数字大小顺序来定义优先级
class SpiderPipeline1:
def process_item(self, item, spider):
print(item)
3.5 start.py
- 可以通过windows命令行输入scrapy crawl douban运行程序
- 也可以调用scrapy中的cmdline.execute()创建python启动程序,注意后边有个.split()分隔
# !/usr/bin/python
# Filename: start.py
# Data : 2020/08/25
# Author : --king--
# ctrl+alt+L自动加空格格式化
from scrapy import cmdline
# cmdline.execute(['scrapy','crawl','douban'])
cmdline.execute('scrapy crawl douban'.split())