分布式爬取scrapy-redis

主要来解决爬虫效率的问题,用几个机器同时来爬取,并保存到一个计算机。
scrapy.spider
crawlspider
共享爬取队列(待爬取队列):用redis来维护,无序集合,
管道爬取的数据默认会存储在redis中

分布式环境搭建:

pip install scrapy -i xxx
pip install scrapy-redis -i xxx

分析redis里面生成的key

items:爬取下来的数据list
dupefilter:已经入带爬取队列的请求、set去重
requests:待请求的对象,一旦爬取内容完成,就看不见requests
settings里的内容:
配置redis:默认保存到本地,如果需要保存其他机器,需要设置这一行代码,更换ip
REDIS_URL = “redis://127.0.0.1:6379”
bind 127.0.0.1 如果需要连接其他机器,要改为0.0.0.0

scrapy-redis源码分析

xpath模糊匹配:

pipeline.py redis生成key
PIPELINE_KEY = ‘%(spider)s:items’
self.key=’%(spider)s:items’
key = ‘%(spider)s:items’ % {‘spider’: spider.name}
占位符%(spider)s
dupefilter.py :形成一个字符串、完成去重
scheduler.py:调度器,里面的enqueue_request函数,判断请求是否存在、不存在就添加到任务队列

案例:盗墓笔记

爬取需求:爬取小说内容
建立一个文件夹,二级文件夹

  1. 找系列名称
  2. 查看源代码,可以从ul里找名称,但是不完整
  3. 通过id匹配,模糊匹配 //li[contains{id,"menu-item-")]/a
  4. from daomu.items import DaomuItem
  5. a_lis = response.xpath('//li[contains(@id, "menu-item-")]/a')
  6. for a in a_lis:
  7. item = DaomuItem()
  8. first_title = a.xpath('./text()').get() # 获取文本数据
  9. sencond_href = a.xpath('./@href').get() # 拿到二级页面的url
  1. # 需要获取小标题,进行text文件命名
  2. b_list = response.xpath('//article')
  3. for b in b_list:
  4. charper_title = b.xpath('./a/text()').get()
  5. content_url = b.xpath('./a/@href').get()
  1. content_list = response.xpath('//article[@class="article-content"]/p/text()').getall()
  2. item['content'] = '\n'.join(content_list) # 把列表元素string用换行符拼接

如果爬取出来的文件名 包含特殊字符会报错,因此要进行处理,正则替换

  1. # 利用正则替换
  2. import re
  3. import os
  4. s = r'七星鲁王:第一章 血尸' # r防止字符串被转义
  5. first_title = re.sub(r'[\\\/\:\*\?\"\<\>\| ]', '_', s) # 把字符集里的符号换成下划线_
  6. print(first_title)
  7. second_title
  8. # 创建文件路径
  9. dir_path = r'.\novel/{}'.format(first_title)
  10. print(dir_path)
  11. # os.makedirs()文件已存在的话就会报错
  12. # 文件路径若不存在 再创建
  13. if not os.path.exist(dir_path):
  14. # 创建文件路径
  15. os.makedirs(dir_path)
  16. # 小说内容文件具体路径
  17. filename = os.path.join(dir_path, first_title)+'.txt'
  18. # 写入内容
  19. with open(filename, 'w','utf-8') as f:
  20. f.write(item['content'])

修改成分布式

  1. 先使用普通的scrapy实现
  2. 爬虫文件中
  3. 修改继承类scrapyspider--->RedisSpider
  4. from copy import deepcopy
  5. 修改配置文件settings
  6. # 需要修改
  7. USER_AGENT = 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36 Edg/100.0.1185.50'
  8. # 设置去重方式
  9. DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
  10. #设置调度器
  11. SCHEDULER = "scrapy_redis.scheduler.Scheduler"
  12. #是否进行持久保存
  13. SCHEDULER_PERSIST = True
  14. pipeline中添加
  15. ITEM_PIPELINES = {
  16. 'daomubiji.pipelines.DaomubijiPipeline': 300,
  17. 'scrapy_redis.pipelines.RedisPipeline': 400,
  18. }
  19. 配置redis
  20. REDIS_URL = "redis://127.0.0.1:6379"