Scrapy開發指南

1、Scrapy簡介 

Scrapy是一個爲了爬取網站數據,提取結構性數據而編寫的應用框架。 能夠應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。css

Scrapy基於事件驅動網絡框架 Twisted 編寫。所以,Scrapy基於併發性考慮由非阻塞(即異步)的實現。

組件

Scrapy Engine

引擎負責控制數據流。html

調度器(Scheduler)

調度器從引擎接受request並將他們入隊,以便以後引擎請求他們時提供給引擎。python

下載器(Downloader)

下載器負責獲取頁面數據並提供給引擎,然後提供給spider。正則表達式

Spiders

Spider是Scrapy用戶編寫用於分析response並提取item(即獲取到的item)或額外跟進的URL的類。 每一個spider負責處理一個特定(或一些)網站。數據庫

Item Pipeline

Item Pipeline負責處理被spider提取出來的item。典型的處理有清理、 驗證及持久化(例如存取到數據庫中)。api

下載器中間件(Downloader middlewares)

下載器中間件是在引擎及下載器之間的特定鉤子(specific hook),處理Downloader傳遞給引擎的response。 其提供了一個簡便的機制,經過插入自定義代碼來擴展Scrapy功能。網絡

Spider中間件(Spider middlewares)

Spider中間件是在引擎及Spider之間的特定鉤子(specific hook),處理spider的輸入(response)和輸出(items及requests)。 其提供了一個簡便的機制,經過插入自定義代碼來擴展Scrapy功能。併發

2、Scrapy環境配置

安裝如下程序框架

  • Python 2.7
  • Python Package: pip and setuptools. 如今 pip 依賴 setuptools ,若是未安裝,則會自動安裝setuptools 。
  • lxml. 大多數Linux發行版自帶了lxml。若是缺失,請查看http://lxml.de/installation.html
  • OpenSSL. 除了Windows(請查看 平臺安裝指南)以外的系統都已經提供。 
    pip install pyopenssl
  • Visual C++2008
  • 安裝PyWin32
  • pip install scrapy

建立工程模板dom

命令行執行:scrapy startproject 工程名

建立好的工程結構以下圖:

  

Idea中配置scrapy啓動

 

2、經常使用API說明

開發中主要涉及spider,item,Pipeline,settings模塊的開發。須要擴展插件則開發extions模塊。

Spider類

繼承scrapy.Spider

屬性

name : 爬蟲名字,用於區別spider,惟一。
start_urls : Spider在啓動時進行爬取的url列表。後續的URL則從初始的URL獲取到的數據中提取。

方法
parse(self, response) :每一個初始url爬取到的數據將經過response參數傳遞過來。此方法負責解析數據(response), 提取數據(生成Item),生成須要進一步處理的URL請求(request)。

scrapy.Request(url=link, errback=self.errback_http, callback=self.parse_article)

框架會對url=link的地址發起請求,若是請求出現錯誤執行用戶自定義的errback_http方法,若是請求成功則執行用戶自定義的parse_article方法。

Item類

須要繼承scrapy.Item。Item是一個dict(),用於存儲spider中parse()中解析到的數據,在pipeline中調用。

import scrapy

class DmozItem(scrapy.Item):
    title = scrapy.Field()
    link = scrapy.Field()
    desc = scrapy.Field()
提取Item

Scrapy Selector基於xpath和css提取元素。

  • xpath(): 傳入xpath表達式,返回該表達式所對應的全部節點的selector list列表 。
  • css(): 傳入CSS表達式,返回該表達式所對應的全部節點的selector list列表.
  • extract(): 序列化該節點爲unicode字符串並返回list。
  • re(): 根據傳入的正則表達式對數據進行提取,返回unicode字符串list列表。

運行爬蟲
在項目目錄下運行如下命令,便可執行爬蟲:
scrapy crawl NAME(爬蟲名字)

配置文件Settings

Settings文件能夠能夠控制包括核心(core),插件(extension),pipeline及spider組件。這裏只說3.settings模塊。

  1. 命令行選項(Command line Options)(最高優先級)
  2. 每一個spider的設定
  3. 項目設定模塊(Project settings module)
  4. 命令默認設定模塊(Default settings per-command)
  5. 全局默認設定(Default global settings) (最低優先級)

訪問settings

若是須要使用該配置文件中定義的屬性,類(爬蟲,管道,插件)須要增長額外的類方法: from_crawler(cls, crawler)。

設定能夠經過Crawler的 scrapy.crawler.Crawler.settings 屬性進行訪問。其由插件及中間件的from_crawler 方法所傳入:

class MyExtension(object):

    @classmethod
    def from_crawler(cls, crawler):
        settings = crawler.settings
        if settings['LOG_ENABLED']:
            print "log is enabled!"

也能夠經過字典訪問,避免錯誤,建議使用setting API中的規範key值。

管道開發

管道相似過濾處理鏈,根據自定義業務依次處理Spider解析後的數據,例如數據驗證(去重、轉換),計算存儲(DB,NOSQL),發送消息(Kafka,MQ),報表生成。
開發自定義管道類須要兩步驟:

  1. 在pipelines中定義類並實現 process_item(self, item, spider) 方法, 其中item對象爲spider解析後待處理的數據。
  2. 在settings中開啓管道配置信息,ITEM_PIPELINES 中配置自定義管道類名和執行序列。

說明
自定義管道根據序列號從小到大依次執行請求,若是拋出DropItem異常,後續管道將不會執行,例如數據出現重複主鍵,能夠拋出DropItem異常。

日誌開發

使用如下代碼在管道中定義日誌名稱

logger = logging.getLogger('pipelogger')

同時能夠在包初始化文件__init__.py中定義日誌級別 : LOG_LEVEL = 'INFO'

日誌啓用也能夠在settings中設置以下屬性
LOG_ENABLED = True #啓用日誌
LOG_ENCODING = 'utf-8' #設置日誌字符集
LOG_FILE = 'e://workspace/log/csdncrawl.log' #指定日誌文件及路徑
LOG_LEVEL = 'INFO' #定義日誌級別
LOG_STDOUT = True #是否將print語句打印內容輸出到日誌

擴展插件

開發者可自定義運行在不一樣階段的插件,例如打開爬蟲、關閉爬蟲、數據抓取等。
插件只須要關注:在何時作什麼事情,即 狀態-方法。
開發插件只須要2步:

  1. 開發插件類,可定義在extensions.py文件中,在from_crawler中增長狀態-方法的映射關係,例如在打開爬蟲的時候執行spider_opened方法可這樣配置:
    crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened)
  1. 在settings中配置插件類,和管道定義相似, 其KEY爲EXTENSIONS

 

4、代碼示例

Spider示例

import scrapy

class DmozSpider(scrapy.Spider):
    name = "dmoz"
    allowed_domains = ["dmoz.org"]
    start_urls = [
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
    ]

    def parse(self, response):
        for sel in response.xpath('//ul/li'):
            title = sel.xpath('a/text()').extract()
            link = sel.xpath('a/@href').extract()
            desc = sel.xpath('text()').extract()
            print title, link, desc

 

日誌Logging

import logginglogger = logging.getLogger('mycustomlogger')
logger.warning("This is a warning") import logging import scrapy logger = logging.getLogger('mycustomlogger') class MySpider(scrapy.Spider): name = 'myspider' start_urls = ['http://scrapinghub.com'] def parse(self, response): logger.info('Parse function called on %s', response.url)

 參考資料: 

中文版scrapy資料地址:https://scrapy-chs.readthedocs.io/zh_CN/1.0/intro/tutorial.html 

相關文章
相關標籤/搜索