OK!终于到了分布式爬虫了,说下,我整了几天才把分布式爬虫给搞定。(内心苦哇)为何会这么久,请听我徐徐道来。html
在使用分布式爬虫的时候通用的作法是一台电脑做为master端,另外的多台电脑做为slaver端,我采用的是主机与虚拟机来搭建的环境,说说个人主机,一台联想的y410笔记本,只有4G的内存,用到如今已经快5年了,还很坚挺 :-)就是内存小了点,个人虚拟机用的是xubuntu(轻量级的ubuntu),虚拟机做为的master端,master端的redis用来存储数据以及url去重,主机做为slaver端执行代码。这里面有一步很关键,那就是个人主机(slaver端)要可以访问个人虚拟机(master端)里面的redis数据库才行,很无奈我就是卡在了这里,个人主机不管如何都没法ping通虚拟机,也就是访问不了xubuntu的redis数据库,在网上找了各类解决方法,都行不通,最后没办法了直接卸载了vnware重装以后,又修改了下网络配置,才最终解决问题。实属心酸~mysql
因此呀,若是有小伙伴碰见相似的问题,除了google以外,能够直接考虑重装下本身的vmware。redis
嗯~好,当主机与虚拟机ping通以后就能够来作分布式了,具体实现细节我就再也不赘余了,百度一下出来一大堆结果。我以后会写一篇关于scrapy-redis的源码解读的博客。这里只是记录一下具体代码实现的过程。sql
http://politics.people.com.cn/GB/1024/index1.html
一样无反爬措施,能够安心使用。mongodb
1 import scrapy 2 3 4 class PeopleItem(scrapy.Item): 5 # define the fields for your item here like: 6 # name = scrapy.Field() 7 title = scrapy.Field() 8 pub_time = scrapy.Field() 9 url = scrapy.Field() 10 content = scrapy.Field()
1 # -*- coding: utf-8 -*- 2 import scrapy 3 4 from scrapy_redis.spiders import RedisSpider 5 from ..items import PeopleItem 6 7 8 class RedisTestSpider(RedisSpider): 9 name = 'redis-test' 10 # allowed_domains = ['people.com.cn'] 有坑需注意 11 # start_urls = ['http://politics.people.com.cn/GB/1024/index1.html'] 12 13 redis_key = "redistest:start_urls" 14 15 def __init__(self, *args, **kwargs): 16 domain = kwargs.pop('domain', '') 17 self.allowed_domains = filter(None, domain.split(',')) 18 super(RedisTestSpider, self).__init__(*args, **kwargs) 19 20 def parse(self, response): 21 news_list = response.xpath("//div[@class='ej_list_box clear']/ul/li") 22 for new in news_list: 23 item = PeopleItem() 24 title = new.xpath("./a/text()").extract_first() 25 url = new.xpath("./a/@href").extract_first() 26 url = "http://politics.people.com.cn" + url 27 pub_time = new.xpath("./em/text()").extract_first() 28 29 item["title"] = title 30 item["url"] = url 31 item["pub_time"] = pub_time 32 yield scrapy.Request(url=url, meta={"item": item}, callback=self.parse_detail, 33 dont_filter=True) # 必需要加上 dont_filter 参数 34 35 # 下一页 36 next_page_url = response.xpath("//div[@class='page_n clearfix']/a[last()]/@href").extract_first() 37 next_page_url = "http://politics.people.com.cn/GB/1024/" + next_page_url 38 is_active = response.xpath("//div[@class='page_n clearfix']/a[last()]/@href").extract_first() 39 40 if next_page_url and is_active != "common_current_page": 41 yield scrapy.Request(url=next_page_url, callback=self.parse, dont_filter=True) # 必需要加上 dont_filter 参数 42 43 def parse_detail(self, response): 44 item = response.meta["item"] 45 article = "" 46 content_list = response.xpath("//div[@class='fl text_con_left']//p/text()").extract() 47 for content in content_list: 48 content = content.strip() 49 article += content 50 print(article) 51 item["content"] = article 52 yield item
spiders.py 这里会有坑的,人民网他的url设计的时候跨度比较大 allowed_domains = ['people.com.cn'] 有时候没法匹配的上,这个时候会控制台会报以下错:数据库
2019-02-11 00:25:51 [scrapy.spidermiddlewares.offsite] DEBUG: Filtered offsite request to 'politics.people.com.cn': <GET http://politics.people.com.cn/n1/2019/0210/c1024-30616296.html>
解决的办法就是将allowed_domains = ['people.com.cn'] 注释掉,若是还不能解决就加上 dont_filter ,表示本次请求不要要对url进行过滤。ubuntu
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 \ Safari/537.36 SE 2.X MetaSr 1.0' ROBOTSTXT_OBEY = False ITEM_PIPELINES = { # 'people.pipelines.PeoplePipeline': 300, 'scrapy_redis.pipelines.RedisPipeline': 400, } # 使用scrapy-redis的去重规则 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # 使用scrapy-redis的引擎 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 暂停功能 SCHEDULER_PERSIST = True # 默认的scrapy-redis请求队列形式(按优先级) SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue" # 注释掉默认使用主机的redis # REDIS_HOST = '192.168.48.128' # REDIS_PORT = 6379
将redis里面的数据存储至mongodb / mysql 这里我在网上找到了一些文章我本身尚未取验证,目前主流的作法是单独的写脚本,从redis里面取数据,我是以为这种作法特别的很差、特别的low,等我验证了网上的一些教程后在来贴出来。网络
ok,scrapy真的是一个可拓展性很强的框架,短短的几行设置就可以实现分布式,往后我会更新一些反爬虫措施强一点的网站、模拟登陆、以及scrapy的源码解读。总是爬一些无反爬措施的网站真的没什么意思。休息了休息了~框架