scrapy

Scrapy是一個爲了爬取網站數據,提取結構性數據而編寫的應用框架。 其能夠應用在數據挖掘,信息處理或存儲歷史數據等一系列的程序中。
其最初是爲了頁面抓取 (更確切來講, 網絡抓取 )所設計的, 也能夠應用在獲取API所返回的數據(例如 Amazon Associates Web Services ) 或者通用的網絡爬蟲。Scrapy用途普遍,能夠用於數據挖掘、監測和自動化測試。html

 

 

 

 

Scrapy主要包括瞭如下組件:python

  • 引擎(Scrapy)
    用來處理整個系統的數據流處理, 觸發事務(框架核心)
  • 調度器(Scheduler)
    用來接受引擎發過來的請求, 壓入隊列中, 並在引擎再次請求的時候返回. 能夠想像成一個URL(抓取網頁的網址或者說是連接)的優先隊列, 由它來決定下一個要抓取的網址是什麼, 同時去除重複的網址
  • 下載器(Downloader)
    用於下載網頁內容, 並將網頁內容返回給蜘蛛(Scrapy下載器是創建在twisted這個高效的異步模型上的)
  • 爬蟲(Spiders)
    爬蟲是主要幹活的, 用於從特定的網頁中提取本身須要的信息, 即所謂的實體(Item)。用戶也能夠從中提取出連接,讓Scrapy繼續抓取下一個頁面
  • 項目管道(Pipeline)
    負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證明體的有效性、清除不須要的信息。當頁面被爬蟲解析後,將被髮送到項目管道,並通過幾個特定的次序處理數據。
  • 下載器中間件(Downloader Middlewares)
    位於Scrapy引擎和下載器之間的框架,主要是處理Scrapy引擎與下載器之間的請求及響應。
  • 爬蟲中間件(Spider Middlewares)
    介於Scrapy引擎和爬蟲之間的框架,主要工做是處理蜘蛛的響應輸入和請求輸出。
  • 調度中間件(Scheduler Middewares)
    介於Scrapy引擎和調度之間的中間件,從Scrapy引擎發送到調度的請求和響應。

 

1.建立項目

scrapy startproject your_project_name

項目文件說明:web

  • scrapy.cfg  項目的配置信息,主要爲Scrapy命令行工具提供一個基礎的配置信息。(真正爬蟲相關的配置信息在settings.py文件中)
  • items.py    設置數據存儲模板,用於結構化數據,如:Django的Model
  • pipelines    數據處理行爲,如:通常結構化的數據持久化
  • settings.py 配置文件,如:遞歸的層數、併發數,延遲下載等
  • spiders      爬蟲目錄,如:建立文件,編寫爬蟲規則

 

2.建立爬蟲文件

在項目目錄下輸入:ajax

scrapy genspider 文件名 域名

 

更改以下設置:正則表達式

# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' \
             '(KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False
LOG_LEVEL = 'ERROR'

 scrapy默認遵照robotstxt,改成False,並把USER_AGENT改成瀏覽器,增長 LOG_LEVEL = 'ERROR',設置爲出錯時纔打印日誌文件。瀏覽器

 

3.運行

進入project_name目錄,運行命令cookie

scrapy crawl spider_name [--nolog]

--nolog 不顯示日誌 網絡

 

4.scrapy的持久化(示例)

爬取數據並進行持久化處理併發

items.py:框架

# 規範持久化的格式
import scrapy

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

 

爬蟲應用:

import scrapy
from  myspider.items import MyspiderItem


class ChoutiSpider(scrapy.Spider):
    name = 'chouti'
    allowed_domains = ['chouti.com']
    start_urls = ['https://dig.chouti.com/']

    def parse(self, response):
        # print(response.text)
        a_list = response.xpath('//div[@id="content-list"]//div[@class="part1"]/a[@class="show-content color-chag"]/@href').extract() # extract()將標籤中數據取出 for url in a_list:
            yield MyspiderItem(url=url)

yield每執行一次,process_item就調用yield Item對象。

此處代碼的關鍵在於:

  • 將獲取的數據封裝在了Item對象中
  • yield Item對象 (一旦parse中執行yield Item對象,則自動將該對象交個pipelines的類來處理)

 

使用scrapy解析文本內容時,可使用每一個應用中的response.xpath(xxx) 進行數據的解析。

print(response.xpath(...))  獲得的是一個Selector對象。selector對象能夠繼續xpath進行數據的解析。

xpath使用方法:
1.//+標籤  表示從全局的子子孫孫中查找標籤    
2./+標籤   表示從子代中查找標籤
3.查找帶有xxx屬性的標籤:   標籤+[@標籤屬性="值"]   
4.查找標籤的某個屬性:  /標籤/@屬性  
5.從當前標籤中查找時:.//+標籤     
response = HtmlResponse(url='http://example.com', body=html,encoding='utf-8')
hxs = HtmlXPathSelector(response)
print(hxs)   # selector對象
hxs = Selector(response=response).xpath('//a')
print(hxs)    #查找全部的a標籤
hxs = Selector(response=response).xpath('//a[2]')
print(hxs)    #查找某一個具體的a標籤    取第三個a標籤
hxs = Selector(response=response).xpath('//a[@id]')
print(hxs)    #查找全部含有id屬性的a標籤
hxs = Selector(response=response).xpath('//a[@id="i1"]')
print(hxs)    # 查找含有id=「i1」的a標籤
# hxs = Selector(response=response).xpath('//a[@href="link.html"][@id="i1"]')
# print(hxs)   # 查找含有href=‘xxx’而且id=‘xxx’的a標籤
# hxs = Selector(response=response).xpath('//a[contains(@href, "link")]')
# print(hxs)   # 查找 href屬性值中包含有‘link’的a標籤
# hxs = Selector(response=response).xpath('//a[starts-with(@href, "link")]')
# print(hxs)   # 查找 href屬性值以‘link’開始的a標籤
# hxs = Selector(response=response).xpath('//a[re:test(@id, "i\d+")]')
# print(hxs)   # 正則匹配的用法   匹配id屬性的值爲數字的a標籤
# hxs = Selector(response=response).xpath('//a[re:test(@id, "i\d+")]/text()').extract()
# print(hxs)    # 匹配id屬性的值爲數字的a標籤的文本內容
# hxs = Selector(response=response).xpath('//a[re:test(@id, "i\d+")]/@href').extract()
# print(hxs)    #匹配id屬性的值爲數字的a標籤的href屬性值
# hxs = Selector(response=response).xpath('/html/body/ul/li/a/@href').extract()
# print(hxs)
# hxs = Selector(response=response).xpath('//body/ul/li/a/@href').extract_first()
# print(hxs)
 
# ul_list = Selector(response=response).xpath('//body/ul/li')
# for item in ul_list:
#     v = item.xpath('./a/span')
#     # 或
#     # v = item.xpath('a/span')
#     # 或
#     # v = item.xpath('*/a/span')
#     print(v)

備註:xpath中支持正則的使用:

1.標籤+[re:test(@屬性值,"正則表達式")]

2.獲取標籤的文本內容:   /text()     

3.獲取第一個值須要  selector_obj.extract_first()    獲取全部的值  selector_obj.extract()  值在一個list中
 

pipelines.py:

class MyspiderPipeline(object):

    def __init__(self,file_path):
        self.f = None
        self.file_path = file_path

    @classmethod
    def from_crawler(cls,crawler):
        '''
        執行pipeline類時,會先去類中找from_crawler的方法,
        若是有,則先執行此方法,而且返回一個當前類的對象,
        若是沒有,則直接執行初始化方法
        :param crawler:
        :return:
        '''
        # 能夠進行一些初始化以前的處理,好比:文件的路徑配置到settings文件中,方便後期的更改。
        file_path = crawler.settings.get('PACHONG_FILE_PATH')
        return cls(file_path)

    def open_spider(self,spider):
        '''
        爬蟲開始時被調用
        :param spider:
        :return:
        '''
        self.f = open(self.file_path,'w',encoding='utf8')

    def process_item(self, item, spider):
        '''
        執行持久化的邏輯操做
        :param item: 爬蟲yield過來的item對象  (一個字典)
        :param spider:  爬蟲對象
        :return:
        '''
        self.f.write(item['url']+'\n')
        self.f.flush()   #將寫入到內存的文件強刷到文件中,防止夯住,不使用此方法會夯住
        return item

    def close_spider(self,spider):
        '''
        爬蟲結束時調用
        :param spider: 
        :return: 
        '''
        self.f.close()

 上述中的pipelines中能夠有多個類,定義各個類的優先級,要在settings.py中作以下配置:

ITEM_PIPELINES = {
    'xxx': 300,
    'xxx': 100,
}
# 每行後面的整型值,肯定了他們運行的順序,item按數字從低到高的順序,經過pipeline,一般將這些數字定義在0-1000範圍內。

 

獲取全部頁面:

import scrapy
from  myspider.items import MyspiderItem
from scrapy.http import Request

class ChoutiSpider(scrapy.Spider):
    name = 'chouti'
    allowed_domains = ['chouti.com']
    start_urls = ['https://dig.chouti.com/']

    def parse(self, response):
        a_list = response.xpath('//div[@id="content-list"]//div[@class="part1"]/a[@class="show-content color-chag"]/@href').extract()
        for url in a_list:
            yield MyspiderItem(url=url)

        # 獲取分頁的url
        url_list = response.xpath('//div[@id="dig_lcpage"]//a/@href').extract()
        for url in url_list:
            url = 'https://dig.chouti.com%s'%url
            yield Request(url=url,callback=self.parse)

以上代碼之因此能夠進行「遞歸」的訪問相關URL,關鍵在於parse方法使用了 yield Request對象。

注:能夠修改settings.py 中的配置文件,以此來指定「遞歸」的層數,如: DEPTH_LIMIT = 1 

 

在生成的每個爬蟲應用中,會有一個起始url,start_urls = ['https://dig.chouti.com/'],這個起始url執行完後會被parse回調函數接收響應結果。那咱們如何修改這個回調函數呢?
其實,在每個爬蟲應用繼承的父類中,會執行一個方法  start_requests ,這個方法,會將起始的url生成一個request對象,傳給調度器。
class Spider(object_ref):

        def start_requests(self):
        cls = self.__class__
        if method_is_overridden(cls, Spider, 'make_requests_from_url'):
            warnings.warn(
                "Spider.make_requests_from_url method is deprecated; it "
                "won't be called in future Scrapy releases. Please "
                "override Spider.start_requests method instead (see %s.%s)." % (
                    cls.__module__, cls.__name__
                ),
            )
            for url in self.start_urls:
                yield self.make_requests_from_url(url)
        else:
            for url in self.start_urls:
                yield Request(url, dont_filter=True)

 備註:在執行爬蟲應用時,會先執行start_requests方法,因此咱們能夠重寫此方法自定製。

 

5.請求傳參

使用請求傳參緣由:須要爬取的數據不在同一頁面

class MovieSpider(scrapy.Spider):
    name = 'movie'
    allowed_domains = ['www.id97.com']
    start_urls = ['http://www.id97.com/']

    def parse(self, response):
        div_list = response.xpath('//div[@class="col-xs-1-5 movie-item"]')

        for div in div_list:
            item = MovieproItem()
            item['name'] = div.xpath('.//h1/a/text()').extract_first()
            item['score'] = div.xpath('.//h1/em/text()').extract_first()
            #xpath(string(.))表示提取當前節點下全部子節點中的數據值(.)表示當前節點
            item['kind'] = div.xpath('.//div[@class="otherinfo"]').xpath('string(.)').extract_first()
            item['detail_url'] = div.xpath('./div/a/@href').extract_first()
            #請求二級詳情頁面,解析二級頁面中的相應內容,經過meta參數進行Request的數據傳遞
            yield scrapy.Request(url=item['detail_url'],callback=self.parse_detail,meta={'item':item})

    def parse_detail(self,response):
        #經過response獲取item
        item = response.meta['item']
        item['actor'] = response.xpath('//div[@class="row"]//table/tr[1]/a/text()').extract_first()
        item['time'] = response.xpath('//div[@class="row"]//table/tr[7]/td[2]/text()').extract_first()
        item['long'] = response.xpath('//div[@class="row"]//table/tr[8]/td[2]/text()').extract_first()
        #提交item到管道
        yield item

scrapy.Request函數經過meta參數把item傳遞給回調函數parse_detail,parse_detail能夠經過reponse.meta調用item,在該函數內完成對二級頁面的爬取,最後將item提交給管道。

 

6.中間件

下載中間件

下載器中間件是介於Scrapy的request/response處理的鉤子框架,是用於全局修改Scrapy request和response的一個輕量、底層的系統。

主要做用:

  • 在Scrapy將請求發送到網站以前修改,處理請求,如:更換代理ip,header等
  • 在將響應傳遞給引擎以前處理收到的響應,如:響應失敗從新請求,或將失敗的作必定處理再返回給引擎
  • 忽略一些響應或者請求

scrapy內置了一些默認配置,這些是不容許被修改的,一般是_BASE結尾的設置,好比DOWNLOADER_MIDDLEWARES_BASE下載中間件的默認設置,以下

{
    'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': 100,
    'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware': 300,
    'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware': 350,
    'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware': 400,
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': 500,
    'scrapy.downloadermiddlewares.retry.RetryMiddleware': 550,
    'scrapy.downloadermiddlewares.ajaxcrawl.AjaxCrawlMiddleware': 560,
    'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware': 580,
    'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 590,
    'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': 600,
    'scrapy.downloadermiddlewares.cookies.CookiesMiddleware': 700,
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 750,
    'scrapy.downloadermiddlewares.stats.DownloaderStats': 850,
    'scrapy.downloadermiddlewares.httpcache.HttpCacheMiddleware': 900,
}

scrapy就是按照上面數字從小到大依次執行的,好比執行完RobotsTxtMiddleware的process_request()方法後會繼續執行下面HttpAuthMiddleware等process_request(),能夠看做串聯的形式依次過流水線。

若是咱們要添加自定義的下載中間件,須要在settings.py中激活DOWNLOADER_MIDDLEWARES。同時想取消默認的一些中間件,也能夠設置爲None。注意的是激活DOWNLOADER_MIDDLEWARES並不會覆蓋DOWNLOADER_MIDDLEWARES_BASE,而是繼續串聯起來

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.CustomDownloaderMiddleware': 543,
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
}

自定義下載中間件

在建立項目後,再項目文件夾中有一middlewares.py文件,裏面自動生成了兩個中間件示例或者說模板。咱們若是要自定義中間件的話,能夠在給的示例上修改,或者新建類實現方法,或者繼承已有的中間件重寫方法

如下是下載中間件能夠實現的方法,在自定義中間件時,能夠根據需求實現

1.process_request(self, request, spider)

當每一個request經過下載中間件時,該方法被調用。process_request() 必須返回其中之一: 返回 None 、返回一個 Response 對象、返回一個 Request 對象或raise IgnoreRequest 。 最常使用的是返回None
  • 若是其返回 None ,會將處理事後的request丟給中間件鏈中的下一個中間件的process_request()方法處理,直到丟到下載器,由下載器下載
  • 若是其返回 Response 對象,Scrapy將不會調用任何其餘的 process_request() 或 process_exception() 方法,也不會丟到下載器下載;直接將其返回的response丟到中間件鏈的process_response()處理。能夠經過scrapy.http.Response構建Response 
  • 若是其返回 Request 對象,Scrapy則中止調用process_request方法並從新調度返回的request。當新返回的request被執行後, 相應地中間件鏈將會根據下載的response被調用。
  • 若是其raise一個 IgnoreRequest 異常,則安裝的下載中間件的 process_exception() 方法會被調用。若是沒有任何一個方法處理該異常, 則request的errback(Request.errback)方法會被調用。若是沒有代碼處理拋出的異常, 則該異常被忽略且不記錄(不一樣於其餘異常那樣)。
參數:
  request(Request 對象)–處理的request
  spider(Spider 對象)–該request對應的spider
 
2.process_response(self, request, response, spider)
 
當下載的response返回時,process_response()被調用,且 必須返回如下之一: 返回一個 Response 對象、 返回一個 Request 對象或raise一個 IgnoreRequest 異常。
  • 若是其返回一個 Response (能夠與傳入的response相同,也能夠是全新的對象), 該response會被在鏈中的其餘中間件的 process_response() 方法處理。
  • 若是其返回一個 Request 對象,則中間件鏈中止, 返回的request會被從新調度下載。處理相似於 process_request() 返回request所作的那樣。
  • 若是其拋出一個 IgnoreRequest 異常,則調用request的errback(Request.errback)。 若是沒有代碼處理拋出的異常,則該異常被忽略且不記錄(不一樣於其餘異常那樣)。
參數:
  request (Request 對象) – response所對應的request
  response (Response 對象) – 被處理的response
  spider (Spider 對象) – response所對應的spider
 
 
3.process_exception(self, request, exception, spider)
 
當下載處理器(download handler)或 process_request() (下載中間件)拋出異常(包括IgnoreRequest異常)時,Scrapy調用 process_exception() 。process_exception() 應該返回如下之一: 返回 None 、 一個 Response 對象、或者一個 Request 對象。
  • 若是其返回 None ,Scrapy將會繼續處理該異常,接着調用已安裝的其餘中間件的 process_exception() 方法,直到全部中間件都被調用完畢,則調用默認的異常處理。
  • 若是其返回一個 Response 對象,則已安裝的中間件鏈的 process_response() 方法被調用。Scrapy將不會調用任何其餘中間件的 process_exception() 方法。
  • 若是其返回一個 Request 對象, 則返回的request將會被從新調用下載。這將中止中間件的 process_exception() 方法執行,就如返回一個response的那樣。
參數:
  request (是 Request 對象) – 產生異常的request
  exception (Exception 對象) – 拋出的異常
  spider (Spider 對象) – request對應的spider
 
4.from_crawler(cls, crawler)
 
若是存在,則調用此類方法建立中間件實例Crawler。它必須返回一個新的中間件實例。Crawler對象提供對全部Scrapy核心組件的訪問,如設置和信號; 它是中間件訪問它們並將其功能掛鉤到Scrapy的一種方式。

參數:

  crawler(Crawlerobject)- 使用此中間件的爬網程序

 

設置隨機User-Agent的中間件:

user_agent_list = [
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 "
    "(KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
    "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 "
    "(KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 "
    "(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
    "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 "
    "(KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
    "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 "
    "(KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 "
    "(KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5"
]

class UserAgent_Middleware():

    def process_request(self, request, spider):
        ua = random.choice(user_agent_list)
        request.headers['User-Agent'] = ua

設置代理中間件

proxy_list=[
    "http://180.76.154.5:8888",
    "http://14.109.107.1:8998",
    "http://106.46.136.159:808",
    "http://175.155.24.107:808",
    "http://124.88.67.10:80",
    "http://124.88.67.14:80",
    "http://58.23.122.79:8118",
    "http://123.157.146.116:8123",
    "http://124.88.67.21:843",
    "http://106.46.136.226:808",
    "http://101.81.120.58:8118",
    "http://180.175.145.148:808"]
class proxy_Middleware(object):

    def process_request(self,request,spider):
        proxy = random.choice(proxy_list)
        request.meta['proxy'] = proxy

 

集成selenium的scrapy(selenium用於爬取動態加載的數據)

from selenium import webdriver
from scrapy.http import HtmlResponse
import time

class SeleniumMiddleware(object):
    def __init__(self):
        self.driver = webdriver.Chrome()

    def process_request(self, request, spider):
        self.driver.get(request.url)
        time.sleep(2)
        body = self.driver.page_source
        return HtmlResponse(self.driver.current_url,
                           body=body,
                           encoding='utf-8',
                           request=request)

最好是在爬蟲文件中建立瀏覽器對象,而後在中間件middlewares.py中經過spider.xxx調用瀏覽器對象,避免屢次建立。

 

spider中間件

spider中間件用於處理引擎傳回的response及spider生成的item和Request

主要做用:

  • 處理spider的異常
  • 對item在進入管道以前操做
  • 根據引擎傳入的響應,再進入回調函數前先處理

默認spider中間件

SPIDER_MIDDLEWARES_BASE

{
    'scrapy.spidermiddlewares.httperror.HttpErrorMiddleware': 50,
    'scrapy.spidermiddlewares.offsite.OffsiteMiddleware': 500,
    'scrapy.spidermiddlewares.referer.RefererMiddleware': 700,
    'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware': 800,
    'scrapy.spidermiddlewares.depth.DepthMiddleware': 900,
}

同理,激活中間件

SPIDER_MIDDLEWARES = {
    'myproject.middlewares.CustomSpiderMiddleware': 543,
    'scrapy.spidermiddlewares.offsite.OffsiteMiddleware': None,
}

自定義spider中間件

1.process_spider_input(self, response, spider)

對於經過spider中間件並進入spider的每一個響應,都會調用此方法進行處理。

process_spider_input()應該返回None或提出異常。

  • 若是它返回None,Scrapy將繼續處理此響應,執行全部其餘中間件,直到最後,響應被交給spider進行處理。
  • 若是它引起異常,Scrapy將不會調用任何其餘spider中間件的process_spider_input(),將調用請求errback(若是有的話),不然它將進入process_spider_exception()鏈

參數:
  response(Responseobject) - 正在處理的響應
  spider(Spiderobject) - 此響應所針對的spider

 

2.process_spider_output(self, response, result, spider)

在處理完響應以後,使用Spider返回的結果調用此方法。

process_spider_output()必須返回一個可迭代的 Request,dict或Item 對象。

參數:
  response(Responseobject) - 從spider生成此輸出的響應
  result(可迭代的Request,dict或Item對象) - spider返回的結果
  spider(Spiderobject) - 正在處理其結果的spider

 

3.process_spider_exception(self, response, exception, spider)

當spider或process_spider_output() 方法(來自先前的spider中間件)引起異常時,將調用此方法。

process_spider_exception()應該返回一個None或一個可迭代的Request,dict或 Item對象。

  • 若是它返回None,Scrapy將繼續處理此異常,執行process_spider_exception()如下中間件組件中的任何其餘組件,直到沒有剩餘中間件組件而且異常到達引擎(它被記錄並丟棄)。
  • 若是它返回一個iterable,那麼process_spider_output()管道將從下一個spider中間件開始啓動,而且不會process_spider_exception()調用其餘任何一個 。

參數:
  response(Responseobject) - 引起異常時正在處理的響應
  exception(異常對象) - 引起異常
  spider(Spiderobject) - 引起異常的spider

 

4.process_start_requests(self, start_requests, spider)

當spider運行到start_requests()的時候,爬蟲中間件的process_start_requests()方法被調用

它接收一個iterable(在start_requests參數中)而且必須返回另外一個可迭代的Request對象。

參數:
start_requests(可迭代Request) - 開始請求
spider(Spiderobject) - 啓動請求所屬的spider

 

5.from_crawler(cls, crawler)

這個類方法一般是訪問settings和signals的入口函數

 

spider中間件總結

1.spider開始start_requests()的時候,spider中間件的process_start_requests()方法被調用

2.下載response成功後,返回到spider 回調函數parse前,調用process_spider_input()

3.當spider yield scrapy.Request()或者yield item的時候,spider中間件的process_spider_output()方法被調用。

4.當spider出現了Exception的時候,spider中間件的process_spider_exception()方法被調用。

 

7.crawlspider

做用:全站數據爬取,處理不在同一頁面的數據

建立命令:

scrapy startproject xx
cd xx
scrapy genspider -t crawl xxx xxxx.com

屬性:

class ChoutiSpider(CrawlSpider):
    name = 'chouti'
    # allowed_domains = ['dig.chouti.com']
    start_urls = ['https://dig.chouti.com']
    # 連接提取器:從起始url對應的頁面中提取符合規則的連接,參數allow=正則表達式,提取符合該正則的連接
    link = LinkExtractor(allow=r'Items/')
    rules = (
        # 規則解析器:將連接提取器提取到的連接對應的頁面源碼進行指定規則(callback)的解析
        # follow=True 將連接提取器繼續做用到連接提取器提取到的連接對應的頁面源碼中(便可以提取到全部分頁)
        Rule(link, callback='parse_item', follow=True),
    )

 

 

8.總結

- scrapy使用流程    - 建立一個工程:scrapy startproject xxx    - cd xxx    - 建立爬蟲文件:scrapy genspider xxx www.xxx.com    - 執行:scrapy crawl xxx- 持久化存儲:    - 基於終端指令:scrapy crawl xxx -o file_path.csv        - 好處:便捷        - 弊端:侷限性強(只能夠寫入本地文件,文件類型有限制)    - 基於管道:        - 數據解析        - 在item類中聲明相關的屬性用於存儲解析到的數據        - 將解析到的數據存儲封裝到item類型的對象中        - 將item對象提交給管道        - item會被管道類中的process_item方法中的item參數進行接收        - 在process_item方法中編寫基於item持久化存儲的操做        - 在配置文件中開啓管道    - 管道細節處理        - 管道文件中的一個類表示的是將解析到的數據存儲到某一個具體的平臺中        - process_item的返回值(return item)就是將item傳遞給下一個即將被執行的管道類        - open_spider, close_spider的使用- 請求傳參    - 應用場景: 爬取得數據不在同一頁面    - 實現:scrapy.Request(url,callback,meta={'':''})           callback回調函數內經過response.meta['']調用傳遞的參數    - 中間件    - 批量攔截請求和響應    - 攔截請求:UA假裝(process_request), 代理IP(process_exception: return request)    - 攔截響應:process_response    - scrapy+selenium- crawlspider    做用:全站數據爬取    - spider的一個子類    - LinkExtractor:連接提取器:從起始url對應的頁面中提取符合規則的連接,參數allow=正則表達式,提取符合該正則的連接    - Rule:規則解析器:將連接提取器提取到的連接對應的頁面源碼進行指定規則(callback)的解析    - 一個連接提取器對用一個規則解析器
相關文章
相關標籤/搜索