在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/人工智能  網(wǎng)絡(luò)安全/ scrapy-redis多臺機器部署,但只有一臺可執(zhí)行

scrapy-redis多臺機器部署,但只有一臺可執(zhí)行

問題描述

使用scrapy-redis進行分布式抓取時,遇到了一個很奇怪的問題,有倆臺機器,Windows電腦A,和Ubuntu電腦B,redis server部署在 Windows電腦A上,在電腦A,B啟動爬蟲后,倆只爬蟲都進入監(jiān)聽狀態(tài),在redis中進行 url的lpush操作,奇怪的事情發(fā)生了,電腦A,或者電腦B中只有一臺電腦能監(jiān)聽到 redis,但是具體哪個能夠監(jiān)聽到這個很隨機,有時是電腦A,有時是電腦B,我能確保,電腦A和B都是連接上了 redis的

運行環(huán)境

  • scrapy 1.5.0
  • scrapy-redis 0.6.8
  • redis.py 2.10.6
  • redis-server(windows x64) 3.2.100

運行截圖

分別啟動倆個spider

啟動倆個spider

第一次進行url的lpush操作,結(jié)果如下

圖片描述

這時只有爬蟲A監(jiān)聽到了 redis的操作,執(zhí)行抓取邏輯,而爬蟲B仍然處于監(jiān)聽狀態(tài)

手動停止倆只spider,并清空redis數(shù)據(jù),再次開啟爬蟲,執(zhí)行l(wèi)push操作,結(jié)果如下

圖片描述

這時,爬蟲B卻監(jiān)聽到了redis的操作,執(zhí)行抓取邏輯,而爬蟲A仍處于監(jiān)聽狀態(tài)

還有一張是lpush后 redis中的數(shù)據(jù)情況

被這個問題困擾了2天了,這倆天一直沒怎么睡,查了好多資料,試了好多辦法,都不行,中間我把redis服務(wù)放在了電腦c上,但是還行不行。

希望前輩們,能指點一二
圖片描述

回答
編輯回答
青黛色
排查了3天,最后可算是把 這個問題解決了,最后還是有完完全全的刨析了一次,scrapy-redis的源碼才找到問題.排查這個,要從爬蟲運行后,Redis中的隊列情況來入手

排查思路

  • 首先查看Redis中的請求隊列的情況,發(fā)現(xiàn)在執(zhí)行過程中只有存儲指紋過濾的隊列和item的隊列,沒有存儲Request的隊列
  • 查看源碼發(fā)現(xiàn),scrapy-redis在將請求入隊列和出隊列時,采用的是,將請求序列化后進行l(wèi)push和lpop后反序列化
  • 然后開啟斷點調(diào)試模式。在request lpush后,查看redis的情況,這時在redis中會出現(xiàn)key:reuqest的隊列,但是只有一個請求
  • 繼續(xù)斷點發(fā)現(xiàn) 在lpop后,由于只向redis中添加了一個request,所以在lpop后,list中就沒有元素了,redis會自動把list刪除
  • 所以這時,另一個爬蟲在查詢主機的redis請求隊列時,是查詢不到任何request的,所以是一直等待的狀態(tài)。
  • 這個跟爬取的數(shù)據(jù)結(jié)構(gòu)有感,爬取的是一個分頁的列表數(shù)據(jù),是在解析完當(dāng)前頁面后,才會生成下一頁的請求的。是深度優(yōu)先的模式
  • 每次只生成一個請求,所以redis請求隊列維護的也只有一個請求。所以就造成這樣的問題
  • 出現(xiàn)問題的代碼如下

        # 單頁面解析完成,開始構(gòu)建下一頁的數(shù)據(jù)
        next_page_link = response.xpath('//div[@class="grid-8"]/div[@class="navigation margin-20"]/a[@class="next page-numbers"]/@href').extract_first()

        if next_page_link is None or len(next_page_link) == 0:
            log.logger.info('completed all page request')

        else:
            log.logger.info('will request next page and request url is %s'%next_page_link)
            #問題出現(xiàn)這這里,每次只生成一個request,所以 redis隊列維護的也只有一個請求
            yield Request(url=next_page_link)

解決辦法

  • 采用廣度優(yōu)先的模式進行抓取
  • 獲取爬取的總頁數(shù),進行提取總頁碼,生成請求連接
  • 獲取待爬取的所有頁面的請求,循環(huán)入redis隊列,可解決這個問題
  • 代碼如下
        if self.already_push_all_request is not True:
            page_list_html_a = response.xpath('//div[@class="grid-8"]/div[@class="navigation margin-20"]/a[@class="page-numbers"]')
            last_page_list_html_a = page_list_html_a[-1]
            last_page_index = last_page_list_html_a.xpath('text()').extract_first()
            print(type(last_page_index))
            last_index_number = int(last_page_index)
            print last_index_number
            format_url = 'http://python.jobbole.com/all-posts/page/{0}/'
            next_page_index = 2
            while next_page_index <= last_index_number:
                next_page_request_url = format_url.format(next_page_index)
                print(' will lpush to redis and url is %s'%next_page_request_url)
                yield Request(url=next_page_request_url)
                next_page_index += 1
            self.already_push_all_request = True
2018年5月27日 12:53