Scrapy源码(1)——爬虫流程概览
时间:2022-05-07
本文章向大家介绍Scrapy源码(1)——爬虫流程概览,主要内容包括前言、介绍、架构概述、数据流(Data flow)、补充、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
前言
使用 Scrapy
已经有一段时间了,觉得自己有必要对源码好好的学习下了,所以写下记录,希望能加深自己的理解。
Scrapy | A Fast and Powerful Scraping and Web Crawling Framework
接下来说到的是最新版本: Scrapy 1.5,暂且把 Spider
称为 蜘蛛,而不是爬虫。
介绍
Scrapy是一个开源爬虫框架,用于抓取网站并提取有用的结构化数据,如数据挖掘,信息处理或历史档案。
尽管Scrapy最初是为网页抓取设计的,但它也可以用于使用API(如Amazon Associates Web Services)或作为通用网络抓取工具提取数据。
一个最简单的例子,相信大家都写过
import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
start_urls = [
'http://quotes.toscrape.com/tag/humor/',
]
def parse(self, response):
for quote in response.css('div.quote'):
yield {
'text': quote.css('span.text::text').extract_first(),
'author': quote.xpath('span/small/text()').extract_first(),
}
next_page = response.css('li.next a::attr("href")').extract_first()
if next_page is not None:
yield response.follow(next_page, self.parse)
一般来说,创建一个Scrapy项目需要如下流程:
- 使用
scrapy startproject spider
创建爬虫模板 - 爬虫类继承
scrapy.Spider
,重写parse
方法和逻辑 -
parse
方法中yield
或return
字典、Request
、Item
- 自定义
Item
、Middlewares
、Pipelines
等 - 使用
scrapy crawl <spider_name>
或新建文件cmdline.execute("scrapy crawl spider_name".split())
运行(便于调试) - 其它
架构概述
这是一张非常经典的图,基本上说到Scrapy都会用到它,来源于Architecture overview
核心组件(Components)
-
Scrapy Engine
:引擎,负责控制系统所有组件之间的数据流,并在发生某些操作时触发事件; -
Scheduler
:调度器,接收来自引擎的请求,并将它们排入队列,以便在引擎请求它们时将它们提供给它们(也提供给引擎); -
Downloader
:下载器,负责从网络上获取网页并将它们返回到引擎,然后引擎将它们返回给蜘蛛/spiders; -
Spiders
:蜘蛛,是用户编写的自定义类,用于解析响应并从中提取项目(也称为抓取的项目)或追加其他请求; -
Item Pipeline
:管道,负责输出结构化数据,可自定义输出位置,典型的任务包括清理,验证和持久性; -
Downloader middlewares
:下载中间件,位于引擎和下载器之间的特定钩子/hooks,当它们从引擎传递到下载器时处理请求,以及从下载器传递到引擎的响应,常用于如下情况:- 在将请求发送到下载器之前处理请求(即在Scrapy将请求发送到网站之前);
- 在将其传递给蜘蛛之前改变接收到的响应;
- 发送新的请求,而不是将接收到的响应传递给蜘蛛;
- 向蜘蛛传递响应而不需要获取网页;
- 默默地放下一些请求。
-
Spider middlewares
:Spider中间件,特定的钩子,位于引擎和蜘蛛之间,能够处理蜘蛛输入(响应)和输出(项目和请求),常用于如下情况:- spider回调的后处理输出 更改/添加/删除请求或items;
- 后处理start_requests;
- 处理蜘蛛异常;
- 根据响应内容为一些请求调用errback而不是callback。
-
Event-driven networking
:事件驱动的网络,Scrapy是用Twisted编写的,这是一个流行的事件驱动的Python网络框架。 因此,它使用非阻塞(又称异步)代码来实现并发。
Twisted is an event-driven networking engine written in Python and licensed under the open source MIT license.
数据流(Data flow)
Scrapy中的数据流由执行引擎控制,如下所示:
- 引擎获取最初的请求从蜘蛛抓取(
start_urls
)。 - 引擎在调度程序中调度请求,并要求下一个请求进行采集。
- 调度器将下一个请求返回给引擎。
- 引擎将请求发送到下载器,通过下载器中间件。
- 一旦页面完成下载,
Downloader
会生成一个响应(包含该页面)并将其发送到引擎,并通过Downloader Middlewares
。 - 引擎从
Downloader
收到响应并将其发送给Spider
进行处理,并通过Spider Middleware
传递。 -
Spider
处理响应,并通过Spider
中间件将抓取的项目和新的请求(后续)返回给引擎。 - 引擎将处理后的项目发送到项目管道,然后将处理后的请求发送到调度程序,并要求可能的下一个请求进行采集。
- 该过程重复(从第1步开始),直到调度器没有更多请求。
找到一张图,便于理解:
第一期差不多就到这了,没有说很多代码,主要是宏观上来观察 Scrapy
的架构,是如何运行。之后会更多的查看Scrapy的源代码,就近是如何采集数据的。
(内心有点小恐慌,不知道会写成什么样子。)
补充
关于如何阅读项目源代码,找到一篇不错的文章,共享:如何阅读开源项目
主要是这几部分:
- 看:静态对代码进行分析,看相关资料,代码逻辑。
- 跑:将项目在IDE里面跑起来,通过IDE调试参数,加Log等。
- 查:阅读过程中肯定会遇到不懂的,这时候需要通过搜索引擎来解决你的疑惑。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- NPM安装模块报错:Error: sha1-W+8rAcUcgURBLVhzyvg+IvHsa4Q= integrity checksum failed when using sha1: wanted
- OPA Gatekeeper 策略入门
- 给Linux命令行加个问候语
- RaspberryPi接入HomeKit
- React Fetch请求
- React使用代理解决跨域问题
- React登录跳转遇到的问题
- 响应式架构与 RxJava 在有赞零售的实践
- Centos 7搭建Gitlab服务器超详细Centos 7搭建Gitlab服务器超详细(搭建成功)
- Netty之旅二:口口相传的高性能Netty到底是什么?
- 前端知识复习(一)
- Powershell运行脚本报错:此系统上禁止运行脚本
- git rebase解决合并冲突
- npm相关操作
- Angular html property的值如何被更新的