要爬取的目标网站地址:http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1
要爬取的内容为问政标题和处理状态。
1、首先介绍Spider.py里面的代码
1.1、首先,如果要使用scrapy_redis分布式,需要导入scrapy_redis对应的包。这里使用深度爬取CrawlSpider来进行
from scrapy_redis.spiders import RedisCrawlSpider
1.2、将spider类继承自scrapy_redis的类,这里使用RedisCrawlSpider
class TestSpider(RedisCrawlSpider):
1.3、我们需要把allow_domain和start_urls进行注释,因为要进行分布式爬取,需要有一个共享的调度队列(用来存放请求对象URL的),所以这里要使用一个redis_key = ‘ts’,用于后续在使用redis时进行放入起始的URL
name = 'test'
#http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1
redis_key = 'ts'
# start_urls = ['http://wz.sun0769.com/political/index/politicsNewest?id=1&page=10']
完整的spider代码
# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
#1、第一步导包
from scrapy_redis.spiders import RedisCrawlSpider
from scrapyRedisPro.items import ScrapyredisproItem
#2、
class TestSpider(RedisCrawlSpider):
#3、
name = 'test'
redis_key = 'ts'
# start_urls = ['http://wz.sun0769.com/political/index/politicsNewest?id=1&page=10']
link = LinkExtractor(allow=r'id=1&page=\d+') #这个链接提取器用于提取页码
rules = (
Rule(link, callback='parse_item', follow=True),
)
def parse_item(self, response):
li_list = response.xpath('/html/body/div[2]/div[3]/ul[2]/li')
for li in li_list:
title = li.xpath('./span[3]/a/text()').extract_first()
state = li.xpath('./span[2]/text()').extract_first()
state = state.strip()
item = ScrapyredisproItem()
item['title'] = title
item['state'] = state
print(item)
yield item
2、接着需要对Settings进行配置,进行基于Scrapy-redis下相关的共享的Pipeline管道和调度器等其他配置
2.1、在Settings里面,进行管道Pipeline、调度器Schedule、过滤器等其他配置,因为要进行分布式爬取,不仅是要有共享的请求队列,还需要有共享的Pipeline管道,才能对数据进行统一的存储和管理。
ITEM_PIPELINES = {
#提交到scrapy_redis的管道中
'scrapy_redis.pipelines.RedisPipeline': 300
# 'scrapyRedisPro.pipelines.ScrapyredisproPipeline': 300,
}
#增加了一个去重容器类的配置,作用使用Redis的set集合来存储请求的指纹数据
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
#使用Scrapy-Redis组件自己的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
#配置调度器是否要持久化,也就是当爬虫结束了,要不要清空Redis中请求队列和去重。
#如果=True,当机器出现宕机,那么重新连接后会接着去爬,否则从0开始。相对于增量式操作。
SCHEDULER_PERSIST = True
#Scrapy默认的开启32个线程池,进行并发的去爬取数据。因为本身爬取的数据比较少,只有10W条,所以没必要开启32,但改的主要原因是因为效果演示问题。如果某台机器网速比较好,很有可能直接将所有请求对象抢去,所以将它从32改为2方便演示。但如果你网速够好,这不是必要改的
CONCURRENT_REQUESTS = 1
3、进行redis服务器配置
#指定redis服务器
#这里要设置存储到哪一台机器的IP地址,设置到了哪一台的IP,那么数据就会存入哪一台机器中
REDIS_HOST = '192.168.1.6'
REDIS_POST = 6379
4、配置redis文件,修改redis.conf文件
4.1,我的主机是Mac主机,那么redis的目录是在/usr/local/etc/redis.conf,要修改的话可以在终端输入:vim /usr/local/etc/redis.conf,或者是直接前往文件夹找到
对应的Windows下,在redis的安装目录下即可找到
4.2修改文件
1、将这行bind注释掉,bind 127.0.0.1表示的是只有本机才能访问redis数据库,而如果假设我需要将Windows的机器爬取的数据和Mac爬取的数据都存储到的是Mac下的redis数据库中,那么需要把这行注释掉,Windows的机器才能访问。
2、修改保护模式,默认是yes,表示分布式其他机器可以访问你的redis但是只能读,但是不能写。而真正的分布式是需要进行写入的,所以这里需要把其改为no
5、启动redis
5.1、我这里以将数据存储到Windows的redis数据库中为例,所以在Windows下的终端下输入以下命令携带刚刚修改好的redis.conf配置文件来启动(默认是不启动的),此时就能看到redis服务器的启动
这个终端表示redis服务器的启动,不能关闭!在此基础上,再次开启一个终端,用来启动redis的客户端
6、启动工程项目
6.1、这里启动过程,需要进入到项目中的Spider模块中。
然后执行:scrapy runspider test.py,来启动
然后可以看到,在终端上显示,此时项目处于监听状态
6.2、往调度器的队列中扔一个URL
此时,就可以在Pycharm下看到整个项目开始在运行了
此时,再次查询redis,可以看到其下面多了3个数据结构
有时候会发现,test:requests的数据结构会消失,这是因为你的网络速度较快,一台机器即可处理,这会导致可能2台机器上只有一台在运行,另外一台处于监听状态。对于这种情况我是这么处理。
1、因为请求对象还是取决了你的起始URL。比如在这个项目中,这里我是使用CrawlSpider来深度爬取的,如果扔入的起始URL是第一页,那么很容易出现这种情况,我将起始URL扔为网页中的第5000页左右,是可以避免的
2、起始URL其实是可以扔入多个URL的,在这里扔入网站的第一页、第5000页、第8000页,这样也是可以看到两台分布式的机器都在运行