第三百四十一節,Python分佈式爬蟲打造搜索引擎Scrapy精講—編寫spiders爬蟲文件循環抓取內容—meta屬性返回指定值給回調函數—Scrapy內置圖片下載器css
編寫spiders爬蟲文件循環抓取內容html
Request()方法,將指定的url地址添加到下載器下載頁面,兩個必須參數,
參數:
url='url'
callback=頁面處理函數
使用時須要yield Request()dom
parse.urljoin()方法,是urllib庫下的方法,是自動url拼接,若是第二個參數的url地址是相對路徑會自動與第一個參數拼接scrapy
# -*- coding: utf-8 -*- import scrapy from scrapy.http import Request #導入url返回給下載器的方法 from urllib import parse #導入urllib庫裏的parse模塊 class PachSpider(scrapy.Spider): name = 'pach' allowed_domains = ['blog.jobbole.com'] #起始域名 start_urls = ['http://blog.jobbole.com/all-posts/'] #起始url def parse(self, response): """ 獲取列表頁的文章url地址,交給下載器 """ #獲取當前頁文章url lb_url = response.xpath('//a[@class="archive-title"]/@href').extract() #獲取文章列表url for i in lb_url: # print(parse.urljoin(response.url,i)) #urllib庫裏的parse模塊的urljoin()方法,是自動url拼接,若是第二個參數的url地址是相對路徑會自動與第一個參數拼接 yield Request(url=parse.urljoin(response.url, i), callback=self.parse_wzhang) #將循環到的文章url添加給下載器,下載後交給parse_wzhang回調函數 #獲取下一頁列表url,交給下載器,返回給parse函數循環 x_lb_url = response.xpath('//a[@class="next page-numbers"]/@href').extract() #獲取下一頁文章列表url if x_lb_url: yield Request(url=parse.urljoin(response.url, x_lb_url[0]), callback=self.parse) #獲取到下一頁url返回給下載器,回調給parse函數循環進行 def parse_wzhang(self,response): title = response.xpath('//div[@class="entry-header"]/h1/text()').extract() #獲取文章標題 print(title)
Request()函數在返回url時,同時能夠經過meta屬性返回一個自定義字典給回調函數分佈式
# -*- coding: utf-8 -*- import scrapy from scrapy.http import Request #導入url返回給下載器的方法 from urllib import parse #導入urllib庫裏的parse模塊 from adc.items import AdcItem #導入items數據接收模塊的接收類 class PachSpider(scrapy.Spider): name = 'pach' allowed_domains = ['blog.jobbole.com'] #起始域名 start_urls = ['http://blog.jobbole.com/all-posts/'] #起始url def parse(self, response): """ 獲取列表頁的文章url地址,交給下載器 """ #獲取當前頁文章url lb = response.css('div .post.floated-thumb') #獲取文章列表區塊,css選擇器 # print(lb) for i in lb: lb_url = i.css('.archive-title ::attr(href)').extract_first('') #獲取區塊裏文章url # print(lb_url) lb_img = i.css('.post-thumb img ::attr(src)').extract_first('') #獲取區塊裏文章縮略圖 # print(lb_img) yield Request(url=parse.urljoin(response.url, lb_url), meta={'lb_img':parse.urljoin(response.url, lb_img)}, callback=self.parse_wzhang) #將循環到的文章url添加給下載器,下載後交給parse_wzhang回調函數 #獲取下一頁列表url,交給下載器,返回給parse函數循環 x_lb_url = response.css('.next.page-numbers ::attr(href)').extract_first('') #獲取下一頁文章列表url if x_lb_url: yield Request(url=parse.urljoin(response.url, x_lb_url), callback=self.parse) #獲取到下一頁url返回給下載器,回調給parse函數循環進行 def parse_wzhang(self,response): title = response.css('.entry-header h1 ::text').extract() #獲取文章標題 # print(title) tp_img = response.meta.get('lb_img', '') #接收meta傳過來的值,用get獲取防止出錯 # print(tp_img) shjjsh = AdcItem() #實例化數據接收類 shjjsh['title'] = title #將數據傳輸給items接收模塊的指定類 shjjsh['img'] = tp_img yield shjjsh #將接收對象返回給pipelines.py處理模塊
Scrapy內置圖片下載器使用ide
Scrapy給咱們內置了一個圖片下載器在crapy.pipelines.images.ImagesPipeline,專門用於將爬蟲抓取到圖片url後將圖片下載到本地函數
第一步、爬蟲抓取圖片URL地址後,填充到 items.py文件的容器函數post
爬蟲文件搜索引擎
# -*- coding: utf-8 -*- import scrapy from scrapy.http import Request #導入url返回給下載器的方法 from urllib import parse #導入urllib庫裏的parse模塊 from adc.items import AdcItem #導入items數據接收模塊的接收類 class PachSpider(scrapy.Spider): name = 'pach' allowed_domains = ['blog.jobbole.com'] #起始域名 start_urls = ['http://blog.jobbole.com/all-posts/'] #起始url def parse(self, response): """ 獲取列表頁的文章url地址,交給下載器 """ #獲取當前頁文章url lb = response.css('div .post.floated-thumb') #獲取文章列表區塊,css選擇器 # print(lb) for i in lb: lb_url = i.css('.archive-title ::attr(href)').extract_first('') #獲取區塊裏文章url # print(lb_url) lb_img = i.css('.post-thumb img ::attr(src)').extract_first('') #獲取區塊裏文章縮略圖 # print(lb_img) yield Request(url=parse.urljoin(response.url, lb_url), meta={'lb_img':parse.urljoin(response.url, lb_img)}, callback=self.parse_wzhang) #將循環到的文章url添加給下載器,下載後交給parse_wzhang回調函數 #獲取下一頁列表url,交給下載器,返回給parse函數循環 x_lb_url = response.css('.next.page-numbers ::attr(href)').extract_first('') #獲取下一頁文章列表url if x_lb_url: yield Request(url=parse.urljoin(response.url, x_lb_url), callback=self.parse) #獲取到下一頁url返回給下載器,回調給parse函數循環進行 def parse_wzhang(self,response): title = response.css('.entry-header h1 ::text').extract() #獲取文章標題 # print(title) tp_img = response.meta.get('lb_img', '') #接收meta傳過來的值,用get獲取防止出錯 # print(tp_img) shjjsh = AdcItem() #實例化數據接收類 shjjsh['title'] = title #將數據傳輸給items接收模塊的指定類 shjjsh['img'] = [tp_img] yield shjjsh #將接收對象返回給pipelines.py處理模塊
第二步、設置 items.py 文件的容器函數,接收爬蟲獲取到的數據填充url
# -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentation in: # http://doc.scrapy.org/en/latest/topics/items.html import scrapy #items.py,文件是專門用於,接收爬蟲獲取到的數據信息的,就至關因而容器文件 class AdcItem(scrapy.Item): #設置爬蟲獲取到的信息容器類 title = scrapy.Field() #接收爬蟲獲取到的title信息 img = scrapy.Field() #接收縮略圖 img_tplj = scrapy.Field() #圖片保存路徑
第三步、在pipelines.py使用crapy內置的圖片下載器
一、首先引入內置圖片下載器
二、自定義一個圖片下載內,繼承crapy內置的ImagesPipeline圖片下載器類
三、使用ImagesPipeline類裏的item_completed()方法獲取到圖片下載後的保存路徑
四、在settings.py設置文件裏,註冊自定義圖片下載器類,和設置圖片保存路徑
# -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html from scrapy.pipelines.images import ImagesPipeline #導入圖片下載器模塊 class AdcPipeline(object): #定義數據處理類,必須繼承object def process_item(self, item, spider): #process_item(item)爲數據處理函數,接收一個item,item裏就是爬蟲最後yield item 來的數據對象 print('文章標題是:' + item['title'][0]) print('文章縮略圖url是:' + item['img'][0]) print('文章縮略圖保存路徑是:' + item['img_tplj']) #接收圖片下載器填充的,圖片下載後的路徑 return item class imgPipeline(ImagesPipeline): #自定義一個圖片下載內,繼承crapy內置的ImagesPipeline圖片下載器類 def item_completed(self, results, item, info): #使用ImagesPipeline類裏的item_completed()方法獲取到圖片下載後的保存路徑 for ok, value in results: img_lj = value['path'] #接收圖片保存路徑 # print(ok) item['img_tplj'] = img_lj #將圖片保存路徑填充到items.py裏的字段裏 return item #將item給items.py 文件的容器函數 #注意:自定義圖片下載器設置好後,須要在
在settings.py設置文件裏,註冊自定義圖片下載器類,和設置圖片保存路徑
IMAGES_URLS_FIELD 設置要下載圖片的url地址,通常設置的items.py裏接收的字段
IMAGES_STORE 設置圖片保存路徑
# Configure item pipelines # See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html ITEM_PIPELINES = { 'adc.pipelines.AdcPipeline': 300, #註冊adc.pipelines.AdcPipeline類,後面一個數字參數表示執行等級, 'adc.pipelines.imgPipeline': 1, #註冊自定義圖片下載器,數值越小,越優先執行 } IMAGES_URLS_FIELD = 'img' #設置要下載圖片的url字段,就是圖片在items.py裏的字段裏 lujin = os.path.abspath(os.path.dirname(__file__)) IMAGES_STORE = os.path.join(lujin, 'img') #設置圖片保存路徑