使用 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爬取房天下的推薦新樓盤
※用 greenlet 實現 Python 中的並發
TAG:Python開發 |