學python,怎麼能不學習scrapy呢!

語言: CN / TW / HK
摘要:本文講述如何編寫scrapy爬蟲。

本文分享自華為雲社群《學python,怎麼能不學習scrapy呢,這篇部落格帶你學會它》,作者: 夢想橡皮擦 。

在正式編寫爬蟲案例前,先對 scrapy 進行一下系統的學習。

scrapy 安裝與簡單執行

使用命令 pip install scrapy 進行安裝,成功之後,還需要隨手收藏幾個網址,以便於後續學習使用。

  • scrapy 官網:https://scrapy.org;
  • scrapy 文件:https://doc.scrapy.org/en/latest/intro/tutorial.html;
  • scrapy 更新日誌:https://docs.scrapy.org/en/latest/news.html。

安裝完畢之後,在控制檯直接輸入 scrapy,出現如下命令表示安裝成功。

> scrapy
Scrapy 2.5.0 - no active project
Usage:
 scrapy <command> [options] [args]
Available commands:

上述截圖是 scrapy 的內建命令列表,標準的格式的 scrapy <command> <options> <args>,通過 scrapy <command> -h 可以檢視指定命令的幫助手冊。

scrapy 中提供兩種型別的命令,一種是全域性的,一種的專案中的,後者需要進入到 scrapy 目錄才可執行。

這些命令無需一開始就完全記住,隨時可查,有幾個比較常用,例如:

**scrpy startproject <專案名> **

該命令先依據 專案名 建立一個資料夾,然後再資料夾下創建於個 scrpy 專案,這一步是後續所有程式碼的起點。

> scrapy startproject my_scrapy
> New Scrapy project 'my_scrapy', using template directory 'e:\pythonproject\venv\lib\site-packages\scrapy\templates\project', created in:  # 一個新的 scrapy 專案被建立了,使用的模板是 XXX,建立的位置是 XXX
    E:\pythonProject\滾雪球學Python第4輪\my_scrapy
You can start your first spider with:  # 開啟你的第一個爬蟲程式
 cd my_scrapy # 進入資料夾
 scrapy genspider example example.com # 使用專案命令建立爬蟲檔案

上述內容增加了一些註釋,可以比對著進行學習,預設生成的檔案在 python 執行時目錄,如果想修改專案目錄,請使用如下格式命令:

scrapy startproject myproject [project_dir]

例如

scrapy startproject myproject d:/d1

命令依據模板創建出來的專案結構如下所示,其中紅色下劃線的是專案目錄,而綠色下劃線才是 scrapy 專案,如果想要執行專案命令,則必須先進入紅色下劃線 my_scrapy 資料夾,在專案目錄中才能控制專案。

下面生成一個爬蟲檔案

使用命令 scrapy genspider [-t template] <name> <domain> 生成爬蟲檔案,該方式是一種快捷操作,也可以完全手動建立。建立的爬蟲檔案會出現在 當前目錄或者專案資料夾中的 spiders 資料夾中,name 是爬蟲名字,domain 用在爬蟲檔案中的 alowed_domains 和 start_urls 資料中,[-t template] 表示可以選擇生成檔案模板。

檢視所有模板使用如下命令,預設模板是 basic。

> scrapy genspider -l
  basic
  crawl
 csvfeed
 xmlfeed

建立第一個 scrapy 爬蟲檔案,測試命令如下:

>scrapy genspider pm imspm.com
Created spider 'pm' using template 'basic' in module:
  my_project.spiders.pm

此時在 spiders 資料夾中,出現 pm.py 檔案,該檔案內容如下所示:

import scrapy
class PmSpider(scrapy.Spider):
    name = 'pm'
 allowed_domains = ['imspm.com']
 start_urls = ['http://imspm.com/']
 def parse(self, response):
 pass

測試 scrapy 爬蟲執行

使用命令 scrapy crawl <spider>,spider 是上文生成的爬蟲檔名,出現如下內容,表示爬蟲正確載入。

>scrapy crawl pm
2021-10-02 21:34:34 [scrapy.utils.log] INFO: Scrapy 2.5.0 started (bot: my_project)
[...]

scrapy 基本應用

scrapy 工作流程非常簡單:

  1. 採集第一頁網頁原始碼;
  2. 解析第一頁原始碼,並獲取下一頁連結;
  3. 請求下一頁網頁原始碼;
  4. 解析原始碼,並獲取下一頁原始碼;
  5. […]
  6. 過程當中,提取到目標資料之後,就進行儲存。

接下來為大家演示 scrapy 一個完整的案例應用,作為 爬蟲 120 例 scrapy 部分的第一例。

> scrapy startproject my_project 爬蟲
> cd 爬蟲
> scrapy genspider pm imspm.com

獲得專案結構如下:

上圖中一些檔案的簡單說明。

  • scrapy.cfg:配置檔案路徑與部署配置;
  • items.py:目標資料的結構;
  • middlewares.py:中介軟體檔案;
  • pipelines.py:管道檔案;
  • settings.py:配置資訊。

使用 scrapy crawl pm 執行爬蟲之後,所有輸出內容與說明如下所示:

上述程式碼請求次數為 7 次,原因是在 pm.py 檔案中預設沒有新增 www,如果增加該內容之後,請求次數變為 4。

現在的 pm.py 檔案程式碼如下所示:

import scrapy
class PmSpider(scrapy.Spider):
    name = 'pm'
 allowed_domains = ['www.imspm.com']
 start_urls = ['http://www.imspm.com/']
 def parse(self, response):
 print(response.text)

其中的 parse 表示請求 start_urls 中的地址,獲取響應之後的回撥函式,直接通過引數 response 的 .text 屬性進行網頁原始碼的輸出。

獲取到原始碼之後,要對原始碼進行解析與儲存

在儲存之前,需要手動定義一個數據結構,該內容在 items.py 檔案實現,對程式碼中的類名進行了修改,MyProjectItem → ArticleItem。

import scrapy
class ArticleItem(scrapy.Item):
 # define the fields for your item here like:
 # name = scrapy.Field()
    title = scrapy.Field() # 文章標題
 url = scrapy.Field() # 文章地址
    author = scrapy.Field() # 作者

修改 pm.py 檔案中的 parse 函式,增加網頁解析相關操作,該操作類似 pyquery 知識點,直接觀察程式碼即可掌握。

 def parse(self, response):
 # print(response.text)
 list_item = response.css('.list-item-default')
 # print(list_item)
 for item in list_item:
            title = item.css('.title::text').extract_first() # 直接獲取文字
 url = item.css('.a_block::attr(href)').extract_first() # 獲取屬性值
            author = item.css('.author::text').extract_first() # 直接獲取文字
 print(title, url, author)

其中 response.css 方法返回的是一個選擇器列表,可以迭代該列表,然後對其中的物件呼叫 css 方法。

  • item.css('.title::text'),獲取標籤內文字;
  • item.css('.a_block::attr(href)'),獲取標籤屬性值;
  • extract_first():解析列表第一項;
  • extract():獲取列表。

在 pm.py 中匯入 items.py 中的 ArticleItem 類,然後按照下述程式碼進行修改:

 def parse(self, response):
 # print(response.text)
 list_item = response.css('.list-item-default')
 # print(list_item)
 for i in list_item:
            item = ArticleItem()
            title = i.css('.title::text').extract_first() # 直接獲取文字
 url = i.css('.a_block::attr(href)').extract_first() # 獲取屬性值
            author = i.css('.author::text').extract_first() # 直接獲取文字
 # print(title, url, author)
 # 對 item 進行賦值
            item['title'] = title
            item['url'] = url
            item['author'] = author
 yield item

此時在執行 scrapy 爬蟲,就會出現如下提示資訊。

此時完成了一個單頁爬蟲

接下來對 parse 函式再次改造,使其在解析完第 1 頁之後,可以解析第 2 頁資料。

 def parse(self, response):
 # print(response.text)
 list_item = response.css('.list-item-default')
 # print(list_item)
 for i in list_item:
            item = ArticleItem()
            title = i.css('.title::text').extract_first() # 直接獲取文字
 url = i.css('.a_block::attr(href)').extract_first() # 獲取屬性值
            author = i.css('.author::text').extract_first() # 直接獲取文字
 # print(title, url, author)
 # 對 item 進行賦值
            item['title'] = title
            item['url'] = url
            item['author'] = author
 yield item
 next = response.css('.nav a:nth-last-child(2)::attr(href)').extract_first() # 獲取下一頁連結
 # print(next)
 # 再次生成一個請求
 yield scrapy.Request(url=next, callback=self.parse)

上述程式碼中,變數 next 表示下一頁地址,通過 response.css 函式獲取連結,其中的 css 選擇器請重點學習。
yield scrapy.Request(url=next, callback=self.parse) 表示再次建立一個請求,並且該請求的回撥函式是 parse 本身,程式碼執行效果如下所示。

如果想要儲存執行結果,執行下面的命令即可。

scrapy crawl pm -o pm.json

如果想要將每條資料儲存為單獨一行,使用如下命令即可 scrapy crawl pm -o pm.jl 。

生成的檔案還支援 csv 、 xml、marchal、pickle ,可自行嘗試。

下面將資料管道利用起來

開啟 pipelines.py 檔案,修改類名 MyProjectPipeline → TitlePipeline,然後編入如下程式碼:

class TitlePipeline:
 def process_item(self, item, spider): # 移除標題中的空格
 if item["title"]:
            item["title"] = item["title"].strip()
 return item
 else:
 return DropItem("異常資料")

該程式碼用於移除標題中的左右空格。

編寫完畢,需要在 settings.py 檔案中開啟 ITEM_PIPELINES 配置。

ITEM_PIPELINES = {
 'my_project.pipelines.TitlePipeline': 300,
}

300 是 PIPELINES 執行的優先順序順序,根據需要修改即可。再次執行爬蟲程式碼,會發現標題的左右空格已經被移除。

到此 scrapy 的一個基本爬蟲已經編寫完畢。

 

點選關注,第一時間瞭解華為雲新鮮技術~