Scrapy是一個爲了爬取網站數據,提取結構性數據而編寫的應用框架。 能夠應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。css
引擎負責控制數據流。html
調度器從引擎接受request並將他們入隊,以便以後引擎請求他們時提供給引擎。python
下載器負責獲取頁面數據並提供給引擎,然後提供給spider。正則表達式
Spider是Scrapy用戶編寫用於分析response並提取item(即獲取到的item)或額外跟進的URL的類。 每一個spider負責處理一個特定(或一些)網站。數據庫
Item Pipeline負責處理被spider提取出來的item。典型的處理有清理、 驗證及持久化(例如存取到數據庫中)。api
下載器中間件是在引擎及下載器之間的特定鉤子(specific hook),處理Downloader傳遞給引擎的response。 其提供了一個簡便的機制,經過插入自定義代碼來擴展Scrapy功能。網絡
Spider中間件是在引擎及Spider之間的特定鉤子(specific hook),處理spider的輸入(response)和輸出(items及requests)。 其提供了一個簡便的機制,經過插入自定義代碼來擴展Scrapy功能。併發
安裝如下程序框架
pip install pyopenssl
建立工程模板dom
命令行執行:scrapy startproject 工程名
建立好的工程結構以下圖:
Idea中配置scrapy啓動
開發中主要涉及spider,item,Pipeline,settings模塊的開發。須要擴展插件則開發extions模塊。
繼承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方法。
須要繼承scrapy.Item。Item是一個dict(),用於存儲spider中parse()中解析到的數據,在pipeline中調用。
import scrapy class DmozItem(scrapy.Item): title = scrapy.Field() link = scrapy.Field() desc = scrapy.Field()
Scrapy Selector基於xpath和css提取元素。
xpath()
: 傳入xpath表達式,返回該表達式所對應的全部節點的selector list列表 。css()
: 傳入CSS表達式,返回該表達式所對應的全部節點的selector list列表.extract()
: 序列化該節點爲unicode字符串並返回list。re()
: 根據傳入的正則表達式對數據進行提取,返回unicode字符串list列表。運行爬蟲
在項目目錄下運行如下命令,便可執行爬蟲:
scrapy crawl NAME(爬蟲名字)
Settings文件能夠能夠控制包括核心(core),插件(extension),pipeline及spider組件。這裏只說3.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),報表生成。
開發自定義管道類須要兩步驟:
說明
自定義管道根據序列號從小到大依次執行請求,若是拋出DropItem異常,後續管道將不會執行,例如數據出現重複主鍵,能夠拋出DropItem異常。
使用如下代碼在管道中定義日誌名稱
logger = logging.getLogger('pipelogger')
日誌啓用也能夠在settings中設置以下屬性
LOG_ENABLED = True #啓用日誌
LOG_ENCODING = 'utf-8' #設置日誌字符集
LOG_FILE = 'e://workspace/log/csdncrawl.log' #指定日誌文件及路徑
LOG_LEVEL = 'INFO' #定義日誌級別
LOG_STDOUT = True #是否將print語句打印內容輸出到日誌
開發者可自定義運行在不一樣階段的插件,例如打開爬蟲、關閉爬蟲、數據抓取等。
插件只須要關注:在何時作什麼事情,即 狀態-方法。
開發插件只須要2步:
crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened)
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