scrapy框架五大核心組件


爬蟲五大核心組件

 組件的作用:
        引擎(Scrapy)
            用來處理整個系統的數據流處理, 觸發事務(框架核心)
        調度器(Scheduler)
            用來接受引擎發過來的請求, 壓入隊列中, 並在引擎再次請求的時候返回. 可以想像成一個URL(抓取網頁的網址或者說是鏈接)的優先隊列, 由它來決定下一個要抓取的網址是什么, 同時去除重復的網址
        下載器(Downloader)
            用於下載網頁內容, 並將網頁內容返回給蜘蛛(Scrapy下載器是建立在twisted這個高效的異步模型上的)
        爬蟲(Spiders)
            爬蟲是主要干活的, 用於從特定的網頁中提取自己需要的信息, 即所謂的實體(Item)。用戶也可以從中提取出鏈接,讓Scrapy繼續抓取下一個頁面
        項目管道(Pipeline)
            負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證實體的有效性、清除不需要的信息。當頁面被爬蟲解析后,將被發送到項目管道,並經過幾個特定的次序處理數據。

請求傳參的實現深度爬取

請求傳參實現的深度爬取
- 深度爬取:爬取的數據沒有在同一張頁面中(首頁數據+詳情頁數據)
- 在scrapy中如果沒有請求傳參我們是無法持久化存儲數據
- 實現方式:
    - scrapy.Request(url,callback,meta)
        - meta是一個字典,可以將meta傳遞給callback
    - callback取出meta:
        - response.meta

代碼實現:

# -*- coding: utf-8 -*-
import scrapy

from movie.items import MovieItem
class MovieTestSpider(scrapy.Spider):
    name = 'movie_test'
    # allowed_domains = ['www.xxxxx.com']
    start_urls = ['https://www.4567kan.com/index.php/vod/show/id/5.html']

    url ="https://www.4567kan.com/index.php/vod/show/id/5/page/{}.html"
    page = 2
    def parse(self, response):
        li_list = response.xpath("/html/body/div[1]/div/div/div/div[2]/ul/li")
        for li in li_list:
            titile = li.xpath("./div/a/@title").extract_first()
            src = "https://www.4567kan.com"+li.xpath("./div/a/@href").extract_first()

            item = MovieItem()
            item["title"] = titile


            yield scrapy.Request(url = src,callback=self.parse_movie,meta={"item":item})

        if self.page<5:
            new_url = self.url.format(self.page)
            self.page+=1
            yield scrapy.Request(url = new_url,callback=self.parse)




    def parse_movie(self,response):
        print(response)
        item = response.meta["item"]
        desc = response.xpath('/html/body/div[1]/div/div/div/div[2]/p[5]/span[2]/text()').extract_first()
        item["desc"] = desc
        yield item


中間件

  • 作用:批量攔截請求和響應

  • 爬蟲中間件(暫時未講)

  • 下載中間件(推薦)

    • 攔截請求:
      • 篡改請求Url
      • 偽裝請求頭信息
        • UA
        • cookie
      • 設置請求代理(重點)
    • 攔截響應
      • 篡改響應數據
    • 代理操作必須使用中間件才可以實現
      • process_exception:
        • request.meta["proxy"] = "http:// ip:port"

middlewares.py代碼

class MiddleproDownloaderMiddleware(object):
	#攔截所有的請求(正常和異常的都算上)
	def process_request(self,request,spider):
		print("process_request()")
		request.headers["User-Agent"] = "xxxx"
		request.headers["Cookie"] = "xxxxx"  #但是平常我們不會這么做,因為settings中有cookie配置,scrapy每次請求會帶這cook 
		return None  #或者request
		
	#攔截所有響應的對象
	#參數:response攔截到的響應對象,request響應對象對應的請求對象
	def process_exception(self,request,response,spider):
		print("process_response()")
		return response
		
	#攔截異常的請求
	#參數:request就是攔截到的發生異常的請求
	#作用:想要將異常的請求進行修正,將其變成正常的請求,然后對其重新發送
	def process_exception(self.request,exception,spider):
		#請求的ip被禁掉,該請求就會變成一個異常的請求
		#這里的meta跟請求傳參一樣。都是Request
		request.meta["proxy"] = "http://ip:port" #設置代理
		print("process_exception()")
		return request #將異常的請求修正后將其重新發送
		

在settings中

打開這個配置,每次請求都會帶這cookie,不需要咱們去添加!

下載圖片的爬取

大文件下載:大文件數據是在管道中請求到的

  • 下屬管道類是scrapy封裝好的我們直接用即可:

  • from scrapy.pipelines.images import ImagesPipeline #提供了數據下載功能

    重寫該管道類的三個方法:

    • get_media_requests
      • 對圖片地址發起請求
    • file_path
      • 返回圖片名稱即可
    • item_copleted
      • 返回item,將其返回給下一個即將被執行的管道類
    • 在配置文件中添加:
      • IMAGES_STORE = 'dirName'

img.py

import scrapy

from imgPro.items import ImgproItem
class ImgSpider(scrapy.Spider):
    name = 'img'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['http://www.521609.com/daxuexiaohua/']

    def parse(self, response):
        #解析圖片地址和圖片名稱
        li_list = response.xpath('//*[@id="content"]/div[2]/div[2]/ul/li')
        for li in li_list:
            img_src = 'http://www.521609.com'+li.xpath('./a[1]/img/@src').extract_first()
            img_name = li.xpath('./a[1]/img/@alt').extract_first()+'.jpg'

            item = ImgproItem()
            item['name'] = img_name
            item['src'] = img_src

            yield item

items.py

import scrapy


class ImgproItem(scrapy.Item):
    # define the fields for your item here like:
    name = scrapy.Field()
    src = scrapy.Field()

pipelines.py

#該默認管道無法幫助我們請求圖片數據,因此該管道我們就不用
# class ImgproPipeline(object):
#     def process_item(self, item, spider):
#         return item

#管道需要接受item中的圖片地址和名稱,然后再管道中請求到圖片的數據對其進行持久化存儲
from scrapy.pipelines.images import ImagesPipeline #提供了數據下載功能
from scrapy.pipelines.media import MediaPipeline
from scrapy.pipelines.files import FilesPipeline
import scrapy
class ImgsPipiLine(ImagesPipeline):
    #根據圖片地址發起請求
    def get_media_requests(self, item, info):
        # print(item)
        yield scrapy.Request(url=item['src'],meta={'item':item})
    #返回圖片名稱即可
    def file_path(self, request, response=None, info=None):
        #通過request獲取meta
        item = request.meta['item']
        filePath = item['name']
        return filePath #只需要返回圖片名稱
    #將item傳遞給下一個即將被執行的管道類
    def item_completed(self, results, item, info):
        return item

settings.py

ITEM_PIPELINES = {
   'imgPro.pipelines.ImgsPipiLine': 300,
}
IMAGES_STORE = './imgLibs'


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM