Python爬蟲scrapy-redis分布式執行個體(一)

來源:互聯網
上載者:User

標籤:col   host   queue   .com   use   命令   spider   取域   sch   

目標任務:將之前新浪網的Scrapy爬蟲項目,修改為基於RedisSpider類的scrapy-redis分布式爬蟲項目,將資料存入redis資料庫。

 

一、item檔案,和之前項目一樣不需要改變

# -*- coding: utf-8 -*-import scrapyimport sysreload(sys)sys.setdefaultencoding("utf-8")class SinanewsItem(scrapy.Item):    # 大類的標題和url    parentTitle = scrapy.Field()    parentUrls = scrapy.Field()    # 小類的標題和子url    subTitle = scrapy.Field()    subUrls = scrapy.Field()    # 小類目錄存放路徑    subFilename = scrapy.Field()    # 小類下的子連結    sonUrls = scrapy.Field()    # 文章標題和內容    head = scrapy.Field()    content = scrapy.Field()

 

二、spiders爬蟲檔案,使用RedisSpider類替換之前的Spider類,其餘地方做些許改動即可,具體代碼如下:

 

# -*- coding: utf-8 -*-import scrapyimport osfrom sinaNews.items import SinanewsItemfrom scrapy_redis.spiders import RedisSpiderimport sysreload(sys)sys.setdefaultencoding("utf-8")class SinaSpider(RedisSpider):    name = "sina"
# 啟動爬蟲的命令 redis_key = "sinaspider:strat_urls"  # 動態定義爬蟲爬取域範圍 def __init__(self, *args, **kwargs): domain = kwargs.pop(‘domain‘, ‘‘) self.allowed_domains = filter(None, domain.split(‘,‘)) super(SinaSpider, self).__init__(*args, **kwargs) def parse(self, response): items= [] # 所有大類的url 和 標題 parentUrls = response.xpath(‘//div[@id="tab01"]/div/h3/a/@href‘).extract() parentTitle = response.xpath(‘//div[@id="tab01"]/div/h3/a/text()‘).extract() # 所有小類的ur 和 標題 subUrls = response.xpath(‘//div[@id="tab01"]/div/ul/li/a/@href‘).extract() subTitle = response.xpath(‘//div[@id="tab01"]/div/ul/li/a/text()‘).extract() #爬取所有大類 for i in range(0, len(parentTitle)): # 爬取所有小類 for j in range(0, len(subUrls)): item = SinanewsItem() # 儲存大類的title和urls item[‘parentTitle‘] = parentTitle[i] item[‘parentUrls‘] = parentUrls[i] # 檢查小類的url是否以同類別大類url開頭,如果是返回True (sports.sina.com.cn 和 sports.sina.com.cn/nba) if_belong = subUrls[j].startswith(item[‘parentUrls‘]) # 如果屬於本大類,將儲存目錄放在本大類目錄下 if(if_belong): # 儲存 小類url、title和filename欄位資料 item[‘subUrls‘] = subUrls[j] item[‘subTitle‘] =subTitle[j] items.append(item) #發送每個小類url的Request請求,得到Response連同包含meta資料 一同交給回呼函數 second_parse 方法處理 for item in items: yield scrapy.Request( url = item[‘subUrls‘], meta={‘meta_1‘: item}, callback=self.second_parse) #對於返回的小類的url,再進行遞迴請求 def second_parse(self, response): # 提取每次Response的meta資料 meta_1= response.meta[‘meta_1‘] # 取出小類裡所有子連結 sonUrls = response.xpath(‘//a/@href‘).extract() items= [] for i in range(0, len(sonUrls)): # 檢查每個連結是否以大類url開頭、以.shtml結尾,如果是返回True if_belong = sonUrls[i].endswith(‘.shtml‘) and sonUrls[i].startswith(meta_1[‘parentUrls‘]) # 如果屬於本大類,擷取欄位值放在同一個item下便於傳輸 if(if_belong): item = SinanewsItem() item[‘parentTitle‘] =meta_1[‘parentTitle‘] item[‘parentUrls‘] =meta_1[‘parentUrls‘] item[‘subUrls‘] = meta_1[‘subUrls‘] item[‘subTitle‘] = meta_1[‘subTitle‘] item[‘sonUrls‘] = sonUrls[i] items.append(item) #發送每個小類下子連結url的Request請求,得到Response後連同包含meta資料 一同交給回呼函數 detail_parse 方法處理 for item in items: yield scrapy.Request(url=item[‘sonUrls‘], meta={‘meta_2‘:item}, callback = self.detail_parse) # 資料解析方法,擷取文章標題和內容 def detail_parse(self, response): item = response.meta[‘meta_2‘] content = "" head = response.xpath(‘//h1[@id="main_title"]/text()‘) content_list = response.xpath(‘//div[@id="artibody"]/p/text()‘).extract() # 將p標籤裡的常值內容合并到一起 for content_one in content_list: content += content_one item[‘head‘]= head[0] if len(head) > 0 else "NULL" item[‘content‘]= content yield item

 

 

三、settings檔案設定

SPIDER_MODULES = [‘sinaNews.spiders‘]NEWSPIDER_MODULE = ‘sinaNews.spiders‘# 使用scrapy-redis裡的去重組件,不使用scrapy預設的去重方式DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"# 使用scrapy-redis裡的調度器組件,不使用預設的調度器SCHEDULER = "scrapy_redis.scheduler.Scheduler"# 允許暫停,redis請求記錄不丟失SCHEDULER_PERSIST = True# 預設的scrapy-redis請求隊列形式(按優先順序)SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"# 隊列形式,請求先進先出#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"# 棧形式,請求先進後出#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"# 只是將資料放到redis資料庫,不需要寫pipelines檔案ITEM_PIPELINES = {#    ‘Sina.pipelines.SinaPipeline‘: 300,    ‘scrapy_redis.pipelines.RedisPipeline‘: 400,}# LOG_LEVEL = ‘DEBUG‘# Introduce an artifical delay to make use of parallelism. to speed up the# crawl.DOWNLOAD_DELAY = 1# 指定資料庫的主機IPREDIS_HOST = "192.168.13.26"# 指定資料庫的連接埠號碼REDIS_PORT = 6379

執行命令:

本次直接使用本地的redis資料庫,將settings檔案中的REDIS_HOST和REDIS_PORT注釋掉。

啟動爬蟲程式

scrapy runspider sina.py

執行程式後終端視窗顯示如下:

表示程式處於等待狀態,此時在redis資料庫端執行如下命令:

redis-cli> lpush sinaspider:start_urls http://news.sina.com.cn/guide/

http://news.sina.com.cn/guide/為起始url,此時程式開始執行。

Python爬蟲scrapy-redis分布式執行個體(一)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.