Scrapy简介
- Scrapy是用纯Python实现一个为了爬取网站数据、提取结构性数据而编写的应用框架,用途非常广泛。
- 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非常之方便。
- Scrapy 使用了 Twisted’twɪstɪd异步网络框架来处理网络通讯,可以加快我们的下载速度,不用自己去实现异步框架,并且包含了各种中间件接口,可以灵活的完成各种需求。
Scrapy架构图
- 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中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)
Scrapy安装
安装命令:
pip install Scrapy
报错及解决
- 错误
- 0: UserWarning: You do not have a working installation of the service_identity module: ‘cannot import name ‘opentype’’. Please install it from …
- 解决:http://www.bubuko.com/infodetail-2467560.html
-
etree
原因:默认安装的lxml版本太高(默认安装最新版),卸载后,重新安装3.8以下版本
conda uninstall lxml
conda install lxml==3.8 -
解决Scrapy安装错误:Microsoft Visual C++ 14.0 is required…
问题描述:
当前环境win7,python_3.6.1,64位。
在windows下,在dos中运行pip install Scrapy报错:
Error: Microsoft Visual C++ 14.0 is required. Get it with “Microsoft Visual C++ Build Tools”: http://landinghub.visualstudio.com/visual-cpp-build-tools
http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 下载twisted对应版本的whl文件(如我的Twisted-18.4.0-cp36-cp36m-win_amd64.whl),
Twisted-18.4.0-cp36-cp36m-win_amd6
4.whl
2.98MB
Twisted-18.4.0-cp35-cp35m-win_amd6
4.whl
2.98MB
cp后面是python版本,amd64代表64位,运行命令:
pip install C:\Users\ibm\Downloads\Twisted-18.4.0-cp36-cp36m-win_amd64.whl
其中install后面为下载的whl文件的完整路径名
安装完成后,以管理员身份次运行:pip install scrapy 即可成功。 -
解决scrapy运行报No module named ‘win32api’
解决方法:
pip install pywin32
如果网速不行,可登录:https://pypi.org/project/pywin32/#files,进行下载
创建Scrapy项目
操作步骤:
1. 新建项目
- 进入工作空间目录
cd Spiders
- 创建项目
scrapy startproject project1
- 进入项目目录
cd project1
scrapy genspider sbaidu baidu.com
-
进入pycharm修改settings文件,将 ROBOTSTXT_OBEY 改为 False
-
重写parse函数
7.启动蜘蛛
scrapy crawl baidu
若报错:
解决方式:
模板:
各个主要文件的作用:
- scrapy.cfg :项目的配置文件 基本信息
- mySpider/ :项目的Python模块,将会从这里引用代码
- mySpider/items.py :项目的目标文件
- mySpider/pipelines.py :项目的管道文件
- mySpider/settings.py :项目的设置文件
- mySpider/spiders/ :存储爬虫代码目录
2. 明确目标(mySpider/items.py)
- 打开mySpider目录下的items.py
- Item 定义结构化数据字段,用来保存爬取到的数据,有点像Python中的dict,但是提供了一些额外的保护减少错误。
- 可以通过创建一个 scrapy.Item 类, 并且定义类型为 scrapy.Field的类属性来定义一个Item(可以理解成类似于ORM的映射关系)。
- 接下来,创建一个BossItem 类,和构建item模型(model)
1、items.py
2、向tieba(boss).py中写入内容
进入myspider项目执行:scrapy crawl boss --nolog
解决方法:
在settings里面加入 HTTPERROR_ALLOWED_CODES = [403]
然后再进入myspider项目执行:scrapy crawl boss --nolog
返回是[] ,因为正常情况下,没有发送请求头,返回403,服务器拒绝了我
使用user_agent
补全代码:
3、数据存储(Item Pipeline)
当Item在Spider中被收集之后,它将会被传递到Item Pipeline,这些Item Pipeline组件按定义的顺序处理Item。
每个Item Pipeline都是实现了简单方法的Python类,比如决定此Item是丢弃还是存储。以下是item pipeline的一些典型应用:
- 验证爬取的数据(检查item包含某些字段,比如说name字段)
- 查重(并丢弃)
- 将爬取结果保存到文件或者数据库中
- 编写item pipeline
编写item pipeline很简单,item pipiline组件是一个独立的Python类,其中process_item()方法必须实现:
启用一个Item Pipeline组件
为了启用Item Pipeline组件,必须将它的类添加到 settings.py文件ITEM_PIPELINES 配置,就像下面这个例子:
分配给每个类的整型值,确定了他们运行的顺序,item按数字从低到高的顺序,通过pipeline,通常将这些数字定义在0-1000范围内(0-1000随意设置,数值越低,组件的优先级越高)
4、启动爬虫(scrapy crawl boss --nolog)
稍等片刻,输出结果可以在数据库中查看
紧接着去获取详情页
源码分析
-
Spider
Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。
class scrapy.Spider是最基本的类,所有编写的爬虫必须继承这个类。
主要用到的函数及调用顺序为:
init() : 初始化爬虫名字和start_urls列表
start_requests() 调用make_requests_from url():生成Requests对象交给Scrapy下载并返回response
parse() : 解析response,并返回Item或Requests(需指定回调函数)。Item传给Item pipline持久化 , 而Requests交由Scrapy下载,并由指定的回调函数处理(默认parse()),一直进行循环,直到处理完所有的数据为止。
-
主要属性和方法
- name
定义spider名字的字符串。
例如,如果spider爬取 mywebsite.com ,该spider通常会被命名为 mywebsite - allowed_domains
包含了spider允许爬取的域名(domain)的列表,可选。 - start_urls
初始URL元祖/列表。当没有制定特定的URL时,spider将从该列表中开始进行爬取。 - start_requests(self)
该方法必须返回一个可迭代对象(iterable)。该对象包含了spider用于爬取(默认实现是使用 start_urls 的url)的第一个Request。 - parse(self, response)
当请求url返回网页没有指定回调函数时,默认的Request对象回调函数。用来处理网页返回的response,以及生成Item或者Request对象。
parse()方法的工作机制:
- 因为使用的yield,而不是return。parse函数将会被当做一个生成器使用。scrapy会逐一获取parse方法中生成的结果,并判断该结果是一个什么样的类型;
- 如果是request则加入爬取队列,如果是item类型则使用pipeline处理,其他类型则返回错误信息。
- scrapy取到第一部分的request不会立马就去发送这个request,只是把这个request放到队列里,然后接着从生成器里获取;
- 取尽第一部分的request,然后再获取第二部分的item,取到item了,就会放到对应的pipeline里处理;
- parse()方法作为回调函数(callback)赋值给了Request,指定parse()方法来处理这些请求 scrapy.Request(url, callback=self.parse)
- Request对象经过调度,执行生成 scrapy.http.response()的响应对象,并送回给parse()方法,直到调度器中没有Request(递归的思路)
- 取尽之后,parse()工作结束,引擎再根据队列和pipelines中的内容去执行相应的操作
- 程序在取得各个页面的items前,会先处理完之前所有的request队列里的请求,然后再提取items。
- 这一切的一切,Scrapy引擎和调度器将负责到底。