赞
踩
Scrapy 是一个通用的爬虫框架,但是不支持分布式,
Scrapy-Redis 是为了更方便地实现Scrapy分布式爬取,而提供了一些以redis为基础的组件(仅有组件)
pip install scrapy-redis
提供了下面四种组件(components):(四种组件意味着这四个模块都要做相应的修改)
Scheduler
Duplication Filter
Item Pipeline
Base Spider
假设有四台电脑:Windows 10、Mac OS X、Ubuntu 16.04、CentOS 7.2,任意一台电脑都可以作为 Master端 或 Slaver端,比如:
Master端
(核心服务器) :使用 Windows 10,搭建一个Redis数据库,不负责爬取,只负责url判重、Request的分配,以及数据的存储Slaver端
(爬虫程序执行端) :使用 Mac OS X 、Ubuntu 16.04、CentOS 7.2,负责执行爬虫程序,运行过程中提交新的Request给MasterScrapy-Redis默认使用的就是这种策略,我们实现起来很简单,因为任务调度等工作Scrapy-Redis都已经帮我们做好了,我们只需要继承RedisSpider、指定redis_key就行了。
缺点是,Scrapy-Redis调度的任务是Request对象,里面信息量比较大(不仅包含url,还有callback函数、headers等信息),可能导致的结果就是会降低爬虫速度、而且会占用Redis大量的存储空间,所以如果要保证效率,那么就需要一定硬件水平。
windows 下载:
https://github.com/MicrosoftArchive/redis
点击release.
https://github.com/MicrosoftArchive/redis/releases/download/win-3.2.100/Redis-x64-3.2.100.msi
redis
配置
linux redis客户端连接windows的服务器
redis-cli -h 10.8.153.5
配置windows的redis服务器可以让其它客户端连接和读写
第56行,把这个注释掉
#bind 127.0.0.1
第75行
protected-mode no
2、分布式部署
(1)安装: pip install scrapy-redis
(2)样本查看
https://github.com/rmax/scrapy-redis/example-project/example/spiders
dmoz.py : 普通crawlspider,没有参考价值
myspider_redis.py : 分布式的Spider模板
mycrawler_redis.py : 分布式的CrawlSpider模板
Spider ====》 RedisSpider
CrawlSpider ====》 RedisCrawlSpider
name name
redis_key start_urls
__init__() allowed_domains
【注】__init__()是一个坑,现在还是使用allowed_domains这种列表的形式
(3)存储到redis中
scrapy-redis组件已经写好往redis中存放的管道,只需要使用即可,默认存储到本机的redis服务中
如果想存储到其它的redis服务中,需要在配置文件中配置
REDIS_HOST = 'ip地址'
REDIS_PORT = 6379
# 也可以使用 REDIS_URL = "redis://10.20.158.2:6379"
(4)部署分布式
爬虫文件按照模板文件修改
配置文件说明:
# 使用scrapy-redis组件的去重队列
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy-redis组件自己的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 是否允许暂停
SCHEDULER_PERSIST = True
【注】分布式爬取的时候,指令不是scrapy crawl xx
scrapy runspider xxx.py
在我的windows中往队列中添加起始url
lpush nnspider:start_urls "http://www.qutu.com/"
修改设置文件
# dupefilter: 去重
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy_redis的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 在redis中保持scrapy-redis用到的各个队列,从而允许暂停和暂停后恢复,也就是不清理redis queues
SCHEDULER_PERSIST = True
ITEM_PIPELINES = {
'example.pipelines.ExamplePipeline': 300,
# 使用redis管道:自动存入redis,默认存入本机的redis
'scrapy_redis.pipelines.RedisPipeline': 400,
}
# 配置远程连接redis
# REDIS_HOST = '10.20.158.2'
# REDIS_PORT = 6379
练习:抓取baidu百科
修改spider
from scrapy_redis.spiders import RedisCrawlSpider
from example.items import BaikeItem
class MyCrawler(RedisCrawlSpider):
"""Spider that reads urls from redis queue (myspider:start_urls)."""
name = 'mycrawler_redis'
redis_key = 'mycrawler:start_urls'
rules = (
# follow all links
Rule(LinkExtractor('item/.*'), callback='parse_page', follow=True),
)
allowed_domains = ['baike.baidu.com']
在redis中保存的记录
1) "mycrawler_redis:items" # 抓取到的数据
2) "mycrawler_redis:requests" # 所有待爬取的请求
3) "mycrawler_redis:dupefilter" # 所有重复的url
import json
import redis
import pymysql
def main():
redis_cli = redis.Redis(host='localhost',port=6379)
mysqldb = pymysql.connect(host='localhost', user='root', password='123456',database='spider')
while True:
source,data = redis_cli.blpop(['mycrawler_redis:items'])
item = json.loads(data)
print(item)
try:
cursor = mysqldb.cursor()
sql = "insert into pics(name, img) values ('%s','%s')" %(item.get('name'), item.get('picture_url'))
cursor.execute(sql)
mysqldb.commit()
cursor.close()
except mysqldb.Error as e:
mysqldb.rollback()
print(e)
if __name__ == '__main__':
main()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。