[Python網頁爬蟲] Scrapy的安裝與使用入門-2

Sean Yeh
Python Everywhere -from Beginner to Advanced
10 min readJun 14, 2022
Bell Caves, Beit Guvrin, Israel, photo by Sean Yeh

Scrapy是一套開放原始碼框架,對於網頁爬蟲作業基本上會有幾個步驟,包括識別目標網址、取得頁面內容、解析以及儲存網頁等步驟,Scrapy框架中定義了完整的爬蟲流程與模組。透過它可以幫助我們快速且簡單的抓取HTML頁面、取得回傳資料。

上一篇中我們已經建立了Scrapy爬蟲專案 my_spider_1,並且在專案資料夾中初始化了一個爬蟲程式(advertimes)。接下來要在advertimes.py檔案中實際撰寫爬蟲的內容,來對目標網頁爬取資料。

提醒:

在這裡我們要抓取的目標頁面是 https://www.advertimes.com/global/

Scrapy爬蟲實作

爬取的方式可分為二層次,首先會爬取單一個頁面上的資料,接著會爬取下一個頁面的網頁資料。最後再修改程式,爬取該單一網頁至延伸至個內頁的資料。

單一網頁資料爬取

所謂單一網頁爬取,是指爬取的範圍僅限於單一頁面上的內容。

以此目標網站為例,我們要爬取的部分為頁面上的標題、摘要、更新日期以及內頁的連結。

尋找目標內容區塊

在此我們可以打開 Google Chrome的DevTools(可以從Chrome的主選單中選擇「更多工具 > 開發人員工具」或按下滑鼠右鍵單擊頁面元素,然後選擇「檢查」)來檢視HTML的結構,用以找尋目標區元素。

經檢視HTML的結構後,可以發現到框住目標內容區塊的最內層元素為 <ul class=”article-list”> 底下的 <li> (如下圖)。

找出目標對應的XPATH規則

接下來,可以在DevTools最下方的位置,使用Cmd+F打開搜尋輸入方匡,尋找出xpath規則。

我們已知HTML的元素為<ul class=”article-list”> 底下的 <li>(1的位置),在下方(2的位置)將它轉換為xpath表示:

//ul[@class="article-list"]/li

如果輸入的xpath正確的話,按下enter之後你會在HTML的元素的地方看到選定的元素變成黃色(1的位置),並且可以在右下方(3的位置)檢視一下符合這個xpath的數量,以本例來說,符合條件的元素有10筆(3的位置)。

接著,就可以透過response.xpath方法取得位置,並將它指定給變數articles:

articles = response.xpath('//ul[@class="article-list"]/li')

最後要把上面這一行寫在parse函式裡面:

def parse(self, response):
articles = response.xpath('//ul[@class="article-list"]/li')

這樣子就完成了一個目標定位。

取出各目標資料元素

接下來要開始取出目標內容區塊裡面的各個目標資料元素。

在articles 裡面包含著我們想要取得的目標資料,包括標題(title)、摘要(content)、更新日期(update_date)以及內頁的連結(link)。

我們一樣將它轉換為XPATH表示:

# 標題的XPATH

.//a/div[@class="article-list-txt"]/h3/text()

# 摘要的XPATH

.//a/div[@class="article-list-txt"]/p/text()

# 更新日期的XPATH

.//a/div[@class="article-list-txt"]//span[@class="update-date"]/text()

# 內頁的連結的XPATH

.//a/@href

其中,標題、摘要與更新日期的資料包夾在 <h3><p><span> 的元素裡面,在這裡使用 text() 取得資料。

由於我們等一下要透過迴圈從articles開始向內取資料,在此要把response.xpath改為article.xpath

title = article.xpath('.//a/div[@class="article-list-txt"]/h3/text()').get()content = article.xpath('.//a/div[@class="article-list-txt"]/p/text()').get()update_date = article.xpath('.//a/div[@class="article-list-txt"]//span[@class="update-date"]/text()').get()

而內頁的連結位置,則位在href屬性上,在這裡要使用 @href 取得資料。

link = article.xpath(".//a/@href").get()

for迴圈取出資料

使用for-in的迴圈將目標資料元素中的資料取出:

for article in articles:
link = article.xpath(".//a/@href").get()
title = article.xpath('.//a/div[@class="article-list-txt"]/h3/text()').get()
content = article.xpath('.//a/div[@class="article-list-txt"]/p/text()').get()
update_date = article.xpath('.//a/div[@class="article-list-txt"]//span[@class="update-date"]/text()').get()

yield回傳資料

最後使用yield回傳資料。yield是Python的關鍵字,類似函式中的return,只是回傳的是Generator。

yield {
'link':link,
'title':title,
'content':content,
'update_date':update_date
}

完成各項步驟後,將程式碼全部組合在一起,結果如下:

def parse(self, response):
articles = response.xpath('//ul[@class="article-list"]/li')

for article in articles:
link = article.xpath(".//a/@href").get()
title = article.xpath('.//a/div[@class="article-list-txt"]/h3/text()').get()
content = article.xpath('.//a/div[@class="article-list-txt"]/p/text()').get()
update_date = article.xpath('.//a/div[@class="article-list-txt"]//span[@class="update-date"]/text()').get()

yield {
'link':link,
'title':title,
'content':content,
'update_date':update_date
}

執行爬蟲程式:

完成爬蟲程式的撰寫後,就可以執行爬蟲程式。在這裡要輸入下面指令:

$ scrapy crawl advertimes

按下enter鍵執行,結果如下:

儲存資料

從上面的執行結果實在看不出什麼。我們可以把結果輸出存成檔案來觀察。在Scrapy crawl指令中,可以在後面加上「-o」來指定輸出的檔案與格式。

CSV檔

$ scrapy crawl advertimes -o advertimes.csv

透過上面指令可以存成CSV檔,檔名為advertimes.csv,檔名的部分可以自行命名。這個CSV檔會儲存在專案資料夾裡面。打開檔案就可以輕易的看到scrapy爬蟲取得的結果。如下圖:

JSON檔

除了儲存為CSV檔外,還可以選擇儲存為JSON檔案。

$ scrapy crawl advertimes -o advertimes.json

JSON檔案一樣會儲存在專案資料夾裡面。打開檔案就可以看到scrapy爬蟲取得的結果。如下圖:

處理編碼問題

可惜的是,上面儲存的結果裡面出現了人類無法閱讀的『亂碼』。這實際上是因為編碼的問題,在Scrapy爬蟲中要解決這個問題的方式很簡單,可以透過修改專案中的settings.py檔案來改善。

打開settings.py檔案,並且新增一項設定:

FEED_EXPORT_ENCODING="utf-8"

設定增加完畢後儲存檔案。刪除原來有亂碼的JSON檔案( advertimes.json) 並重新執行一遍爬蟲指令:

$ scrapy crawl advertimes -o advertimes.json

結果,新產生的JSON檔案就可以正常顯示,沒有亂碼了。

以上是Scrapy爬蟲框架針對單一網頁的爬取方式,如果您曾經使用過其他爬蟲程式,應該會覺得透過Scrapy來處理資料會比較簡便。至於更多的網頁爬取細節包括如何爬取多個頁面,我們留待下一篇說明。

--

--

Sean Yeh
Python Everywhere -from Beginner to Advanced

# Taipei, Internet Digital Advertising,透過寫作讓我們回想過去、理解現在並思考未來。並樂於分享,這才是最大贏家。