scrapy本身是不支持分布式爬取的,但和组件scrapy-redis一起使用,则支持分布式爬取。
分布式爬取原理:所有爬虫端共享redis里面的request请求,然后从这里面获取请求,再去爬取,直至队列为空。
本例共使用了3个系统,win10和ubuntu作为爬虫客户端,另外一个ubuntu存放redis数据库用来保存爬取的数据 请求及去重指纹。
目的:通过简单分布式爬取腾讯社招每个分页的职位相关信息,明白使用scrapy及scrapy-redis组件搭建分布式爬虫的思路。可在使用crawlspider类爬虫的基础上修改,进而搭建分布式。
重点:在settings.py设置文件里面的添加的修改,主要是把爬取时的数据 请求 去重指纹保存到redis里面,因为scrapy默认不支持分布式,而scrapy-redis组件使用redis才支持分布式;爬虫文件主要是进行分布式爬取,注意每个爬虫端都要保证可以使用redis-cli来连接服务端的redis;把爬取到的数据可以从redis里面读取出来保存到mysql和mongodb里面。当然,也可以直接书写分布式爬虫,主要是保存数据到redis和爬虫文件,这和修改的用法一样。
遇到的问题:爬取时有一个爬虫端不能爬取数据,另外一个爬取完爬虫端没有关闭
解决的方法:经过测试发现,是由于异步请求的个数设置过大导致一个爬虫端就可以完成,把settings.py文件里面的CONCURRENT_REQUESTS 设置一个合适的数就可以。关于爬取完关闭爬虫,则采用超时方法解决,可参考scrapy_redis 解决空跑问题,自动关闭爬虫,主要在项目的设置文件settings.py及同级目录再添加一个文件解决。
要爬取的目标内容items.py
# -*- coding: utf-8 -*- import scrapy class TencentItem(scrapy.Item): # 职位名称 job_Title = scrapy.Field() # 详细链接 job_Link = scrapy.Field() # 职位类型 job_Type = scrapy.Field() # 职位人数 job_Number = scrapy.Field() # 工作位置 job_Location = scrapy.Field() # 发布日期 job_PublicDate = scrapy.Field() # utc时间 unix_Time = scrapy.Field() # 爬虫名 spider_Name = scrapy.Field()
爬虫文件tc.py
#!/usr/bin/env python # -*- coding: utf-8 -*- import scrapy from scrapy.linkextractors import LinkExtractor # from scrapy.spiders import CrawlSpider, Rule from scrapy_redis.spiders import RedisCrawlSpider from scrapy.spiders import Rule from tencent.items import TencentItem # class TencentShezhaoSpider(CrawlSpider): class TencentXiaozhaoSpider(RedisCrawlSpider): name = 'tencent_shezhao' # allowed_domains = ['tencent.com'] # start_urls = ['https://hr.tencent.com/position.php?&start=0#a'] redis_key = 'TencentXiaozhaoSpider:start_urls' def __init__(self, *args, **kwargs): domain = kwargs.pop('domain', '') self.allowed_domains = filter(None, domain.split(',')) super(TencentXiaozhaoSpider, self).__init__(*args, **kwargs) # 获取匹配分页页码的链接的正则表达式 page_link = LinkExtractor(allow='start=\d+') rules = ( Rule(page_link, callback='parse_item',follow=True), ) def parse_item(self, response): # print '='*60 # print response.url # print '='*60 job_list = response.xpath('//tr[@class="odd"] | //tr[@class="even"]') item = TencentItem() for each in job_list: item['job_Title'] = each.xpath('./td[1]/a/text()')[0].extract() item['job_Link'] = each.xpath('./td[1]/a/@href')[0].extract() item['job_Type'] =