Python分布式爬虫!你以为你会了吗?你看看这篇教程!万字长文!

---恢复内容开始---

背景

一、前沿

1.1 爬虫是什么?

网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本。

1.2 为什么是Python?

简单易学:简单到没有学习过任何编程语言的人稍微看下资料就能编写出爬虫 解释型编程语言:编写完后可以直接执行,无须编译

代码重用性高:可以直接把包含某个功能的模块带入其它程序中使用

跨平台性:几乎所有的python程序都可以不加修改的运行在不同的操作系统

从零基础到项目实战视频获取地址群:125240963

2.2 URL 的含义

概念:

URL(协议(服务方式) + IP地址(包括端口号) + 具体地址),即统一资源定位符,也就是我们说的网址,统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。爬虫爬取数据时必须要有一个目标的URL才可以获取数据,因此,它是爬虫获取数据的基本依据。

相关:

URI = Universal Resource Identifier 统一资源标志符

URL = Universal Resource Locator 统一资源定位符

URN = Universal Resource Name 统一资源名称

2.4 代理基本原理

2.4.1基本原理

在本机和服务器之间搭建了一个桥,此时本机不是直接向 Web 服务器发起请求,而是向代理服务器发出请求,这个过程 Web 服务器识别出的真实的 IP 就不再是我们本机的 IP 了,就成功实现了 IP 伪装,这就是代理的基本原理

2.4.2代理的作用

1、突破自身 IP 访问限制,访问一些平时不能访问的站点

2、访问一些单位或团体内部资源

3、隐藏真实 IP

2.4.3爬虫代理

在爬取过程中可能遇到同一个 IP 访问过于频繁的问题,网站就会让我们输入验证码或登录或者直接封锁 IP,这样会给爬取带来极大的不便。让服务器误以为是代理服务器的在请求自己。这样在爬取过程中通过不断更换代理,就不会被封锁,可以达到很好的爬取效果

三、爬虫入门

3.2 一个入门栗子

其它策略

Timeout设置

3.4 动态渲染页面抓取

Splash 是一个 JavaScript 渲染服务,是一个带有 HTTP API 的轻量级浏览器,同时它对接了 Python 中的 Twisted 和 QT 库,利用它我们同样可以实现动态渲染页面的抓取。

异步方式处理多个网页渲染过程

获取渲染后的页面的源代码或截图

通过关闭图片渲染或者使用 Adblock 规则来加快页面渲染速度

可执行特定的 JavaScript 脚本

可通过 Lua 脚本来控制页面渲染过程

获取渲染的详细过程并通过 HAR(HTTP Archive)格式呈现

3.5 爬虫完整流程

四、爬虫框架

4.1 PySpider简介

一个国人编写的强大的网络爬虫系统并带有强大的WebUI。采用Python语言编写,分布式架构,支持多种数据库后端,强大的WebUI支持脚本编辑器,任务监视器,项目管理器以及结果查看器

4.3 Scrapy简介

Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。

5.3 scrapy项目指令

crawl:使用spider进行爬取

check:检查项目是否有错

list: 列出当前项目中所有可用的spider,每行输出一个spider

edit:仅仅是提供一个快捷方式。开发者可以自由选择其他工具或者IDE来编写调试spiderparse

parse:获取给定的URL并使用相应的spider分析处理

bench:运行benchmark测试

5.4 scrapy选择器

BeautifulSoup 是在程序员间非常流行的网页分析库,它基于HTML代码的结构来构造一个Python对象, 对不良标记的处理也非常合理,但它有一个缺点:慢。

lxml 是一个基于 ElementTree (不是Python标准库的一部分)的python化的XML解析库(也可以解析HTML)。

Scrapy提取数据有自己的一套机制。它们被称作选择器(seletors),因为他们通过特定的 XPath 或者 CSS 表达式来“选择” HTML文件中的某个部分。

XPath 是一门用来在XML文件中选择节点的语言,也可以用在HTML上。

CSS 是一门将HTML文档样式化的语言。选择器由它定义,并与特定的HTML元素的样式相关连。

Scrapy选择器构建于 lxml 库之上,这意味着它们在速度和解析准确性上非常相似

属性

name: 定义spider名字的字符串(string)

allowed_domains: 包含了 spider 允许爬取的域名(domain)列表(list)

start_urls: URL列表。当没有制定特定的URL时,spider将从该列表中开始进行爬取

custom_settings: 该设置是一个dict.当启动spider时,该设置将会覆盖项目级的设置. 由于设置必须在初始化(instantiation)前被更新,所以该属性 必须定义为class属性

crawler: 该属性在初始化class后,由类方法 from_crawler() 设置, 并且链接了本spider实例对应的 Crawler 对象

settings: crawler 的配置管理器,扩展(extensions)和中间件(middlewares)使用它用来访问 Scrapy 的配置

logger: self.logger.info('日志:%s', response.status)

方法

from_crawler: 如果存在,则调用此类方法以从 Crawler 创建 pipeline 实例。它必须返回一个新的pipeline实例。 Crawler 对象提供对所有 Scrapy 核心组件(如settings 和 signals)的访问; 它是 pipeline 访问它们并将其功能挂钩到Scrapy中的一种方法

start_requests: 该方法必须返回一个可迭代对象(iterable)。该对象包含了spider用于爬取的第一个Request

make_requests_from_url: 该方法接受一个URL并返回用于爬取的 Request 对象

parse: 当response没有指定回调函数时,该方法是Scrapy处理下载的response的默认方法

log: 使用 scrapy.log.msg() 方法记录(log)message

closed: 当spider关闭时,该函数被调用

5.6 Item Pipeline

当 Item 在 Spider 中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。每个item pipeline组件(有时称之为“Item Pipeline”)是实现了简单方法的Python类。他们接收到Item并通过它执行一些行为,同时也决定此Item是否继续通过pipeline,或是被丢弃而不再进行处理。

六、scrapy 搭建项目

6.1 爬虫思路

6.2 实际项目分析

项目结构

七、分布式爬虫

7.1 单主机爬虫架构

本机维护一个爬虫队列,scheduler 进行调度

Q:多台主机协作的关键是什么?

A:共享爬虫队列

单主机爬虫架构

7.2 分布式爬虫架构

image

分布式爬虫架构

7.3 问题

Q1:队列怎么选?

A1: Redis队列

Redis 非关系型数据库,key-value形式存储,结构灵活

是内存中的数据结构存储系统,处理速度快,性能好

提供队列、集合等多种存储结构,方便队列维护

Q2:怎么去重?

A2:Redis集合

Redis 提供集合数据结构,在redis集合中存储每个request的指纹

在向redis集合中存储request指纹的时候,先验证指纹是否存在?

[如果存在]:则不添加request到队列

[不存在]:则将request加入队列,并将指纹加入集合

Q3:怎样防止中断?

A3:启动判断

在每台从机 scrapy 启动时 都会首先判断当前 redis reqeust队列是否为空

[不为空]:从队列中取得下一个 request ,进行执行爬虫

[空]:重新开始爬取,第一台从机执行爬取向队列中添加request

Q4:怎样实现该架构?

A4:Scrapy-Redis

scrapy是Python的一个非常好用的爬虫框架,功能非常强大,但是当我们要爬取的页面非常多的时候,单个主机的处理能力就不能满足我们的需求了(无论是处理速度还是网络请求的并发数),这时候分布式爬虫的优势就显现出来,人多力量大。而scrapy-Redis就是结合了分布式数据库redis,重写了scrapy一些比较关键的代码(scrapy的调度器、队列等组件),将scrapy变成一个可以在多个主机上同时运行的分布式爬虫。

github地址:https://github.com/rmax/scrapy-redis

7.4 源码解读

阅读源码前:需要了解 scrapy 的运行原理,否则并没什么用。

scrapy-redis 工程的主体还是 redis 和 scrapy 两个库,将两个库的核心功能结合,实现分布式。

1 connection.py

负责根据setting中配置实例化redis连接。被dupefilter和scheduler调用,总之涉及到redis存取的都要使用到这个模块

2 dupefilter.py

通过继承 BaseDupeFilter 重写他的方法,实现了基于redis的 request 判重。scrapy-redis使用 redis的一个 set 中插入 fingerprint(不同spider的key不同)

spider名字+DupeFilter的key就是为了在不同主机上的不同爬虫实例,只要属于同一种spider,就会访问到同一个set,而这个set就是他们的url判重池 。

DupeFilter 判重会在 scheduler 类中用到,每一个request在进入调度之前都要进行判重,如果重复就不需要参加调度,直接舍弃就好了

image

3 picklecompat.py

loads 和 dumps 两个函数,其实就是实现了一个 serializer,因为 redis 数据库不能存储复杂对象(value部分只能是字符串,字符串列表,字符串集合和hash,key部分只能是字符串),所以存储前需要先序列化成文本才行

这个 serializer 主要用于 scheduler 存 reuqest 对象。

为什么不用json格式?(item pipeline 的串行化默认用的就是 json)

4 pipelines.py

pipeline 文件实现了一个 item pipieline 类,和 scrapy 的 item pipeline 是同一个对象,从settings中获取我们配置的REDISITEMSKEY作为key,把item串行化之后存入redis数据库对应的value中(这个value是list,我们的每个item是这个list中的一个结点),这个pipeline把提取出的item存起来,主要是为了方便我们延后处理数据。

7 spider.py

设计的这个spider从redis中读取要爬的url,然后执行爬取,若爬取过程中返回更多的url,那么继续进行直至所有的request完成。之后继续从redis中读取url,循环这个过程。

分析:在这个spider中通过connect signals.spideridle信号实现对crawler状态的监视。当idle时,返回新的makerequestsfromurl(url)给引擎,进而交给调度器调度。

 

---恢复内容结束---

猜你喜欢

转载自www.cnblogs.com/sm123456/p/9028916.html