scrapy+redis实现分布式爬虫
前言介绍
- 分布式爬虫又可以称为集群爬虫,和单点爬虫不同的是分布式爬虫可以实现多台机器同时运行,速度更快也能避免反爬虫机制对ip检测封锁,而且能随时停止和运行,自动url去重(这意味着再次运行必须先清空redis数据库下的XX:dupefilter,否则无法重复爬取相同url)。
- 本文介绍redis分布式爬虫 ,redis是一种非关系数据库除了支持string类型的value外还支持string、hash、set、sortedset、list等数据结构。重要的是能支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。
- 我们利用redis的特性,更改scrapy的任务调度,我们在scrapy项目spider中建立两个爬虫一个专门爬取url网络链接,一个爬取数据。master(主机)将设置链接爬虫爬取对应的网络链接后在redis中分享url链接给slave(从机),slave领取任务后开始数据爬取并将数据存储在redis中,最后master便能通过访问redis命令提取目标数据。
1.scrapy+redis分布式准备工作:
(1).下载redis及环境搭建
redis下载地址 windows
redis desktop manager(Windows可视化管理redis数据库工具)下载地址
redis 官网最新下载地址 Linux
Linux Ubuntu系统安装介绍看这里
(2).scrapy_redis环境安装
windows安装后
- 找到并修改安装目录下bin文件下的redis.conf
#需要远程连接redis 先注释bind
# bind 127.0.0.1
如果需要修改密码,也在redis.conf文件找到:
#取消注释requirepass
requirepass redisredis # redisredis就是密码(记得自己修改)
- 运行redis服务器的命令:安装目录下的redis-server.exe
- 运行redis客户端的命令:安装目录下的redis-cli.exe,也可以在当前目录下打开dos输入redis-cli 然后auth 密码
Linux安装后
- 进入目录下 同样修改redis.conf文件
- 输入/etc/redis-serverce redis.conf启动redis服务器
- 当前目录 重新打开一个新窗口 输入/etc/redis-cli (一般在etc目录下)
然后在Linux或Windows的命令窗口输入命令安装对应的python库
pip install scrapy-redis
pip install redis
我们可以在windows下测试远程连接redis是否正常
打开dos窗口输入
redis-cli -h 远程ip地址 -p 6379
注意要提前打开远程机器的redis-server,当然你也可以通过redis desktop manager图形化界面工具来连接管理你的redis数据库。
(3)介绍redis有关操作命令
网上可以搜到很多有关redis的操作命令,我这里介绍比较常见的
D:\Program Files\Redis>redis-cli #启动redis客户端
redis 127.0.0.1:6379> auth 123456 #输入密码
OK
redis 127.0.0.1:6379> keys * #查询当前所有数据表
(empty list or set)
redis 127.0.0.1:6379> select 1 #选择数据库db=1 默认是0
OK
redis 127.0.0.1:6379[1]> keys *
1) "ifengspider:items"
3) "ifengurls:dupefilter"
4) "newspider:dupefilter"
5) "ifeng:requests"
redis 127.0.0.1:6379[1]> lrange ifengspider:items 1 2 #读取ifengspider:item表前2行数据
#这里数据过多将无法显示,在windows下使用redis desktop manager可查看更多,但也很容易崩溃,不是很稳定
redis 127.0.0.1:6379[1]> flushdb #只清空当前数据库数据
redis 127.0.0.1:6379[1]> flushall #清空所有数据库数据
2、scrapy中使用加入redis
(1)在setting.py文件的添加:
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
SCHEDULER_PERSIST = True
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderPriorityQueue'
REDIS_URL = 'redis://:password@hostname:6973' # 此处设置将连接有密码的host
REDIS_HOST = '127.0.0.1' #如果设置了REDIS_URL此处将被覆盖
REDIS_PORT = 6379 #同上
#启用Redis调度存储请求队列
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
#确保所有的爬虫通过Redis去重
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
--------------------------------以下选填-----------------------------------------------
#默认请求序列化使用的是pickle 但是我们可以更改为其他类似的。PS:这玩意儿2.X的可以用。3.X的不能用
#SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat"
#不清除Redis队列、这样可以暂停/恢复 爬取
#SCHEDULER_PERSIST = True
#使用优先级调度请求队列 (默认使用)
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'
#可选用的其它队列
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue'
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.LifoQueue'
#最大空闲时间防止分布式爬虫因为等待而关闭
#SCHEDULER_IDLE_BEFORE_CLOSE = 10
#此处设置将返回的数据自动保存在连接主机的redis数据库中
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline': 300
}
#序列化项目管道作为redis Key存储
#REDIS_ITEMS_KEY = '%(spider)s:items'
#默认使用ScrapyJSONEncoder进行项目序列化
#You can use any importable path to a callable object.
#REDIS_ITEMS_SERIALIZER = 'json.dumps'
#指定连接到redis时使用的端口和地址(可选)
#REDIS_HOST = 'localhost'
#REDIS_PORT = 6379
#指定用于连接redis的URL(可选)
#如果设置此项,则此项优先级高于设置的REDIS_HOST 和 REDIS_PORT
#REDIS_URL = 'redis://user:pass@hostname:9001'
#自定义的redis参数(连接超时之类的)
#REDIS_PARAMS = {}
#自定义redis客户端类
#REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient'
#如果为True,则使用redis的'spop'进行操作。
#如果需要避免起始网址列表出现重复,这个选项非常有用。开启此选项urls必须通过sadd添加,否则会出现类型错误。
#REDIS_START_URLS_AS_SET = False
#RedisSpider和RedisCrawlSpider默认 start_usls 键
#REDIS_START_URLS_KEY = '%(name)s:start_urls'
#设置redis使用utf-8之外的编码
#REDIS_ENCODING = 'latin1'
(2)在其他文件中,若要通过代码来连接redis数据库以此操作redis数据库中数据:
pool =redis.ConnectionPool(host='hostname', port=6379, db=0,password=‘pwd’)
#password没有设置可不填
r = redis.Redis(connection_pool=pool)
r.lpush('XX:items’,data) #将数据data导入连接的数据库中 字段名XX:items
data = r.lpop('XX:items') #从数据库中XX:items字段最上方数据弹出
r.delete('aa:items','bb:items') #清空 aa:items,bb:items中数据 如果需要反复跑程序可在爬虫开始时设置,来删除对应的dupefilter
(3)关于item.py和middlewares.py:
这里和scrapy下写法没什么区别,都照原来写就好了
(4)关于自定义spider写法:
主要不同的是爬虫类需要继承scrapy_redis中的RedisCrawlSpider而不是scrapy.Spider,然后start_urls改成redis_key来从redis服务端提取url任务链接地址。这样主机有专门爬取链接的爬虫,其它从机只需要领取其中的任务,解析任务页面返回数据,即可实现分布式爬虫。
import scrapy
from scrapy_redis.spiders import RedisCrawlSpider
class XX_spider(RedisCrawlSpider): #继承scrapy_redis
name = 'ifengspider'
allowed_domains=['finance.ifeng.com','app.finance.ifeng.com']
redis_key = 'XX:requests' #填任务url链接所在表名,在setting.py中已经设置好要连接的redis-server和对应db
def parse(self,response): #这里直接写scrapy默认的parse,到这里就可以直接写对应网页解析了
(5)pipelines.py 将Spider文件返回的数据传入redis数据库中:
首先在setting.py文件下设置
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline': 300
}
pipelines.py :
class Redis_pipelines(object):
def process_item(self,item,spider):
item['a']=item['a'] #这里作为处理结果的收尾地方,可以按自己意愿改写数据
item['b']=item['b']
item['c']=item['c']
item['d']=item['d']
return item
这里会使每台机器跑下来的数据会发送到setting.py设置的主机地址redis服务器上,字段名为XXspider:items。最后所有url跑完后,在服务器写一个mysql.py文件:连接本地redis服务器导出所有数据给自己的Mysql数据库。下面我贴上Pipelines.py的改写代码和提取redis数据循环导入mysql数据库中代码。
Mysql.py:
import pymysql
import redis
import json
def Data_into_Mysql():
conn = pymysql.connect(host='127.0.0.1',
charset='utf8',user='root',passwd='pwd',db='crawler',port=3306)
pool =redis.ConnectionPool(host='127.0.0.1', port=6379, password='pwd',db=2)
r = redis.Redis(connection_pool=pool)
data = r.lpop('xx:items')
count=0
while data is not None:
try:
data=data.decode('utf-8','ignore')
a=json.loads(data)
with conn.cursor() as cursor:
sql = '''INSERT INTO table VALUES(%s,%s)'''
cursor.execute(sql, (a['key'],a['key']))
conn.commit()
count+=1
print(count)
data = r.lpop('xx:items')
except Exception as e:
print(str(e))
print(a)
data = r.lpop('xx:items')
conn.close();
Data_into_Mysql()
注意如果要重新跑相同的url,请先清空对应dupefilter里的数据,此处为redis去重设置。
结语
作为爬虫新手,第一次写自己爬虫学习上的一些经历,若有不足之处欢迎指出,欢迎感兴趣的朋友一起探讨研究,分布式爬虫学习也是在网上到处翻了各种资料对比填坑才成功实现,我希望自己总结的经验能方便更多感兴趣的小伙伴,若写有不明之处,可以留言或私信我,当然特别细节的东西可能我也需要继续学习。后续可能会继续更新分布式爬虫相关的内容和填坑,谢谢大家支持。
参考资料:
基于Python使用scrapy-redis框架实现分布式爬虫
使用scrapy-redis构建简单的分布式爬虫
如果您喜欢我的文章,请关注或点击喜欢,您的支持是我最大的动力 ^ ^~!
转载请注明作者黑羊的皇冠及其出处
黑羊的皇冠 主页
github地址也将尽快放出来