《python3網絡爬蟲開發實戰》--Scrapy

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 關閉時,該方法會被調用,在這裏-般會定義釋放資源的一些操做或其 他收尾操做 。
相關文章
相關標籤/搜索