1. 架構css
引擎(Scrapy):用來處理整個系統的數據流處理, 觸發事務(框架核心)
調度器(Scheduler):用來接受引擎發過來的請求, 壓入隊列中, 並在引擎再次請求的時候返回. 能夠想像成一個URL(抓取網頁的網址或者說是連接)的優先隊列, 由它來決定下一個要抓取的網址是什麼, 同時去除重複的網址
下載器(Downloader):用於下載網頁內容, 並將網頁內容返回給蜘蛛(Scrapy下載器是創建在twisted這個高效的異步模型上的)
爬蟲(Spiders):爬蟲是主要幹活的, 用於從特定的網頁中提取本身須要的信息, 即所謂的實體(Item)。用戶也能夠從中提取出連接,讓Scrapy繼續抓取下一個頁面
項目管道(Pipeline):負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證明體的有效性、清除不須要的信息。當頁面被爬蟲解析後,將被髮送到項目管道,並通過幾個特定的次序處理數據。
下載器中間件(Downloader Middlewares):位於Scrapy引擎和下載器之間的框架,主要是處理Scrapy引擎與下載器之間的請求及響應。
爬蟲中間件(Spider Middlewares):介於Scrapy引擎和爬蟲之間的框架,主要工做是處理蜘蛛的響應輸入和請求輸出。
調度中間件(Scheduler Middewares):介於Scrapy引擎和調度之間的中間件,從Scrapy引擎發送到調度的請求和響應。html
2. 數據流web
Scrapy 中的數據流由引擎控制:數據庫
(I) Engine首先打開一個網站,找處處理該網站的 Spider,並向該 Spider請求第一個要爬取的 URL。json
(2)Engine從 Spider中獲取到第一個要爬取的 URL,並經過 Scheduler以Request的形式調度。
(3) Engine 向 Scheduler請求下一個要爬取的 URL。
(4) Scheduler返回下一個要爬取的 URL給 Engine, Engine將 URL經過 DownloaderMiddJewares轉發給 Downloader下載。cookie
(5)一旦頁面下載完畢, Downloader生成該頁面的 Response,並將其經過 DownloaderMiddlewares發送給 Engine。網絡
(6) Engine從下載器中接收到lResponse,並將其經過 SpiderMiddlewares發送給 Spider處理。架構
(7) Spider處理 Response,並返回爬取到的 Item及新的 Request給 Engine。
(8) Engine將 Spider返回的 Item 給 Item Pipeline,將新 的 Request給 Scheduler。app
(9)重複第(2)步到第(8)步,直到 Scheduler中沒有更多的 Request, Engine關閉該網站,爬取結束。框架
經過多個組件的相互協做、不一樣組件完成工做的不一樣、組件對異步處理的支持 , Scrapy最大限度 地利用了網絡帶寬,大大提升了數據爬取和處理的效率 。
2. 實戰
建立項目
scrapy startproject tutorial
建立Spider
cd tutorial
scrapy genspider quotes quotes.toscrape.com
建立Item
Item是保存爬取數據的容器,它的使用方法和字典相似。 不過,相比字典,Item多了額外的保護機制,能夠避免拼寫錯誤或者定義字段錯誤 。
建立 Item 須要繼承 scrapy.Item類,而且定義類型爲 scrapy.Field 的字段 。 觀察目標網站,咱們能夠獲取到到內容有 text、 author、 tags。
使用Item
items.py
1 import scrapy 2 3 4 class TutorialItem(scrapy.Item): 5 # define the fields for your item here like: 6 # name = scrapy.Field() 7 text = scrapy.Field() 8 author = scrapy.Field() 9 tags = scrapy.Field()
quotes.py
1 # -*- coding: utf-8 -*- 2 import scrapy 3 4 from tutorial.items import TutorialItem 5 6 7 class QuotesSpider(scrapy.Spider): 8 name = "quotes" 9 allowed_domains = ["quotes.toscrape.com"] 10 start_urls = ['http://quotes.toscrape.com/'] 11 12 def parse(self, response): 13 quotes = response.css('.quote') 14 for quote in quotes: 15 item = TutorialItem() 16 item['text'] = quote.css('.text::text').extract_first() 17 item['author'] = quote.css('.author::text').extract_first() 18 item['tags'] = quote.css('.tags .tag::text').extract() 19 yield item 20 21 next = response.css('.pager .next a::attr(href)').extract_first() 22 url = response.urljoin(next) 23 yield scrapy.Request(url=url, callback=self.parse)
scrapy crawl quotes -o quotes.json scrapy crawl quotes -o quotes .csv scrapy crawl quotes -o quotes.xml scrapy crawl quotes -o quotes.pickle scrapy crawl quotes -o quotes.marshal scrapy crawl quotes -o ftp://user:pass@ftp.example.com/path/to/quotes.csv
3. 使用Item Pipeline
Item Pipeline爲項目管道 。 當 Item生成後,它會自動被送到 ItemPipeline進行處理,咱們經常使用 ItemPipeline來作以下操做 。
清理 HTML數據。
驗證爬取數據,檢查爬取字段。
查重井丟棄重複內容。
將爬取結果保存到數據庫。
定義一個類並實現 process_item()方法便可。啓用 ItemPipeline後,Item Pipeline會自動調用這個方法。 process_item()方法必須返回包含數據的字典或 Item對象,或者拋出 Dropltem異常。
process_item()方法有兩個參數。 一個參數是 item,每次 Spider生成的 Item都會做爲參數傳遞過來。 另外一個參數是 spider,就是 Spider的實例。
修改項目裏面的pipelines.py
# -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html from scrapy.exceptions import DropItem import pymongo class TextPipeline(object): def __init__(self): self.limit = 50 def process_item(self, item, spider): if item['text']: if len(item['text']) > self.limit: item['text'] = item['text'][0:self.limit].rstrip() + '...' return item else: return DropItem('Missing Text') class MongoPipeline(object): def __init__(self, mongo_uri, mongo_db): self.mongo_uri = mongo_uri self.mongo_db = mongo_db @classmethod def from_crawler(cls, crawler): return cls( mongo_uri=crawler.settings.get('MONGO_URI'), mongo_db=crawler.settings.get('MONGO_DB') ) def open_spider(self, spider): self.client = pymongo.MongoClient(self.mongo_uri) self.db = self.client[self.mongo_db] def process_item(self, item, spider): name = item.__class__.__name__ self.db[name].insert(dict(item)) return item def close_spider(self, spider): self.client.close()
seetings.py
# -*- coding: utf-8 -*- # Scrapy settings for tutorial project # # For simplicity, this file contains only settings considered important or # commonly used. You can find more settings consulting the documentation: # # https://doc.scrapy.org/en/latest/topics/settings.html # https://doc.scrapy.org/en/latest/topics/downloader-middleware.html # https://doc.scrapy.org/en/latest/topics/spider-middleware.html BOT_NAME = 'tutorial' SPIDER_MODULES = ['tutorial.spiders'] NEWSPIDER_MODULE = 'tutorial.spiders' # Crawl responsibly by identifying yourself (and your website) on the user-agent #USER_AGENT = 'tutorial (+http://www.yourdomain.com)' # Obey robots.txt rules ROBOTSTXT_OBEY = True # Configure maximum concurrent requests performed by Scrapy (default: 16) #CONCURRENT_REQUESTS = 32 # Configure a delay for requests for the same website (default: 0) # See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay # See also autothrottle settings and docs #DOWNLOAD_DELAY = 3 # The download delay setting will honor only one of: #CONCURRENT_REQUESTS_PER_DOMAIN = 16 #CONCURRENT_REQUESTS_PER_IP = 16 # Disable cookies (enabled by default) #COOKIES_ENABLED = False # Disable Telnet Console (enabled by default) #TELNETCONSOLE_ENABLED = False # Override the default request headers: #DEFAULT_REQUEST_HEADERS = { # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', # 'Accept-Language': 'en', #} # Enable or disable spider middlewares # See https://doc.scrapy.org/en/latest/topics/spider-middleware.html #SPIDER_MIDDLEWARES = { # 'tutorial.middlewares.TutorialSpiderMiddleware': 543, #} # Enable or disable downloader middlewares # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html #DOWNLOADER_MIDDLEWARES = { # 'tutorial.middlewares.TutorialDownloaderMiddleware': 543, #} # Enable or disable extensions # See https://doc.scrapy.org/en/latest/topics/extensions.html #EXTENSIONS = { # 'scrapy.extensions.telnet.TelnetConsole': None, #} # Configure item pipelines # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html ITEM_PIPELINES = { 'tutorial.pipelines.TextPipeline': 300, 'tutorial.pipelines.MongoPipeline': 400, } # Enable and configure the AutoThrottle extension (disabled by default) # See https://doc.scrapy.org/en/latest/topics/autothrottle.html #AUTOTHROTTLE_ENABLED = True # The initial download delay #AUTOTHROTTLE_START_DELAY = 5 # The maximum download delay to be set in case of high latencies #AUTOTHROTTLE_MAX_DELAY = 60 # The average number of requests Scrapy should be sending in parallel to # each remote server #AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0 # Enable showing throttling stats for every response received: #AUTOTHROTTLE_DEBUG = False # Enable and configure HTTP caching (disabled by default) # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings #HTTPCACHE_ENABLED = True #HTTPCACHE_EXPIRATION_SECS = 0 #HTTPCACHE_DIR = 'httpcache' #HTTPCACHE_IGNORE_HTTP_CODES = [] #HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage' MONGO_URI='localhost' MONGO_DB='tutorial'
4. Selector的用法
Selector是一個能夠獨立使用的模塊。咱們能夠直接利用 Selector這個類來構建一個選擇器對象,而後調用它的相關方法如 xpath()、 css()等來提取數據。
5.XPath選擇器
response 有一個屬性 selector,咱們調用 response.selector 返回的內容就至關於用 response 的body構造了一個 Selector對象。 經過這個 Selector對象咱們能夠調用解析方法如 xpath()、 css()等,經過向方法傳入 XPath或 css選擇器參數就能夠實現信息的提取。
6.CSS選擇器
7.正則匹配
8.spider的用法
spider的運行流程:
口 定義爬取網站的動做;
口 分析爬取下來的網頁。
對於 Spider類來講,整個爬取循環過程以下所述。
口 以初始的 URL初始化 Request,並設置回調函數。 當該 Request成功請求並返回時, Response生成井做爲參數傳給該回調函數 。
口 在回調函數內分析返回的網頁內容 。 返回結果有兩種形式 。 一種是解析到的有效結果返回 字典或 Item對象,它們能夠通過處理後(或直接)保存。 另外一種是解析獲得下一個(以下一頁)連接,能夠 利用此連接構造 Request並設置新的回調函數,返回 Request等待後續調度 。
口 若是返回的是字典或 Item 對象,咱們可經過 Feed Exports 等組件將退回結果存入到文件 。 若是設置了 Pipeline的話,咱們可使用 Pipeline處理 (如過濾、修正等)並保存。
口 若是返回的是 Reqeust,那麼 Request 執行成功獲得 Response 以後, Response 會被傳遞給Request 中定義的回調函數,在回調函數中咱們能夠再次使用選擇器來分析新獲得的網頁內 容,並根據分析的數據生成 Item。
spider類分析:
1 口 name。 爬蟲名稱,是定義 Spider名字的字符串。 Spider的名字定義了 Scrapy如何定位並初始 化 Spider,它必須是惟 一 的 。 不過咱們能夠生成多個相同的 Spider 實例,數量沒有限制 。 name是 Spider最重要的屬性。 若是 Spider~取單個網站, 一個常見的作法是以該網站的域名 名稱來命名 Spider。 例如, SpiderJI\巳取 mywebsite.com , 該 Spider一般會被命名爲 mywebsite。 2 口 allowed_domains。 容許爬取的域名,是可選配置,不在此範圍的連接不會被跟進爬取。 3 口 start_urls。 它是起始 URL 列表,當咱們沒有實現 start_requests()方法時,默認會從這個 4 列表開始抓取 。 5 口 custom_settings。 它是一個字典,是專屬於本 Spider 的配置,此設置會覆蓋項目全局的設 6 置。 此設置必須在初始化前被更新,必須定義成類變量。 7 口 crawler。 它是由 from_crawler()方法設置的,表明的是本 Spider 類對應的 Crawler 對象 。 8 Crawler對象包含了不少項目組件,利用它咱們能夠獲取項目的一些配置信息,如最多見的獲 9 取項目的設置信息,即 Settings。 10 0 settings。 它是一個 Settings對象,利用它咱們能夠直接獲取項目的全局設置變量 。 11 除了基礎屬性, Spider還有 一些經常使用的方法 。 12 口 start_requests()。 此方法用於生成初始請求,它必須返回 一個可迭代對象 。 此方法會默認 使用 start_urls裏面的 URL來構造 Request,並且 Request是 GET請求方式。 若是咱們想在啓 動時以 POST方式訪問某個站點,能夠直接重寫這個方法,發送 POST請求時使用 FormRequest 便可。 13 口 parse()。 當 Response沒有指定回調函數時,該方法會默認被調用 。 它負責處理 Response, 處 理返回結果,並從巾提取Hi想要的數據和下一步的請求,而後返回。 該方法須要返回一個包 含 Request或 ltem的可迭代對象。 14 口 closed()。 當 Spider 關閉時,該方法會被調用,在這裏-般會定義釋放資源的一些操做或其 他收尾操做 。