Scrapy简介
Scrapy 是一个开源的Python网络爬虫框架。源码在github上开源,地址。Scrapy简单易学而且非常好用,支持配置、代理分布式爬取、容易扩展而且官方也很活跃。截止目前(2019年8月21日)最新版本为 v1.7.3 。
Scrapy 安装
你需要先安装Python,Scrapy需要 Python 2.7 或者 Python 3.5+ ,通常MacOS会自带Python,其它系统需要自己安装,Python安装不再赘述。
Scrapy由纯Python语言实现,但是需要依赖一些Python包,包括
- lxml:一种高效的XML和HTML解析器,
- parsel:一个HTML / XML数据提取库,基于上面的lxml,
- w3lib:一种处理URL和网页编码多功能辅助
- twisted:一个异步网络框架
- cryptography and pyOpenSSL:处理各种网络级安全需求
由于包依赖版本问题,建议首先安装 virtualenv ,这是一个独立Python运行环境包。
- 全局安装 virtualenv
1 | $ sudo pip install virtualenv |
- 创建独立Python运行环境
1 | $ virtualenv ENV |
- 安装Scrapy
1 | $ pip install scrapy |
在不同的平台上的安装步骤不尽相同,某些平台需要安装平台依赖包,具体请 查看
Scrapy项目创建
- 创建项目&生成爬虫
1 | $ scrapy startproject [PROJECT_NAME] |
[PROJECT_NAME] 是待创建的爬虫项目名
[SPIDER_NAME] 是爬虫名
[SITE_NAME] 是待爬取的初始站点地址
例如我们创建了一个名为 tutorial 的项目,并添加爬虫 top
项目目录如下
1 | tutorial/ |
打开 top.py 可以看到 Scrapy 爬虫文件结构
- name 爬虫名
- allowed_domains 是允许爬取的域名
- start_urls 开始爬取的链接
- start_requests() 开始爬取的链接方法,需要返回 Requests 对象的遍历器或者 Reqeusts 数组
- parse() 爬取后的处理方法
settings 修改
可以在 settings.py 文件中看到常用设置:
- USER_AGENT request的
user-agent
header 中的 user-agent 参数 - ROBOTSTXT_OBEY 是否遵守robots.txt协议,默认
True
- CONCURRENT_REQUESTS 最大并发请求数量
- DEFAULT_REQUEST_HEADERS 覆盖默认请求header 参数
- SPIDER_MIDDLEWARES 爬虫中间件
- DOWNLOADER_MIDDLEWARES 下载中间件
- ITEM_PIPELINES 设置pipeline调用顺序
使用 shell 命令分析待爬取网站
shell命令是Scrapy提供的交互式页面分析工具,类似于一个debug工具,你可以先使用shell分析待爬取的页面然后再执行爬虫。
1 | scrapy shell [SITE_NAME] |
shell命令将会采用settings里的配置来请求地址 [SITE_NAME] ,以下列出一些常用分析命令
- scrapy scrapy模块,包括scrapy.Request, scrapy.Selector等
- crawler scrapy.crawler.Crawler object
- response 返回的响应object
- request 请求的object
- settings 请求的设置
- view(response) 在浏览器中查看获取到页面
- fetch(url[, redicrect=True]) 重新获取url内容并更新当前object
- fetch(req) 获取一个 scrapy.Request 并更新当前object
view(response)
可以在浏览器中查看页面结构。
如果返回的结构和我们期待的有所不同,可以通过 request.replace()
进行修改,例如修改请求方法 request.replace(method='POST')
fetch(req)
常用在对request或settings进行了修改然后重新请求。response
是返回的响应体,这通常是我们需要分析的东西,如果分析的是html,首先最好先执行 view(response)
在浏览器中查看页面结构,找到我们需要获取的 文本/链接 位置。
然后使用 xpath选择器 或者 css选择器 定位我们需要获取的 文本/链接 位置。
例如采用 css选择器 且我们需要获取页面中的所有链接,则可以执行
response.css('a::attr(href).getall()')
如果获取title文本则可以执行
response.css('title::text').get(default='')
fetch(url)
常用来获取下一个待分析的链接
这样就构成了一个完整闭环
另外我们也可以通过1
2from pprint import pprint
pprint(response.headers)
来打印相应object
Scrapy Items
通常我们需要爬取的都是结构化的数据,在 Scrapy 中被称为 Item,在 items.py 中我们需要定义需要爬取的字段,类似 Python dict
1 | name = scrapy.Field() |
Scrapy Item Pipeline
Scrapy支持pipeline来对爬取到的数据进行类似于管道一样的一系列操作。
管道类一般用来进行以下几类操作:
- 清洗 HTML 数据
- 验证爬取到的数据(检查items包括特定的field)
- 检查重复数据
- 将爬取到的数据存储于数据库中
包括以下几分方法
process_item(self, item, spider)
处理item,需要返回处理后的 data dict
open_spider(self, spider)
spider开始时触发的钩子
close_spider(self, spider)
spider结束时触发的钩子
from_crawler(cls, crawler)
类方法,可以通过 crawler.settings 获取 settings.py 里的配置信息
运行爬虫
1 | $ scrapy crawl [SPIDER_NAME] [-o [FILE_NAME]] |
可以添加 -o
参数来输出为不同的文件例如 xml, csv, json 文件
爬取后的文件默认放到项目根目录下