1. 程式人生 > 其它 >Scrapy入門到放棄03:理解settings配置,監控Scrapy引擎

Scrapy入門到放棄03:理解settings配置,監控Scrapy引擎

程式碼未動、配置先行。

前言

程式碼未動,配置先行。本篇文章主要講述一下Scrapy中的配置檔案settings.py的引數含義,以及如何去獲取一個爬蟲程式的執行效能指標。

這篇文章無聊的一匹,沒有程式碼,都是配置化的東西,但是呢不學還不行,屬於Scrapy的樞紐,很關鍵。所以還請各位看官老爺耐得住這一章的寂寞。

settings.py

在我們建立一個Scrapy專案的時候,就會在專案下生成四個py檔案,其中就有一個settings.py。其中大大小小配置也是有大幾十個,這裡只講一些比較常見的,其他的還請移步官方文件。

官文配置引數說明url:
https://docs.scrapy.org/en/latest/topics/settings.html

常見引數

下面也羅列了小几十個配置,大部分都其實使用預設值即可,最值得我們關注的,就是下面幾個:

  1. DOWNLOAD_DELAY
  2. CONCURRENT_REQUESTS
  3. CONCURRENT_REQUESTS_PER_DOMAIN
  4. CONCURRENT_REQUESTS_PER_IP
  5. SPIDER_MIDDLEWARES
  6. DOWNLOADER_MIDDLEWARES
  7. ITEM_PIPELINES

那麼,為什麼說Settings是Scrapy的樞紐?

還記得我上篇文章畫的架構圖嗎?還記得之前說過Scrapy的四大模組嗎?每個模組在專案初始化時都是獨立的,各個模組只有在Settings配置之後,請求、響應、資料才會在模組間流轉。這一部分對應上面提到的配置5、6、7。

配置具體說明,詳看下文:

# Scrapy settings for ScrapyDemo project

# 自動生成的配置,無需關注,不用修改
BOT_NAME = 'ScrapyDemo'
SPIDER_MODULES = ['ScrapyDemo.spiders']
NEWSPIDER_MODULE = 'ScrapyDemo.spiders'

# 設定UA,但不常用,一般都是在MiddleWare中新增
USER_AGENT = 'ScrapyDemo (+http://www.yourdomain.com)'

# 遵循robots.txt中的爬蟲規則,很多人喜歡False,當然我也喜歡....
ROBOTSTXT_OBEY = True

# 對網站併發請求總數,預設16
CONCURRENT_REQUESTS = 32

# 相同網站兩個請求之間的間隔時間,預設是0s。相當於time.sleep()
DOWNLOAD_DELAY = 3
# 下面兩個配置二選一,但其值不能大於CONCURRENT_REQUESTS,預設啟用PER_DOMAIN
# 對網站每個域名的最大併發請求,預設8
CONCURRENT_REQUESTS_PER_DOMAIN = 16
# 預設0,對網站每個IP的最大併發請求,會覆蓋上面PER_DOMAIN配置,
# 同時DOWNLOAD_DELAY也成了相同IP兩個請求間的間隔了
CONCURRENT_REQUESTS_PER_IP = 16

# 禁用cookie,預設是True,啟用
COOKIES_ENABLED = False

# 請求頭設定,這裡基本上不用
DEFAULT_REQUEST_HEADERS = {
#   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
#   'Accept-Language': 'en',
#}

# 配置啟用Spider MiddleWares,Key是class,Value是優先順序
SPIDER_MIDDLEWARES = {
    'ScrapyDemo.middlewares.ScrapydemoSpiderMiddleware': 543,
}

# 配置啟用Downloader MiddleWares

DOWNLOADER_MIDDLEWARES = {
    'ScrapyDemo.middlewares.ScrapydemoDownloaderMiddleware': 543,
}

# 配置並啟用擴充套件,主要是一些狀態監控
EXTENSIONS = {
    'scrapy.extensions.telnet.TelnetConsole': None,
}

# 配置啟用Pipeline用來持久化資料
ITEM_PIPELINES = {
   'ScrapyDemo.pipelines.ScrapydemoPipeline': 300,
}

# 禁止控制檯使用telnet連線scrapy獲取狀態,預設是啟用。我們使用預設值即可
TELNETCONSOLE_ENABLED = False
# Telnet終端使用的埠範圍。預設: [6023, 6073],如果設定為 None 或 0 , 則使用動態分配的埠
# TELNETCONSOLE_PORT

# telnet賬號,預設:scrapy
TELNETCONSOLE_USERNAME = None

# telnet密碼:預設會自動生成一個密碼
TELNETCONSOLE_PASSWORD

# Telnet終端監聽的介面(interface)。預設: '127.0.0.1'
TELNETCONSOLE_HOST = '127.0.0.1'


# AutoThrottle是限速節流演算法
# 讓爬蟲程式自適應download_delay和concurrent併發
AUTOTHROTTLE_ENABLED = True
# 爬蟲程式啟動時,開始對網站發起請求的延遲
AUTOTHROTTLE_START_DELAY = 5
# 請求到響應的最大允許的延遲時間,必須大於download_delay
AUTOTHROTTLE_MAX_DELAY = 60
# 並行傳送到每個遠端伺服器的平均請求數,小於CONCURRENT_REQUESTS_PER_DOMAIN和CONCURRENT_REQUESTS_PER_IP
AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
# 為每個響應啟用顯示限制統計資訊
AUTOTHROTTLE_DEBUG = False

# HttpCache主要是將每次的請求和響應快取到本地,可以離線進行處理
# 配置啟用HTTP Cache,預設不啟用
HTTPCACHE_ENABLED = True
# 快取的過期時間,0為永不過期
HTTPCACHE_EXPIRATION_SECS = 0
# 快取目錄名稱
HTTPCACHE_DIR = 'httpcache'
# 設定不需要快取的狀態碼請求
HTTPCACHE_IGNORE_HTTP_CODES = []
# 此類將快取儲存到本地檔案系統,還可以使用其他類儲存到資料庫
HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'

像上面的Telnet配置使用預設即可,一般AutoThrottle限速演算法和Http Cache用的也少,當然還有一些log日誌、retry請求重試功能,這裡就不一一列舉了。

區域性配置定義

settings.py中的配置,屬於全域性配置,是專案中所有爬蟲共享的。改了一個,其他的爬蟲也會受影響。

所以很多時候我們都會在爬蟲程式內,定義字典型別的custom_settings成員變數,來實現區域性配置。

    custom_settings = {
        'DOWNLOAD_DELAY': 10
    }

這樣DOWNLOAD_DELAY為10這個配置,只在當前程式中生效。

那這區域性配置在什麼時候用的多?

我用的最多的地方,就是使用Scrapy-Splash外掛的時候,因為要發起的是SplashRequest,而不是之前的Request,所以要進行單獨的配置。為了不改變全域性配置、影響其他爬蟲,通常在程式內定義這些配置。

這個後面Scrapy-Splash外掛會講。

啟動時配置

我們在啟動爬蟲時,可以使用-s來指定配置。

scrapy crawl [spiderName] -s DOWNLOAD_DELAY=10

程式中獲取配置

我們通常也將資料庫的使用者、密碼、ip等資訊配置在settings中,然後通過crawler物件來獲取。該物件提供對所有Scrapy核心元件的訪問,可以debug看一下。

如圖,可以通過crawler訪問到settings配置、engine引擎、訊號量signals、狀態stat等。這裡我們先只關注settings。

這裡寫一段程式碼,驗證區域性配置、啟動時配置、以及配置三個功能。

import scrapy

class DouLuoDaLuSpider(scrapy.Spider):
    name = 'DouLuoDaLu'
    allowed_domains = ['v.qq.com']
    start_urls = ['https://v.qq.com/detail/m/m441e3rjq9kwpsc.html']
    # 自定義配置
    custom_settings = {
        'DOWNLOAD_DELAY': 10
    }

    def parse(self, response):
        # 獲取配置
        delay = self.crawler.settings.get('DOWNLOAD_DELAY')
        print(delay)

DOWNLOAD_DELAY在全域性配置中我修改為3,如果沒有在程式中定義custom_settings,則輸出為3。

當我們定義custom_settings之後,啟動程式,輸出如下:

這裡輸出的就是10,是程式內的配置,覆蓋了全域性配置。當我們使用以下命令在啟動爬蟲時指定延遲為11。

scrapy crawl DouLuoDaLu -s DOWNLOAD_DELAY=11


則輸出為11,覆蓋了程式內變數。所以,我們也得出一個結論,同一配置的優先順序為:

啟動時配置 > 程式內配置 > 全域性配置

引擎狀態監控

關於引擎的定義:

Scrapy engine which controls the Scheduler, Downloader and Spiders

引擎狀態是指現在排程器中有多少請求排隊、下載器中有多少個請求正在下載、有多少響應在被處理等等,而監控是通過telnet來實現。

我的Scrapy中全域性配置都是預設的,為了直觀,我這裡都使用區域性配置。這裡我發起100 * 10次請求,模擬一個一直執行的爬蟲,程式碼如下:

import scrapy
from scrapy import Request

class DouLuoDaLuSpider(scrapy.Spider):
    name = 'DouLuoDaLu'
    allowed_domains = ['v.qq.com']
    start_urls = ['https://v.qq.com/detail/m/m441e3rjq9kwpsc.html']

    custom_settings = {
        'DOWNLOAD_DELAY': 6,
        'CONCURRENT_REQUESTS': 32,
        'CONCURRENT_REQUESTS_PER_DOMAIN': 8,
        # 賬號預設就是scrapy
        # 'TELNETCONSOLE_USERNAME' = 'scrapy'
        'TELNETCONSOLE_PASSWORD': 'scrapy'
    }

    def start_requests(self):
        for i in range(0, 100):
            yield Request(url=self.start_urls[0], callback=self.parse, dont_filter=True)

    def parse(self, response):
        for i in range(0, 10):
            yield Request(url=self.start_urls[0], callback=self.parse, dont_filter=True)

啟動爬蟲之後,使用以下命令進入telnet。

# telnet終端監聽埠配置為*TELNETCONSOLE_PORT*,預設為6023。
telnet localhost 6023

輸入賬號和密碼:

進入互動頁面,輸入est(),輸出引擎狀態指標。

主要監控一下五個指標:

  1. engine.downloader.active:下載器中等待下載的請求,對應最大併發數。設定中為32,這裡也是32,說明下載器已經滿了,其他請求進不來了。
  2. engine.slot.scheduler.mqs:記憶體排程佇列。進不去下載器的請求就只能在排程器中等待了,這裡有28個請求在等待。
  3. engine.slot.scheduler.dqs:磁碟排程佇列,可以設定,將請求放於磁碟之中。
  4. engine.scraper.slot.active:正在被處理的響應數量
  5. engine.scraper.slot.itemproc_size:pipeline處理的Item數量

同時也可以在互動命令中暫停、恢復、停止引擎。

engine.pause()
engine.unpause()
engine.stop()

當引擎被暫停或停止,下載器處理完佇列中的請求之後,便處於空閒狀態。

結語

本篇文章主要講了一些基本的配置和Telnet引擎監控,主要目的還是為了將Scrapy架構掰扯清楚,後面用的時候才能瞭然於胸。

後面的文章接著寫其他模組,下一篇講MiddleWare中介軟體,下下篇就是Pipeline,下下下篇打算寫一個完整的樣例,將各個模組整合起來。期待下一次相遇。



95後小程式設計師,寫的都是日常工作中的親身實踐,置身於初學者的角度從0寫到1,詳細且認真。文章會在公眾號 [入門到放棄之路] 首發,期待你的關注。