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运行环境包。

  1. 全局安装 virtualenv
1
$ sudo pip install virtualenv
  1. 创建独立Python运行环境
1
$ virtualenv ENV
  1. 安装Scrapy
1
$ pip install scrapy

在不同的平台上的安装步骤不尽相同,某些平台需要安装平台依赖包,具体请 查看

Scrapy项目创建

  1. 创建项目&生成爬虫
1
2
3
$ scrapy startproject [PROJECT_NAME]
$ cd [PROJECT_NAME]
$ scrapy genspider [SPIDER_NAME] [START_SITE_NAME]

[PROJECT_NAME] 是待创建的爬虫项目名
[SPIDER_NAME] 是爬虫名
[SITE_NAME] 是待爬取的初始站点地址

例如我们创建了一个名为 tutorial 的项目,并添加爬虫 top

项目目录如下

1
2
3
4
5
6
7
8
9
10
11
tutorial/
|___scrapy.cfg # 配置文件
|___tutorial/ # 项目的 Python 模块,代码存在这里
|___ __init__.py
|___items.py # 项目 items 定义文件
|___middlewares.py # 项目 middlewares 文件
|___pipelines.py # 项目 pipelines 文件
|___settings.py # 项目 settings 文件
|___spiders/ # 爬虫文件目录
|___ __init__.py
|___top.py # 爬虫文件

打开 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
2
from 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 文件
爬取后的文件默认放到项目根目录下