當前位置:
首頁 > 知識 > 使用 Scrapy 構建一個網路爬蟲

使用 Scrapy 構建一個網路爬蟲

點擊上方「

Python開發

」,選擇「置頂公眾號」


關鍵時刻,第一時間送達!






記得n年前項目需要一個靈活的爬蟲工具,就組織了一個小團隊用Java實現了一個爬蟲框架,可以根據目標網站的結構、地址和需要的內容,做簡單的配置開發,即可實現特定網站的爬蟲功能。因為要考慮到各種特殊情形,開發還耗了不少人力。後來發現了Python下有這個Scrapy工具,瞬間覺得之前做的事情都白費了。對於一個普通的網路爬蟲功能,Scrapy完全勝任,並把很多複雜的編程都包裝好了。本文會介紹如何Scrapy構建一個簡單的網路爬蟲。



一個基本的爬蟲工具,它應該具備以下幾個功能:






  • 通過HTTP(S)請求,下載網頁信息



  • 解析網頁,抓取需要的內容



  • 保存內容



  • 從現有頁面中找到有效鏈接,從而繼續抓取下一個網頁






我們來看下Scrapy怎麼做到這些功能的。首先準備Scrapy環境,你需要安裝Python(本文使用v2.7)和pip,然後用pip來安裝lxml和scrapy。個人強烈建議使用virtualenv來安裝環境,這樣不同的項目之間不會衝突。詳細步驟這裡就不贅述了。對於Mac用戶要注意,當使用pip安裝lxml時,會出現類似於的下面錯誤:





Error: #include 「xml/xmlversion.h」 not found




解決這個問題,你需要先安裝Xcode的command line tools,具體的方法是在命令行執行下面的命令即可。





$ xcode-select --install




環境安裝好之後,我們來用Scrapy實現一個簡單的爬蟲,抓取本博客網站的文章標題,地址和摘要。




1. 創建工程





$ scrapy startproject my_crawler



該命令會在當前目錄下創建一個名為」my_crawler」的工程,工程的目錄結構如下





my_crawler


  |-

my_crawler


  |    |-

spiders


  |    |    |-

__init__

.

py


  |    |-

items

.

py


  |    |-

pipelines

.

py

  |    |-

setting

.

py


  |-

scrapy

.

cfg




2. 設置待抓取內容的欄位,本例中就是文章的標題,地址和摘要




修改」items.py」文件,在」MyCrawlerItem」類中加上如下代碼:





# -*- coding: utf-8 -*-


import

scrapy



class

MyCrawlerItem

(

scrapy

.

Item

)

:


    

title

=

scrapy

.

Field

()

    

# 文章標題


    

url

=

scrapy

.

Field

()

      

# 文章地址


    

summary

=

scrapy

.

Field

()

  

# 文章摘要


    

pass




3. 編寫網頁解析代碼




在」my_crawler/spiders」目錄下,創建一個名為」crawl_spider.py」文件(文件名可以任意取)。代碼如下





# -*- coding: utf-8 -*-


import

scrapy


from

scrapy

.

linkextractors

import

LinkExtractor


from

scrapy

.

spiders

import

CrawlSpider

,

Rule



from

my_crawler

.

items

import

MyCrawlerItem



class

MyCrawlSpider

(

CrawlSpider

)

:


    

name

=

"my_crawler"

              

# Spider名,必須唯一,執行爬蟲命令時使用


    

allowed_domains

=

[

"bjhee.com"

]

  

# 限定允許爬的域名,可設置多個


    

start_urls

=

[


        

"http://www.bjhee.com"

,

      

# 種子URL,可設置多個


    

]



    

rules

=

(

    

# 對應特定URL,設置解析函數,可設置多個


        

Rule

(

LinkExtractor

(

allow

=

r

"/page/[0-9]+"

),

  

# 指定允許繼續爬取的URL格式,支持正則


                          

callback

=

"parse_item"

,

  

# 用於解析網頁的回調函數名


                          

follow

=

True


        

),


    

)



    

def

parse_item

(

self

,

response

)

:


        

# 通過XPath獲取Dom元素


        

articles

=

response

.

xpath

(

"//*[@id="main"]/ul/li"

)



        

for

article

in

articles

:


            

item

=

MyCrawlerItem

()


            

item

[

"title"

]

=

article

.

xpath

(

"h3[@class="entry-title"]/a/text()"

).

extract

()[

0

]


            

item

[

"url"

]

=

article

.

xpath

(

"h3[@class="entry-title"]/a/@href"

).

extract

()[

0

]


            

item

[

"summary"

]

=

article

.

xpath

(

"div[2]/p/text()"

).

extract

()[

0

]


            

yield

item




對於XPath不熟悉的朋友,可以通過Chrome的debug工具獲取元素的XPath。







4. 讓我們測試下爬蟲的效果




在命令行中輸入:





$ scrapy crawl my_crawler




注意,這裡的」my_crawler」就是你在」crawl_spider.py」文件中起的Spider名。




沒過幾秒鐘,你就會看到要抓取的欄位內容列印在控制台上了。就是這麼神奇!Scrapy將HTTP(S)請求,內容下載,待抓取和已抓取的URL隊列的管理都封裝好了。你的主要工作基本上就是設置URL規則及編寫解析的方法。




我們將抓取的內容保存為JSON文件:





$ scrapy crawl my_crawler -o my_crawler.json -t json




你可以在當前目錄下,找到文件」my_crawler.json」,裡面保存的就是我們要抓取的欄位信息。(參數」-t json」可以省去)




5. 將結果保存到資料庫




這裡我們採用MongoDB,你需要先安裝Python的MongoDB庫」pymongo」。編輯」my_crawler」目錄下的」pipelines.py」文件,在」MyCrawlerPipeline」類中加上如下代碼:





# -*- coding: utf-8 -*-


import

pymongo



from

scrapy

.

conf

import

settings


from

scrapy

.

exceptions

import

DropItem



class

MyCrawlerPipeline

(

object

)

:


    

def

__init__

(

self

)

:


        

# 設置MongoDB連接


        

connection

=

pymongo

.

Connection

(


            

settings

[

"MONGO_SERVER"

],


            

settings

[

"MONGO_PORT"

]


        

)


        

db

=

connection

[

settings

[

"MONGO_DB"

]]


        

self

.

collection

=

db

[

settings

[

"MONGO_COLLECTION"

]]



    

# 處理每個被抓取的MyCrawlerItem項


    

def

process_item

(

self

,

item

,

spider

)

:


        

valid

=

True


        

for

data

in

item

:


            

if

not

data

:  

# 過濾掉存在空欄位的項


                

valid

=

False


                

raise

DropItem

(

"Missing {0}!"

.

format

(

data

))



        

if

valid

:


            

# 也可以用self.collection.insert(dict(item)),使用upsert可以防止重複項


            

self

.

collection

.

update

({

"url"

:

item

[

"url"

]},

dict

(

item

),

upsert

=

True

)



        

return

item




再打開」my_crawler」目錄下的」settings.py」文件,在文件末尾加上pipeline的設置:





ITEM_PIPELINES

=

{


    

"my_crawler.pipelines.MyCrawlerPipeline"

:

300

,

    

# 設置Pipeline,可以多個,值為執行優先順序


}



# MongoDB連接信息


MONGO_SERVER

=

"localhost"


MONGO_PORT

=

27017


MONGO_DB

=

"bjhee"


MONGO_COLLECTION

=

"articles"



DOWNLOAD_DELAY

=

2

    

# 如果網路慢,可以適當加些延遲,單位是秒




6. 執行爬蟲





$ scrapy crawl my_crawler




別忘了啟動MongoDB並創建」bjhee」資料庫哦。現在你可以在MongoDB里查詢到記錄了。







總結下,使用Scrapy來構建一個網路爬蟲,你需要做的就是:






  • 「items.py」中定義爬取欄位



  • 在」spiders」目錄下創建你的爬蟲,編寫解析函數和規則



  • 「pipelines.py」中對爬取後的結果做處理



  • 「settings.py」設置必要的參數




其他的事情,Scrapy都幫你做了。下圖就是Scrapy具體工作的流程。怎麼樣?開始寫一個自己的爬蟲吧。







本例中的代碼可以在這裡下載(http://www.bjhee.com/downloads/201511/my_crawler.tar.gz)。






  • 來源:思誠之道




  • www.bjhee.com/scrapy.html



  • Python開發整理髮布,轉載請聯繫作者獲得授權


【點擊成為Java大神】

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

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


請您繼續閱讀更多來自 Python開發 的精彩文章:

詳解Python爬取房天下的推薦新樓盤
用 greenlet 實現 Python 中的並發

TAG:Python開發 |