當前位置:
首頁 > 知識 > Scrapy 入門教程

Scrapy 入門教程

Scrapy 是用 Python 實現的一個為了爬取網站數據、提取結構性數據而編寫的應用框架。

Scrapy 常應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。

通常我們可以很簡單的通過 Scrapy 框架實現一個爬蟲,抓取指定網站的內容或圖片。



Scrapy架構圖(綠線是數據流向)

Scrapy 入門教程

打開今日頭條,查看更多精彩圖片

  • Scrapy Engine(引擎)

    : 負責Spider、ItemPipeline、Downloader、Scheduler中間的通訊,信號、數據傳遞等。
  • Scheduler(調度器)

    : 它負責接受引擎發送過來的Request請求,並按照一定的方式進行整理排列,入隊,當引擎需要時,交還給引擎。
  • Downloader(下載器)

    :負責下載Scrapy Engine(引擎)發送的所有Requests請求,並將其獲取到的Responses交還給Scrapy Engine(引擎),由引擎交給Spider來處理,
  • Spider(爬蟲)

    :它負責處理所有Responses,從中分析提取數據,獲取Item欄位需要的數據,並將需要跟進的URL提交給引擎,再次進入Scheduler(調度器).
  • Item Pipeline(管道)

    :它負責處理Spider中獲取到的Item,並進行進行後期處理(詳細分析、過濾、存儲等)的地方。
  • Downloader Middlewares(下載中間件)

    :你可以當作是一個可以自定義擴展下載功能的組件。
  • Spider Middlewares(Spider中間件)

    :你可以理解為是一個可以自定擴展和操作引擎和Spider中間通信的功能組件(比如進入Spider的Responses;和從Spider出去的Requests)

Scrapy的運作流程

代碼寫好,程序開始運行...

  • 1 引擎:Hi!Spider, 你要處理哪一個網站?
  • 2 Spider:老大要我處理xxxx.com。
  • 3 引擎:你把第一個需要處理的URL給我吧。
  • 4 Spider:給你,第一個URL是xxxxxxx.com。
  • 5 引擎:Hi!調度器,我這有request請求你幫我排序入隊一下。
  • 6 調度器:好的,正在處理你等一下。
  • 7 引擎:Hi!調度器,把你處理好的request請求給我。
  • 8 調度器:給你,這是我處理好的request
  • 9 引擎:Hi!下載器,你按照老大的下載中間件的設置幫我下載一下這個request請求
  • 10 下載器:好的!給你,這是下載好的東西。(如果失敗:sorry,這個request下載失敗了。然後引擎告訴調度器,這個request下載失敗了,你記錄一下,我們待會兒再下載)
  • 11 引擎:Hi!Spider,這是下載好的東西,並且已經按照老大的下載中間件處理過了,你自己處理一下(注意!這兒responses默認是交給def parse()這個函數處理的)
  • 12 Spider:(處理完畢數據之後對於需要跟進的URL),Hi!引擎,我這裡有兩個結果,這個是我需要跟進的URL,還有這個是我獲取到的Item數據。
  • 13 引擎:Hi !管道 我這兒有個item你幫我處理一下!調度器!這是需要跟進URL你幫我處理下。然後從第四步開始循環,直到獲取完老大需要全部信息。
  • 14 管道調度器:好的,現在就做!

注意!只有當調度器中不存在任何request了,整個程序才會停止,(也就是說,對於下載失敗的URL,Scrapy也會重新下載。)


製作 Scrapy 爬蟲 一共需要4步:

  1. 新建項目 (scrapy startproject xxx):新建一個新的爬蟲項目
  2. 明確目標 (編寫items.py):明確你想要抓取的目標
  3. 製作爬蟲 (spiders/xxspider.py):製作爬蟲開始爬取網頁
  4. 存儲內容 (pipelines.py):設計管道存儲爬取內容

安裝

Windows 安裝方式

升級 pip 版本:

pip install --upgrade pip

通過 pip 安裝 Scrapy 框架:

pip install Scrapy

Ubuntu 安裝方式

安裝非 Python 的依賴:

sudo apt-get install python-dev python-pip libxml2-dev libxslt1-dev zlib1g-dev libffi-dev libssl-dev

通過 pip 安裝 Scrapy 框架:

sudo pip install scrapy

Mac OS 安裝方式

對於Mac OS系統來說,由於系統本身會引用自帶的python2.x的庫,因此默認安裝的包是不能被刪除的,但是你用python2.x來安裝Scrapy會報錯,用python3.x來安裝也是報錯,我最終沒有找到直接安裝Scrapy的方法,所以我用另一種安裝方式來說一下安裝步驟,解決的方式是就是使用virtualenv來安裝。

$ sudo pip install virtualenv
$ virtualenv scrapyenv
$ cd scrapyenv
$ source bin/activate
$ pip install Scrapy

安裝後,只要在命令終端輸入 scrapy,提示類似以下結果,代表已經安裝成功。

Scrapy 入門教程



入門案例

學習目標

  • 創建一個Scrapy項目
  • 定義提取的結構化數據(Item)
  • 編寫爬取網站的 Spider 並提取出結構化數據(Item)
  • 編寫 Item Pipelines 來存儲提取到的Item(即結構化數據)

一. 新建項目(scrapy startproject)

在開始爬取之前,必須創建一個新的Scrapy項目。進入自定義的項目目錄中,運行下列命令:

scrapy startproject mySpider

其中, mySpider 為項目名稱,可以看到將會創建一個 mySpider 文件夾,目錄結構大致如下:

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

mySpider/
scrapy.cfg
mySpider/
__init__.py
items.py
pipelines.py
settings.py
spiders/
__init__.py
...

這些文件分別是:

  • scrapy.cfg: 項目的配置文件。
  • mySpider/: 項目的Python模塊,將會從這裡引用代碼。
  • mySpider/items.py: 項目的目標文件。
  • mySpider/pipelines.py: 項目的管道文件。
  • mySpider/settings.py: 項目的設置文件。
  • mySpider/spiders/: 存儲爬蟲代碼目錄。

二、明確目標(mySpider/items.py)

我們打算抓取 http://www.itcast.cn/channel/teacher.shtml 網站里的所有講師的姓名、職稱和個人信息。

  1. 打開 mySpider 目錄下的 items.py。
  2. Item 定義結構化數據欄位,用來保存爬取到的數據,有點像 Python 中的 dict,但是提供了一些額外的保護減少錯誤。
  3. 可以通過創建一個 scrapy.Item 類, 並且定義類型為 scrapy.Field 的類屬性來定義一個 Item(可以理解成類似於 ORM 的映射關係)。
  4. 接下來,創建一個 ItcastItem 類,和構建 item 模型(model)。

import scrapy
class ItcastItem(scrapy.Item):
name = scrapy.Field()
title = scrapy.Field()
info = scrapy.Field()

三、製作爬蟲 (spiders/itcastSpider.py)

爬蟲功能要分兩步:

1. 爬數據

在當前目錄下輸入命令,將在mySpider/spider目錄下創建一個名為itcast的爬蟲,並指定爬取域的範圍:

scrapy genspider itcast "itcast.cn"

打開 mySpider/spider目錄里的 itcast.py,默認增加了下列代碼:

import scrapy
class ItcastSpider(scrapy.Spider):
name = "itcast"
allowed_domains = ["itcast.cn"]
start_urls = (
"http://www.itcast.cn/",
)
def parse(self, response):
pass

其實也可以由我們自行創建itcast.py並編寫上面的代碼,只不過使用命令可以免去編寫固定代碼的麻煩

要建立一個Spider, 你必須用scrapy.Spider類創建一個子類,並確定了三個強制的屬性 和 一個方法。

name = "" :這個爬蟲的識別名稱,必須是唯一的,在不同的爬蟲必須定義不同的名字。

allow_domains = [] 是搜索的域名範圍,也就是爬蟲的約束區域,規定爬蟲只爬取這個域名下的網頁,不存在的URL會被忽略。

start_urls = () :爬取的URL元祖/列表。爬蟲從這裡開始抓取數據,所以,第一次下載的數據將會從這些urls開始。其他子URL將會從這些起始URL中繼承性生成。

parse(self, response) :解析的方法,每個初始URL完成下載後將被調用,調用的時候傳入從每一個URL傳回的Response對象來作為唯一參數,主要作用如下:

負責解析返回的網頁數據(response.body),提取結構化數據(生成item)

生成需要下一頁的URL請求。

將start_urls的值修改為需要爬取的第一個url

start_urls = ("http://www.itcast.cn/channel/teacher.shtml",)

修改parse()方法

def parse(self, response):
filename = "teacher.html"
open(filename, "w").write(response.body)

然後運行一下看看,在mySpider目錄下執行:

scrapy crawl itcast

是的,就是 itcast,看上面代碼,它是 ItcastSpider 類的 name 屬性,也就是使用 scrapy genspider命令的唯一爬蟲名。

運行之後,如果列印的日誌出現 [scrapy] INFO: Spider closed (finished),代表執行完成。 之後當前文件夾中就出現了一個 teacher.html 文件,裡面就是我們剛剛要爬取的網頁的全部源代碼信息。

注意:Python2.x默認編碼環境是ASCII,當和取回的數據編碼格式不一致時,可能會造成亂碼;我們可以指定保存內容的編碼格式,一般情況下,我們可以在代碼最上方添加

import sys
reload(sys)
sys.setdefaultencoding("utf-8")

這三行代碼是 Python2.x 里解決中文編碼的萬能鑰匙,經過這麼多年的吐槽後 Python3 學乖了,默認編碼是Unicode了...(祝大家早日擁抱Python3)

2. 取數據

爬取整個網頁完畢,接下來的就是的取過程了,首先觀察頁面源碼:

<div class="li_txt">
<h3> xxx </h3>
<h4> xxxxx </h4>
<p> xxxxxxxx </p>

是不是一目了然?直接上 XPath 開始提取數據吧。

xpath 方法,我們只需要輸入的 xpath 規則就可以定位到相應 html 標籤節點,詳細內容可以查看 xpath 教程。

不會 xpath 語法沒關係,Chrome 給我們提供了一鍵獲取 xpath 地址的方法(右鍵->檢查->copy->copy xpath),如下圖:

Scrapy 入門教程

這裡給出一些 XPath 表達式的例子及對應的含義:

  • /html/head/title: 選擇HTML文檔中 <head> 標籤內的 <title> 元素
  • /html/head/title/text(): 選擇上面提到的 <title> 元素的文字
  • //td: 選擇所有的 <td> 元素
  • //div[@class="mine"]: 選擇所有具有 class="mine" 屬性的 div 元素

舉例我們讀取網站 http://www.itcast.cn/ 的網站標題,修改 itcast.py 文件代碼如下::

# -*- coding: utf-8 -*-
import scrapy
# 以下三行是在 Python2.x版本中解決亂碼問題,Python3.x 版本的可以去掉
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
class Opp2Spider(scrapy.Spider):
name = "itcast"
allowed_domains = ["itcast.com"]
start_urls = ["http://www.itcast.cn/"]
def parse(self, response):
# 獲取網站標題
context = response.xpath("/html/head/title/text()")

# 提取網站標題
title = context.extract_first()
print(title)
pass

執行以下命令:

$ scrapy crawl itcast
...
...
傳智播客官網-好口碑IT培訓機構,一樣的教育,不一樣的品質
...
...

我們之前在 mySpider/items.py 里定義了一個 ItcastItem 類。 這裡引入進來:

from mySpider.items import ItcastItem

然後將我們得到的數據封裝到一個 ItcastItem 對象中,可以保存每個老師的屬性:

from mySpider.items import ItcastItem
def parse(self, response):
#open("teacher.html","wb").write(response.body).close()
# 存放老師信息的集合
items = []
for each in response.xpath("//div[@class="li_txt"]"):
# 將我們得到的數據封裝到一個 `ItcastItem` 對象
item = ItcastItem()
#extract()方法返回的都是unicode字元串
name = each.xpath("h3/text()").extract()
title = each.xpath("h4/text()").extract()
info = each.xpath("p/text()").extract()
#xpath返回的是包含一個元素的列表
item["name"] = name[0]
item["title"] = title[0]
item["info"] = info[0]
items.append(item)
# 直接返回最後數據
return items

我們暫時先不處理管道,後面會詳細介紹。

保存數據

scrapy保存信息的最簡單的方法主要有四種,-o 輸出指定格式的文件,命令如下:

scrapy crawl itcast -o teachers.json

json lines格式,默認為Unicode編碼

scrapy crawl itcast -o teachers.jsonl

csv 逗號表達式,可用Excel打開

scrapy crawl itcast -o teachers.csv

xml格式

scrapy crawl itcast -o teachers.xml

思考

如果將代碼改成下面形式,結果完全一樣。

請思考 yield 在這裡的作用(Python yield 使用淺析):

# -*- coding: utf-8 -*-
import scrapy
from mySpider.items import ItcastItem
# 以下三行是在 Python2.x版本中解決亂碼問題,Python3.x 版本的可以去掉
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
class Opp2Spider(scrapy.Spider):
name = "itcast"
allowed_domains = ["itcast.com"]
start_urls = ("http://www.itcast.cn/channel/teacher.shtml",)
def parse(self, response):
#open("teacher.html","wb").write(response.body).close()
# 存放老師信息的集合
items = []
for each in response.xpath("//div[@class="li_txt"]"):
# 將我們得到的數據封裝到一個 `ItcastItem` 對象
item = ItcastItem()
#extract()方法返回的都是unicode字元串
name = each.xpath("h3/text()").extract()
title = each.xpath("h4/text()").extract()
info = each.xpath("p/text()").extract()
#xpath返回的是包含一個元素的列表
item["name"] = name[0]
item["title"] = title[0]
item["info"] = info[0]
items.append(item)
# 直接返回最後數據
return items

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

pgbouncer安裝
運算符,鍵盤錄入,流程式控制制語句if總結

TAG:程序員小新人學習 |