當前位置: 妍妍網 > 辦公

從原理到實戰,一份詳實的 Scrapy 爬蟲教程

2024-03-04辦公

之前分享了很多 requests selenium 的 Python 爬蟲文章,本文將 從原理到實戰 帶領大家入門另一個強大的框架 Scrapy 如果對 Scrapy 感興趣的話,不妨跟隨本文動手做一遍!

一、Scrapy框架簡介

Scrapy 是:由 Python 語言開發的一個快速、高層次的螢幕抓取和web抓取框架,用於抓取web站點並從頁面中提取結構化的數據,只需要實作少量的程式碼,就能夠快速的抓取。

二、執行原理

Scrapy框架的執行原理看下面一張圖就夠了( 事實上原理是比較復雜的,也不是三言兩語能夠說清楚的,因此感興趣的讀者可以進一步閱讀更多的相關文章來了解,本文不做過多講解

Scrapy主要包括了以下元件:

  • 引擎(Scrapy Engine)

  • Item 計畫

  • 排程器(Scheduler)

  • 下載器(Downloader)

  • 爬蟲(Spiders)

  • 計畫管道(Pipeline)

  • 下載器中介軟體(Downloader Middlewares)

  • 爬蟲中介軟體(Spider Middlewares)

  • 排程中介軟體(Scheduler Middewares)

  • 三. 入門

    3.1安裝

    第一種:在命令列模式下使用pip命令即可安裝:

    $ pip install scrapy

    第二種:首先下載,然後再安裝:

    $ pip download scrapy -d ./
    # 透過指定國內映像源下載 
    $pip download -i https://pypi.tuna.tsinghua.edu.cn/simple scrapy -d ./

    進入下載目錄後執行下面命令安裝:

    $ pip install Scrapy-1.5.0-py2.py3-none-any.whl

    3.2使用

    使用大概分為下面四步 1 建立一個scrapy計畫

    scrapy startproject mySpider

    2 生成一個爬蟲

    scrapy genspider demo "demo.cn"

    3 提取數據

    完善spider 使用xpath等

    4 保存數據

    pipeline中保存數據

    3.3 程式執行

    在命令中執行爬蟲

    scrapy crawl qb # qb爬蟲的名字

    在pycharm中執行爬蟲

    from scrapy import cmdline
    cmdline.execute("scrapy crawl qb".split())

    四、基本步驟

    Scrapy 爬蟲框架的具體使用步驟如下:

    1. 選擇目標網站

    2. 定義要抓取的數據(透過Scrapy Items來完成的)

    3. 編寫提取數據的spider

    4. 執行spider,獲取數據

    5. 數據儲存

    五. 目錄檔說明

    當我們建立了一個scrapy計畫後,繼續建立了一個spider,目錄結構是這樣的:

    下面來簡單介紹一下各個主要檔的作用:

    scrapy.cfg :計畫的配置檔

    mySpider/ :計畫的Python模組,將會從這裏參照程式碼

    mySpider/items.py :計畫的目的檔

    mySpider/pipelines.py :計畫的管道檔

    mySpider/settings.py :計畫的設定檔

    mySpider/spiders/ :儲存爬蟲程式碼目錄

    5.1 scrapy.cfg檔

    計畫配置檔。這個是檔的內容:

    # Automatically created by: scrapy startproject
    #
    # For more information about the [deploy] p see:
    # https://scrapyd.readthedocs.io/en/latest/deploy.html
    [settings]
    default = mySpider.settings
    [deploy]
    #url = http://localhost:6800/
    project = mySpider

    5.2 mySpider**/**

    計畫的Python模組,將會從這裏參照程式碼

    5.3 mySpider/items.py

    計畫的目的檔

    # Define here the models for your scraped items
    #
    # See documentation in:
    # https://docs.scrapy.org/en/latest/topics/items.html
    import scrapy
    classMyspiderItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    pass

    定義scrapy items的模組,範例: name = scrapy.Field()

    5.4 mySpider/pipelines.py

    計畫的管道檔

    # Define your item pipelines here
    #
    # Don't forget to add your pipeline to the ITEM_PIPELINES setting
    # See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html

    # useful for handling different item types with a single interface
    from itemadapter import ItemAdapter

    classMyspiderPipeline:
    defprocess_item(self, item, spider):
    return item

    這個檔也就是我們說的管道,當Item在Spider中被收集之後,它將會被傳遞到Item Pipeline(管道),這些Item Pipeline元件按定義的順序處理Item。每個Item Pipeline都是實作了簡單方法的Python類,比如決定此Item是丟棄而儲存。以下是item pipeline的一些典型套用:

  • 驗證爬取的數據(檢查item包含某些欄位,比如說name欄位)

  • 查重(並丟棄)

  • 將爬取結果保存到檔或者資料庫中

  • 5.5 mySpider/settings.py

    計畫的設定檔

    # Scrapy settings for mySpider project
    ...
    BOT_NAME = 'mySpider'# scrapy計畫名
    SPIDER_MODULES = ['mySpider.spiders']
    NEWSPIDER_MODULE = 'mySpider.spiders'
    .......
    # Obey robots.txt rules
    ROBOTSTXT_OBEY = False# 是否遵守協定,一般給位false,但是建立完計畫是是True,我們把它改為False
    # Configure maximum concurrent requests performed by Scrapy (default: 16)
    #CONCURRENT_REQUESTS = 32 # 最大並行量 預設16
    ......
    #DOWNLOAD_DELAY = 3 # 下載延遲 3秒
    # 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',
    }
    # 爬蟲中介軟體
    #SPIDER_MIDDLEWARES = {
    # 'mySpider.middlewares.MyspiderSpiderMiddleware': 543,
    #}
    # 下載中介軟體
    #DOWNLOADER_MIDDLEWARES = {
    # 'mySpider.middlewares.MyspiderDownloaderMiddleware': 543,
    #}
    ......
    # Configure item pipelines
    # See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
    #ITEM_PIPELINES = {
    # 'mySpider.pipelines.MyspiderPipeline': 300, # 管道
    #}
    .......




    省略號省略程式碼,一般重要點,給了註釋

    6.mySpider/spiders/ :儲存爬蟲程式碼目錄

    import scrapy
    classDbSpider(scrapy.Spider):
    name = 'db'
    allowed_domains = ['douban.com'# 可以修改
    start_urls = ['http://douban.com/'# 開始的url也可以修改
    defparse(self, response):
    # pass

    六. Scrapy shell

    Scrapy終端是一個互動終端,我們可以在未啟動spider的情況下嘗試及偵錯程式碼,也可以用來測試XPath或CSS運算式,檢視他們的工作方式,方便我們爬取的網頁中提取的數據,但是一般使用的不多。感興趣的檢視官方文件:

    官方文件

    http://scrapy-chs.readthedocs.io/zh_CN/latest/topics/shell.html

    Scrapy Shell根據下載的頁面會自動建立一些方便使用的物件,例如 Response 物件,以及 Selector 物件 (對HTML及XML內容)

  • 當shell載入後,將得到一個包含response數據的本地 response 變量,輸入 response.body 將輸出response的包體,輸出 response.headers 可以看到response的包頭。

  • 輸入 response.selector 時, 將獲取到一個response 初始化的類 Selector 的物件,此時可以透過使用 response.selector.xpath() response.selector.css() 來對 response 進行查詢。

  • Scrapy也提供了一些捷徑, 例如 response.xpath() response.css() 同樣可以生效(如之前的案例)。

  • Selectors選擇器

    Scrapy Selectors 內建 XPath CSS Selector 運算式機制

    Selector有四個基本的方法,最常用的還是xpath:

  • xpath(): 傳入xpath運算式,返回該運算式所對應的所有節點的selector list列表

  • extract(): 序列化該節點為字串並返回list

  • css(): 傳入CSS運算式,返回該運算式所對應的所有節點的selector list列表,語法同 BeautifulSoup4

  • re(): 根據傳入的正規表式對數據進行提取,返回字串list列表

  • 七、案例實戰

    本節,我將使用Scrapy爬取站酷數據作為範例

    7.1 案例說明

    既然已經初步了解了scrapy的工作流程以及原理,我們來做一個入門的小案例,爬取站酷首頁推薦的item資訊。如下圖所示,一個小方框就是一個item資訊。我們要提取每一個item的六個組成部份:

    1. imgLink(封面圖片連結);

    2. title(標題);

    3. types(型別);

    4. vistor(人氣);

    5. comment(評論數);

    6. likes(推薦人數)

    然後只是一個頁面的item,我們還要透過翻頁實作批次數據采集。

    7.2 檔配置

    目錄結構

    在上一篇中我們說明了新建 scrapy計畫(zcool) spider計畫(zc) ,這裏不再贅述,然後得到我們的目錄結構如下圖所示:

    start.py檔

    然後為了方便執行,在zcool目錄下新建start檔。並進行初始化設定。

    from scrapy import cmdline
    cmdline.execute('scrapy crawl zc'.split())

    settings.py檔

    在這個檔裏我們需要做幾樣設定👇

    避免在程式執行的時候打印log日誌資訊

    LOG_LEVEL = 'WARNING'

     ROBOTSTXT_OBEY = False 

    添加請求頭:

    開啟管道:

    item.py檔

    import scrapy
    classZcoolItem(scrapy.Item):
    # define the fields for your item here like:
    imgLink = scrapy.Field() # 封面圖片連結
    title = scrapy.Field() # 標題
    types = scrapy.Field() # 型別
    vistor = scrapy.Field() # 人氣
    comment = scrapy.Field() # 評論數
    likes = scrapy.Field() # 推薦人數

    7.3 頁面數據提取

    首先我們在站酷頁面使用xpath-helper測試一下:

    然後zc.py檔裏面初步測試一下:

    defparse(self, response):
    divList = response.xpath('//div[@ class="work-list-box"]/div')
    print(len(divList))

    執行結果如下圖所示:

    沒有問題,然後我們對各種資訊分別解析提取,

    defparse(self, response):
    divList = response.xpath('//div[@ class="work-list-box"]/div')
    for div in divList:
    imgLink = div.xpath("./div[1]/a/img/@src").extract()[0# 1.封面圖片連結
    ... 2.title(標題);3 types(型別);4vistor(人氣);5comment(評論數) ....
    likes = div.xpath("./div[2]/p[3]/span[3]/@title").extract_first() # 6likes(推薦人數)
    item = ZcoolItem(imgLink=imgLink,title=title,types=types,vistor=vistor,comment=comment,likes=likes)
    yield item

    解釋: xpath提取數據方法:

    S.N. 方法 & 描述
    extract() 返回的是符合要求的所有的數據,存在一個列表裏。
    extract_first() 返回的hrefs 列表裏的第一個數據。
    get() 和extract_first()方法返回的是一樣的,都是列表裏的第一個數據。
    getall() 和extract()方法一樣,返回的都是符合要求的所有的數據,存在一個列表裏。

    註意:

    get() 、getall() 方法是新的方法,extract() 、extract_first()方法是舊的方法。extract() 、extract_first()方法取不到就返回None。get() 、getall() 方法取不到就raise一個錯誤。

    item例項建立(yield上面一行程式碼)

    這裏我們之前在目錄檔配置的item檔中已經進行了設定,對於數據儲存,我們在爬蟲檔中開頭要匯入這個類:

    from zcool.items import ZcoolItem

    然後使用yield返回數據。

    為什麽使用yield而不是return

    不能使用return這個無容置疑,因為要翻頁,使用return直接結束函式;而對於yield:在呼叫for的時候,函式內部不會立即執行,只是返回了一個生成器物件。在叠代的時候函式會開始執行,當在yield的時候,會返回當前值(i)。之後的這個函式會在迴圈中進行,直到沒有下一個值。

    7.4 翻頁實作批次數據采集

    透過上面的程式碼已經可以初步實作數據采集,只不過只有第一頁的,如下圖所示:

    但是我們的目標是100個頁面的批次數據采集,所以程式碼還需要修改。針對翻頁這裏介紹兩種方式:

    方式一 :我們首先在頁面中定位到下一頁的按鈕,如下圖所示:

    然後編寫如下程式碼,在for迴圈完畢後。

    next_href = response.xpath("//a[@ class='laypage_next']/@href").extract_first()
    if next_href:
    next_url = response.urljoin(next_href)
    print('*' * 60)
    print(next_url)
    print('*' * 60)
    request = scrapy.Request(next_url)
    yield request

    scrapy.Request(): 把下一頁的url傳遞給Request函式,進行翻頁迴圈數據采集。

    https://www.cnblogs.com/heymonkey/p/11818495.html # scrapy.Request()參考連結

    註意方式一只有下一頁按鈕它的 href 對應內容值和下一頁的url一致才行。

    方式二 :定義一個全域變量count = 0,每爬取一頁數據,令其加一,構建新的url,再使用scrapy.Request() 發起請求。

    如下圖所示:

    count = 1
    classZcSpider(scrapy.Spider):
    name = 'zc'
    allowed_domains = ['zcool.com.cn']
    start_urls = ['https://www.zcool.com.cn/home?p=1#tab_anchor'# 第一頁的url
    defparse(self, response):
    global count
    count += 1
    for div in divList:
    # ...xxx...
    yield item
    next_url = 'https://www.kuaikanmanhua.com/tag/0?state=1&sort=1&page={}'.format(count)
    yield scrapy.Request(next_url)


    這兩種方式在實際案例中擇機采用。

    7.5 數據儲存

    數據儲存是在pipline.py中進行的,程式碼如下:

    from itemadapter import ItemAdapter
    import csv
    classZcoolPipeline:
    def__init__(self):
    self.f = open('Zcool.csv','w',encoding='utf-8',newline='') # line1
    self.file_name = ['imgLink''title','types','vistor','comment','likes'] # line2
    self.writer = csv.DictWriter(self.f, fieldnames=self.file_name) # line3
    self.writer.writeheader() # line4
    defprocess_item(self, item, spider):
    self.writer.writerow(dict(item)) # line5
    print(item)
    return item # line6 
    defclose_spider(self,spider):
    self.f.close()

    解釋:

  • line1: 開啟檔,指定方式為寫,利用第3個參數把csv寫數據時產生的空行消除

  • line2: 設定檔第一行的欄位名,註意要跟spider傳過來的字典key名稱相同

  • line3: 指定檔的寫入方式為csv字典寫入,參數1為指定具體檔,參數2為指定欄位名

  • line4: 寫入第一行欄位名,因為只要寫入一次,所以檔放在__init__裏面

  • line5: 寫入spider傳過來的具體數值,註意在spider檔中yield的item,是一個由類建立的例項物件,我們寫入數據時,寫入的是 字典,所以這裏還要轉化一下。

  • line6: 寫入完返回

  • 7.6 程式執行

    因為之前建立了start.py檔,並且對它就行了初始化設定,現在執行爬蟲程式不需要在控制台中輸入命令:

    scrapy crawl zc(爬蟲計畫名)

    直執行start.py檔:得到如下結果:

    對應於頁面:

    開啟csv檔如下圖所示:(由於csv檔在word中亂碼了,此處我是用Notepad++開啟)

    沒有問題,數據采集完畢。

    7.7. 總結

    入門案例,需要細心,主要是基礎知識的鞏固,以便於為進階學習做好準備。


    作者: 飲馬長江

    來源 :早起Python

    Crossin的新書【 碼上行動:用ChatGPT學會Python編程 】已經上市了。 本書以ChatGPT為輔助,系統全面地講解了如何掌握Python編程,適合Python零基礎入門的讀者學習。

    購買後可加入讀者交流群,Crossin為你開啟陪讀模式,解答你在閱讀本書時的一切疑問。

    Crossin的其他書籍:

    添加微信 crossin123 ,加入編程教室共同學習 ~

    感謝 轉發 點贊 的各位~