scrapy--分布式爬蟲(chóng)

為什么使用分布式爬蟲(chóng)

分布式:MongoDB的主從(一主多從)
分布式就比如說(shuō)一個(gè)工廠生產(chǎn)線,有車間主人,車間主人分配任務(wù)給一個(gè)員工,和任務(wù)分給多個(gè)員工的時(shí)候,那是一個(gè)人還是多個(gè)人的效率高那

同理

  • 單機(jī)版爬蟲(chóng):

引擎把一個(gè)request請(qǐng)求任務(wù)放到調(diào)度器任務(wù)隊(duì)列,向服務(wù)器發(fā)起請(qǐng)求的時(shí)候會(huì)從調(diào)度器拿到request請(qǐng)求給下載器發(fā)起請(qǐng)求。


image.png
  • 多臺(tái)機(jī)器同時(shí)爬取數(shù)據(jù)大大提高了爬取的效率。當(dāng)多臺(tái)機(jī)器同時(shí)進(jìn)行爬蟲(chóng)的時(shí)候我們需要一個(gè)資源管理的容器(調(diào)度器)取管理和分配任務(wù)


    image.png

提取的數(shù)據(jù)、新提取的url會(huì)繼續(xù)構(gòu)建一個(gè)request請(qǐng)求交給資源管理器

scrapy-redis

安裝:pip3 install scrapy-redis

  • Scrapy_redis在scrapy的基礎(chǔ)上實(shí)現(xiàn)了更多,更強(qiáng)大的功能,具體體現(xiàn)在:reqeust去重,爬蟲(chóng)持久化,和輕松實(shí)現(xiàn)分布式
  • Scrapy-redis提供了下面四種組件(components):(四種組件意味著這四個(gè)模塊都要做相應(yīng)的修改)

Scheduler
Duplication Filter
Item Pipeline
Base Spider

  • Scrapy_redis是工作流程:


    image.png

具體操作:

配置settings文件

# 1:設(shè)置去重組件,使用的是scrapy_redis的去重組件,而不是scrapy自己的去重組件了
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 2:設(shè)置調(diào)度器,使用scrapy——redis重寫(xiě)的調(diào)度器,
# 而不再使用scrapy內(nèi)部的調(diào)度器了
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 3:可以實(shí)現(xiàn)斷點(diǎn)爬取=jondir,(請(qǐng)求的記錄不會(huì)丟失,會(huì)存儲(chǔ)在redis數(shù)據(jù)庫(kù)中,
# 不會(huì)清楚 redis的隊(duì)列,下次直接從redis的隊(duì)列中爬?。?SCHEDULER_PERSIST = True
# 4:設(shè)置任務(wù)隊(duì)列的模式(三選一):
# SpiderPriorityQueue數(shù)據(jù)scrapy-redis默認(rèn)使用的隊(duì)列模式(
# 有自己的優(yōu)先級(jí))默認(rèn)第一種
SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"
# 使用了隊(duì)列的形式,任務(wù)先進(jìn)先出。
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"
# 采用了棧的形式:任務(wù)先進(jìn)后出
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"
#5: 實(shí)現(xiàn)這個(gè)管道可以將爬蟲(chóng)端獲取的item數(shù)據(jù),統(tǒng)一保存在redis數(shù)據(jù)庫(kù)中
ITEM_PIPELINES = {
    'scrapy_redis.pipelines.RedisPipeline': 400,
}

# 6:指定要存儲(chǔ)的redis數(shù)據(jù)庫(kù)的主機(jī)IP
REDIS_HOST = '127.0.0.1'  # 遠(yuǎn)端的ip地址

# 指定redis數(shù)據(jù)庫(kù)主機(jī)的端口
REDIS_PORT = 6379

使用scrapy-redis

  • 代碼執(zhí)行之后redis自動(dòng)生成以下內(nèi)容:
"xcfCrawlSpider:requests":存儲(chǔ)的是請(qǐng)求的request對(duì)象
"xcfCrawlSpider:items":存儲(chǔ)的爬蟲(chóng)端獲取的items數(shù)據(jù)
"xcfCrawlSpider:dupefilter":存儲(chǔ)的指紋(為了實(shí)現(xiàn)去重)
127.0.0.1:6379> type xcfCrawlSpider:requests
zset
127.0.0.1:6379> type xcfCrawlSpider:items
list
127.0.0.1:6379> type xcfCrawlSpider:dupefilter
set
  • 第一種情況:只設(shè)置settings文件,并沒(méi)有實(shí)現(xiàn)分布式,只是實(shí)現(xiàn)了scrapy_redis的數(shù)據(jù)儲(chǔ)存和去重功能(只實(shí)現(xiàn)了存,沒(méi)有?。?/li>
import scrapy
from xiachufang.items import XiachufangTagItem,XiachufangCaiPuItem,XiachufangUserInfoItem


class XcfSpider(scrapy.Spider):
    name = 'xcf'
    allowed_domains = ['xiachufang.com']
    #start_urls = ['https://www.xiachufang.com/category/40076/?page=1']
    start_urls = ['http://www.xiachufang.com/category/']

    def start_requests(self):
        pass
  • 第二種:通用爬蟲(chóng)
from scrapy_redis.spiders import RedisCrawlSpider
# 繼承自redis——crawlspider
class MyCrawler(RedisCrawlSpider):
    """Spider that reads urls from redis queue (myspider:start_urls)."""
    name = 'mycrawler_redis'
    # 缺少了start_url,多了redis_key:根據(jù)redis_key從redis數(shù)據(jù)庫(kù)中獲取任務(wù)
    redis_key = 'mycrawler:start_urls'

啟動(dòng)爬蟲(chóng)
爬蟲(chóng)出現(xiàn)等待狀態(tài):我們需要在redis中設(shè)置起始任務(wù):
redis輸入命令:lpush xcfCrawlSpider:start_urls http://www.xiachufang.com/category/

注意:在redis保存起始url的時(shí)候,windows系統(tǒng)寫(xiě)url的時(shí)候不加引號(hào),ubuntu如果輸入redis命令不生效,url需要加引號(hào)

  • 第三種情況:實(shí)現(xiàn)scrpy.spider爬蟲(chóng)的分布式爬蟲(chóng)
  from scrapy_redis.spiders import RedisSpider
    #繼承自:RedisSpider
    class MyCrawler(RedisSpider):
        """Spider that reads urls from redis queue (myspider:start_urls)."""
        name = 'mycrawler_redis'
        allowed_domains = ['dmoz.org']
        #缺少了start_url,多了redis_key:根據(jù)redis_key從redis
        #數(shù)據(jù)庫(kù)中獲取任務(wù)
        redis_key = 'mycrawler:start_urls'

        def start_requests(self):
            """
            重寫(xiě)這個(gè)方法的目的可以根據(jù)自己的需求發(fā)起請(qǐng)求
            :return:
            """
            for url in self.start_urls:
                yield scrapy.Request(url, callback=self.parse, dont_filter=True)
        def parse(self, response):
             pass
    啟動(dòng)爬蟲(chóng):scrapy crawl 爬蟲(chóng)名稱
    現(xiàn)象:爬蟲(chóng)處于等待狀態(tài)
    需要設(shè)置起始任務(wù):
    lpush mycrawler:start_urls 目標(biāo)url

注意:實(shí)現(xiàn)scrpy.spider爬蟲(chóng)的分布式爬蟲(chóng)第一個(gè)回調(diào)方法必須是parse,否則代碼無(wú)法運(yùn)行。第三種情況同樣要注意redis的命令

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容