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


1. 架構

引擎(Scrapy):用來處理整個系統的數據流處理, 觸發事務(框架核心)
調度器(Scheduler):用來接受引擎發過來的請求, 壓入隊列中, 並在引擎再次請求的時候返回. 可以想像成一個URL(抓取網頁的網址或者說是鏈接)的優先隊列, 由它來決定下一個要抓取的網址是什么, 同時去除重復的網址
下載器(Downloader):用於下載網頁內容, 並將網頁內容返回給蜘蛛(Scrapy下載器是建立在twisted這個高效的異步模型上的)
爬蟲(Spiders):爬蟲是主要干活的, 用於從特定的網頁中提取自己需要的信息, 即所謂的實體(Item)。用戶也可以從中提取出鏈接,讓Scrapy繼續抓取下一個頁面
項目管道(Pipeline):負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證實體的有效性、清除不需要的信息。當頁面被爬蟲解析后,將被發送到項目管道,並經過幾個特定的次序處理數據。
下載器中間件(Downloader Middlewares):位於Scrapy引擎和下載器之間的框架,主要是處理Scrapy引擎與下載器之間的請求及響應。
爬蟲中間件(Spider Middlewares):介於Scrapy引擎和爬蟲之間的框架,主要工作是處理蜘蛛的響應輸入和請求輸出。
調度中間件(Scheduler Middewares):介於Scrapy引擎和調度之間的中間件,從Scrapy引擎發送到調度的請求和響應。

2. 數據流

Scrapy 中的數據流由引擎控制:

(I) Engine首先打開一個網站,找到處理該網站的 Spider,並向該 Spider請求第一個要爬取的 URL。

(2)Engine從 Spider中獲取到第一個要爬取的 URL,並通過 Scheduler以Request的形式調度。
(3) Engine 向 Scheduler請求下一個要爬取的 URL。
(4) Scheduler返回下一個要爬取的 URL給 Engine, Engine將 URL通過 DownloaderMiddJewares轉發給 Downloader下載。

(5)一旦頁面下載完畢, Downloader生成該頁面的 Response,並將其通過 DownloaderMiddlewares發送給 Engine。

(6) Engine從下載器中接收到lResponse,並將其通過 SpiderMiddlewares發送給 Spider處理。

(7) Spider處理 Response,並返回爬取到的 Item及新的 Request給 Engine。
(8) Engine將 Spider返回的 Item 給 Item Pipeline,將新 的 Request給 Scheduler。

(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 關閉時,該方法會被調用,在這里-般會定義釋放資源的一些操作或其 他收尾操作 。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM