Scrapy 是一個以 Python 撰寫的網路爬蟲框架,這篇主要來紀錄一下怎麼使用。

首先,你需要一份官網教學文件

其實官方文件寫得滿清楚的,只是想稍微整理一下、紀錄一下碰到什麼問題而已。然後這篇會以 Answers.com 作為例子。以下正式進入這次的整理:

建立專案

進入你想儲存專案的目錄底下,輸入以下指令,Scrapy就會自動幫你建好一個專案了。

1
scrapy startproject tutorial

完成之後,專案會長這樣子:
Screen Shot 2016-01-18 at 18.01.01

每個檔案是做什麼的官方文件都有,想知道就點進去看吧。

定義 Items

關於 Items,官網是這樣寫的:

Items are containers that will be loaded with the scraped data; they work like simple python dicts but provide additional protecting against populating undeclared fields, to prevent typos.

簡單來說就是定義一些你要輸出的格式(欄位),以 Answers.com 為例,我要抓問題還有分類的 Tag,所以我就定義了一個欄位就做 question 和另一個欄位叫做 url,是這個 question 的連結:

1
2
3
4
5
class AnswersItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
question = scrapy.Field()
url = scrapy.Field()

The First Spider

第一隻蜘蛛 XDD

這裡要寫的是主要的爬蟲程式,包括你要爬的網址、路徑以及方法,簡單來說就是要寫清楚該如何去抓你剛剛定義的那幾個 Items。而這支程式必須要放在 tutorial/spiders 這個目錄底下。

先把該 Import 的東西都弄進來:

1
2
3
4
import sys
import scrapy
from scrapy.http import Request, FormRequest
from scrapy.spider import Spider

接著,把該設定的值設定一下,要設定的部分主要有三個:
(1) name:爬蟲的名字,之後開始爬網頁的時候需要呼叫到
(2) allowed_domains:要爬的網域
(3) start_urls:要從哪個網址開始爬,每個網址會產生不同的 response,這邊用迴圈控制要爬的頁面數量

1
2
3
4
class AnswersSpider(scrapy.Spider):
name = 'myAnswers';
allowed_domains = ['http://www.answers.com/']
start_urls = ['http://www.answers.com/Q/FAQ/4000-%d' % int(i+1) for i in range(10)]

最後,就要來寫方法了。

有兩種方式,第一個是直覺一點的寫法,但是比較沒有那麼清楚,跟剛剛定義的 item 也沒什麼關係。如果要抓的欄位只有一兩個,直接用這個方法我覺得比較方便。

1
2
3
4
5
6
def parse(self, response):
quesText = response.selector.xpath('//div[@class="question"]//a/text()').extract()
with open('questions', 'a') as f:
for qt in quesText:
f.write(str(qt) + '\n')

response.selector.xpath 直接透過 xpath 去抓我要的問題欄位,然後送回給 quesText。而 quesText 會是一個 list,裡頭存著一條條抓回來的問題。要注意的是,如果內文是中文,這邊要記得把每一條問題都 encode 成 utf-8 才有辦法印出。

另一個方法看起來比較複雜,但其實寫起來比較清楚。過程都差不多,只是會把抓回來的東西丟回到剛剛設定好的 item 裡面。每個item都會有兩個欄位,分別是 question 和 url。

1
2
3
4
5
6
7
8
9
def parse(self, response):
sel = Selector(response)
itemList = []
rows = sel.xpath('//div[@class="question_slot"]')
for row in rows:
item = AnswersItem()
item['question'] = row.xpath('.//div[@class="question"]//a/text()').extract()
item['url'] = row.xpath('.//div[@class="question"]//a/@href').extract()
itemList.append(item)

把 item 印出來,會長這樣:

{'question': [u'What are some adjectives that describe a person and begin with the letter N?'], 'url': [u'http://www.answers.com/Q/What_are_some_adjectives_that_describe_a_person_and_begin_with_the_letter_N']}

itemList 當然就是一個個 item 組成的 list。

爬資料

該寫的都寫好了,就要來爬了。要讓這隻蜘蛛開始工作,只要到專案的頂層目錄輸入這個指令:

1
scrapy crawl myAnswers

myAnswers 是剛剛在 class 裡定義的那個 name,就是在這裡用上了。

按下 Enter 後,就等資料自己爬過來吧!

參考文件