大规模并发采集——分布式爬虫


当爬取内容过多,需要多机合作的时候,就需要用到分布式系统,这节课给大家讲解一下分布式爬虫的实现。

分布式系统

什么是分布式系统?

分布式系统就是把一些计算机通过网络连接起来,然后协同工作

协同工作需要解决两个问题:

  • 任务分解 
    把一个问题拆解成若干个独立任务,每个任务在一台节点上运行,实现多任务的并发执行

  • 节点通信 
    节点之间互相通信,需要设计特定的通信协议来实现。协议可以采用RPC或Message Queue等方式

分布式爬虫系统

scrapy_redis

  • scrapy-redis是为了更方便地实现scrapy分布式爬取,而提供了一些以redis数据库为基础的组件
  • scrapy-redis提供了维持待爬取url的去重以及储存requests的指纹验证。原理是:redis维持一个共同的url队列,各个不同机器上的爬虫程序获取到的url都保存在redis的url队列,各个爬虫都从redis的url队列获取url,并把数据统一保存在同一个数据库里面
  • 本课主要讲授基于scrapy_redis的分布式爬虫

消息队列

  • MQ全称为Message Queue, 是一种分布式应用程序的的通信方法,消息发送后可以立即返回,由消息系统来确保消息的可靠传递
  • 它是消费-生产者模型的一个典型的代表,producer往消息队列中不断写入消息,而另一端consumer则可以读取或者订阅队列中的消息
  • 消息生产者只管把消息发布到 MQ 中而不用管谁来取,消息消费者只管从 MQ 中取消息而不管是谁发布的

RabbitMQ

  • RabbitMQ是MQ产品的典型代表,是一款基于AMQP协议可复用的企业消息系统。业务上,可以实现服务提供者和消费者之间的数据解耦,提供高可用性的消息传输机制,在实际生产中应用相当广泛

scrapy_rabbitmq分布式

  • Scrapy-rabbitmq-link 是可以让你从RabbitMQ 消息队列中取到URL并且分发给Scrapy spiders的组件

celery初步

  • Celery 用消息通信,通常使用中间人(Broker)在客户端和程序间斡旋。这个过程从客户端向队列添加消息开始,之后中间人把消息派送给程序

scrapy_redis分布式

什么是Redis数据库?

Redis是一个使用ANSI C编写的开源、支持网络基于内存可选持久性键值对存储数据库

安装Redis数据库及scrapy_redis:
Windows系统安装:
  1. 下载Redis压缩包: 
    前往:https://github.com/MicrosoftArchive/redis/releases 
    或者前往网盘链接:http://pan.baidu.com/s/1i5f9xSL 密码:t5bo 
    下载Redis-x64-3.2.100.zip,并将其解压缩

  1. 安装Redis: 
    打开cmd,切换到解压的文件夹下执行命令

redis-server –service-install redis.windows.conf –loglevel verbose

  1. 启动Redis服务: 
    在解压的文件夹下执行命令

redis-server –service-start

  1. 安装scrapy_redis 
    启动cmd,使用pip安装scrapy_redis

pip install scrapy_redis


Mac OS系统安装:
  1. 下载Redis压缩包: 
    打开终端(Terminal),使用curl命令下载压缩包(注意:curl -后面是大写字母O,不是数字0),并解压

curl -O http://download.redis.io/releases/redis-4.0.2.tar.gz 
tar xzf redis-4.0.2.tar.gz

  1. 安装Redis: 
    切换到redis-4.0.2目录下面,安装Redis:

cd redis-4.0.2 
make

  1. 启动Redis服务: 
    启动文件在src目录下

src/redis-server

  1. 安装scrapy_redis 
    打开Terminal,使用pip安装scrapy_redis(或者可以在PyCharm里安装)

pip install scrapy_redis


Scrapy_redis设置
在项目中进行如下的设置:

更改去重对列:必有项

SCHEDULER = “scrapy_redis.scheduler.Scheduler”

利用Redis去重:必有项

DUPEFILTER_CLASS = “scrapy_redis.dupefilter.RFPDupeFilter”

序列化方案

SCHEDULER_SERIALIZER = “scrapy_redis.picklecompat”

故障重跑

SCHEDULER_PERSIST = True

URL队列优先级

SCHEDULER_QUEUE_CLASS = ‘scrapy_redis.queue.PriorityQueue’

把item储存进Redis管道

ITEM_PIPELINES = { 
‘scrapy_redis.pipelines.RedisPipeline’: 300 
}

队列名字

REDIS_ITEMS_KEY = ‘%(spider)s:items’

配置连接

REDIS_HOST = ‘localhost’ 
REDIS_PORT = 6379 
#或者 
REDIS_URL = ‘redis://user:pass@hostname:9001’

实例化一个Redis对象

REDIS_PARAMS[‘redis_cls’] = ‘myproject.RedisClient’

设置set格式(不允许重复的元素)

REDIS_START_URLS_AS_SET = False

键值对中键值命名规则

REDIS_START_URLS_KEY = ‘%(name)s:start_urls’

编码方式

REDIS_ENCODING = ‘latin1’

启动scrapy_redis
  1. 运行爬虫:

scrapy crawl 爬虫名

  1. 启动:(注意:启动的时候应该先切换到redis安装目录下)

Windows系统:

url选用的是list类型:

url选用的是set类型:

Mac OS系统:(注意:在Terminal下启动Redis后,应该新建一个Terminal窗口,并且切换到redis安装目录下)

url选用的是list类型:

url选用的是set类型:


案例演示

我们这次用的依然是上节课的city58的案例,只是修改了settings.py和city58_test.py两个文件。 
city58_test.py:实现翻页爬取

# -*- coding: utf-8 -*-
import scrapy
from pyquery import PyQuery
from ..items import City58Item
from scrapy.http import Request
from scrapy_redis.spiders import RedisSpider
class City58TestSpider(RedisSpider):
name = 'city58_test'
allowed_domains = [ '58.com']
start_urls = [ 'http://bj.58.com/chuzu/']
def parse(self, response):
jpy = PyQuery(response.text)
li_list = jpy( 'body > div.mainbox > div.main > div.content > div.listBox > ul > li').items()
for it in li_list:
a_tag = it( 'div.des > h2 > a')
item = City58Item()
item[ 'name'] = a_tag.text()
item[ 'url'] = (a_tag.attr( 'href') if a_tag.attr( 'href') else '')
item[ 'price'] = it( 'div.listliright > div.money > b').text()
yield item
if not li_list:
return
pn = response.meta.get( 'pn', 1) #得到meta中pn的数值,如果没有,就默认为1
pn += 1
#response.meta['pn'] = p
if pn > 5
return
#把相对路径转化为绝对路径,并request访问
req = response.follow( '/chuzu/pn{}/'.format(pn), #拼接相对路径
callback = self.parse,
meta = { 'pn':pn} #使用meta参数进行传值
)
yield req

settings.py

SCHEDULER = "scrapy_redis.scheduler.Scheduler" #必有项:更改去重对列
# Ensure all spiders share same duplicates filter through redis.
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" #必有项:利用Redis去重
#SCHEDULER_PERSIST = True #故障重跑
REDIS_URL = 'redis://localhost:6379' #配置连接
#REDIS_START_URLS_AS_SET = False #设置set格式(不允许重复的元素)

运行时要记得在队列中塞入start_urls

Windows系统: 
redis-cli lpush city58_test:start_urls http://bj.58.com

Mac OS系统: 
src/redis-cli lpush city58_test:start_urls http://bj.58.com

redis desktop manager软件安装及使用
  1. Windows系统安装包下载 
    前往网盘链接:http://pan.baidu.com/s/1gfpgQxt 密码:iz9u 
    MacOS系统安装包下载 
    前往网盘链接:http://pan.baidu.com/s/1pKO2kX1 密码:wfkw 

  2. 根据提示进行安装 
    只需要执行默认安装便可 

  3. 打开软件,点击connect to redis server 

  4. 输入数据库名字,以及host和端口 
    数据库名字test,host为127.0.0.1(本机),默认端口为6379 

  5. 打开数据库,就可以看到数据了

其他的分布式系统知识介绍

本节课介绍了基于scrapy-redis的分布式系统,用于分布式爬虫URL队列的存储和去重队列的存储。当然,对于更大型的爬虫系统,或者对于非scrapy框架的爬虫,可以选择其它的方案替代scrapy和scrapy-redis,比如可以使用RabbitMQ消息队列代替Redis。以下的内容,提供了更多关于分布式爬虫的知识和方案

消息队列

MQ全称为Message Queue, 是一种分布式应用程序的的通信方法,它是消费-生产者模型的一个典型的代表,producer往消息队列中不断写入消息,而另一端consumer则可以读取或者订阅队列中的消息

爬虫之消息队列

在构建一个松耦合或是异步的系统时,消息队列是最常用的方法。在爬虫中使用消息队列有哪些好处呢?

  • 通过消息队列实现线程安全的去重
  • 多进程消费爬虫任务队列
  • 确保每一条任务都执行
RabbitMQ消息队列

RabbitMQ 是一种消息队列,用于程序间的通信 
形象地说 : MQ就像一个邮局,发送者将消息写入 MQ,MQ 负责把消息发送给接收者。RabbitMQ 可支持 Java, PHP, Python, Go, JavaScript, Ruby 等多种语言


注意:RabbitMQ的使用需要事先安装 


Scrapy-rabbitmq-link的安装和配置

Scrapy-rabbitmq-link 是可以让你从RabbitMQ 消息队列中取到URL并且分发给Scrapy spiders的组件

安装:

pip install scrapy-rabbitmq-link

配置:

# Enable RabbitMQ scheduler
SCHEDULER = "scrapy_rabbitmq_link.scheduler.SaaS"
# Provide AMQP connection string
RABBITMQ_CONNECTION_PARAMETERS = 'amqp://guest:guest@localhost:5672/'
# Set response status codes to requeue messages on
SCHEDULER_REQUEUE_ON_STATUS = [ 500]
# Middleware acks RabbitMQ message on success
DOWNLOADER_MIDDLEWARES = {
'scrapy_rabbitmq_link.middleware.RabbitMQMiddleware': 999
}
Celery - 分布式任务队列

Celery 是一个简单、灵活且可靠的,处理大量消息的分布式系统,并且提供维护这样一个系统的必需工具

它是一个专注于实时处理的任务队列,同时也支持任务调度

Celery 需要一个发送和接受消息的传输者。Celery 支持 RabbitMQRedis 甚至其他数据库系统作为其消息代理中间件,但也提供大量其他实验性方案的支持

Celery 好处也很多,尤其在使用python构建的应用系统中,无缝衔接,使用相当方便

celery的应用场景
  • 处理异步任务
  • 任务调度
  • 处理定时任务
  • 分布式调度
安装Celery

pip install celery

配置Celery
from celery import Celery
app = Celery( 'hello', broker= 'amqp://guest@localhost//') #配置rabbitMQ
@app.task #装饰器
def hello():
return 'hello world'
  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值