[Rails] Capybara 搭配 Nokogiri 動態網站爬蟲 Web Scraping & Parsing

Roger Wang
4 min readDec 7, 2019

--

前言

最近碰到了一個與動態爬蟲有關的功能需求,順便筆記一下 2019 年在 RoR 上動態爬蟲的方案之一: Capybara + Nokogiri

Nokogiri

Nokogiri 是 Rails 內用來爬取標籤文件(例如:HTML、XML)的套件,大部分的 RoR 實作爬蟲的方式就是使用這個套件,但因為現代網頁的內容通常不會直接定義在 HTML 內了,所以光是會靜態網站爬蟲已經很難爬到想要的資料了

Capybara

Capybara 原本是用來做 integration test 的套件,但它的 browser 模擬也很適合用來搭配 Nokogiri 做動態爬蟲

Step 1: 搭建環境

首先開啟一個新的 Rails 專案並在 Gemfile 加入以下套件,Capybara 在 Gemfile 內原本就有定義了,但因為他放在 test 環境內,所以要移出來其他環境使用

gem 'selenium-webdriver'gem 'capybara'gem 'webdrivers' # 讓使用 driver 變得更方便

然後新增一個 initializer,設為 selenium 方便在開發的時候觀察網頁模擬操作的情形

可以把 driver 設為 headless 讓爬蟲能在 server 上運行,而且執行起來很快,無負擔,詳細設定在:https://thoughtbot.com/blog/headless-feature-specs-with-chrome

太長被切掉了 😱直接點進去看看唄

Step 2: 了解目標網頁的行為觸發

大俠,平日閒暇時間多使用 chrome 的開發模式觀察網頁內容

所謂知己知彼,百戰百勝啊 🤷‍♀️🤷‍♂️

設定完 Capybara 後,就可以來爬蟲了🐞,本篇以台大醫院的看診進度的分頁為例,網址如下:https://reg.ntuh.gov.tw/webadministration/ClinicCurrentLightNoByDeptCode.aspx

Step 2–1: 網頁元件

進入連結後,會看到以下四個元件

  • 3 個選擇列表
  • 1 個查詢按鈕

這個分頁只有一個功能,選擇了醫院、科別與時間後就會自動查詢,不過只要選擇科部後就會自動 render 出該科部的內容了,因為該元件中 onchange() 定義如下

注意 onchange()

另外該元件的 id 為 SelectHospDeptAndAMPM_DropDownDept

Step 2–2: 行為觸發

當在 --選擇科部-- 中選擇內科部後,頁面會自動 render 出該科別所有門診的看診進度

P.S. 因為我是在週末寫這篇的😝 週末沒有人在看病,不然燈號那邊是會有一個數字的,臺大醫院內科部也不會只有一個門診,BTW 那個號碼也是爬得出來的,我試過~

Step 3: 寫程式模擬行為

Step 3–1: Capybara 模擬瀏覽器行為

  1. Capybara browser, driver 宣告
  2. 造訪網頁
  3. --選擇科別-- 選擇內科部(id 在前個步驟有說明,如果忘記了請往上找)

Step 3–2: 使用 Nokogiri 爬取網站內容

3–1 做完,執行時已經可以看到網頁出現 2–2 中的畫面了,接下來我們要用 nokogiri 來爬我們需要的內容

使用 driver 中的 page_source 取得 HTML 內容,然後再使用標籤中的 css 輔助查找需要的元件與元件內容,過程我就不贅述了,在開發模式找一找就好~

執行上面兩段程式碼會得到以下四個結果

  1. 98 診
  2. 主治醫師
  3. 醫師約診
  4. nil (因為現在是空號)

功能實作到此完結撒花🎊 🎉

後記

是不是 Hen 簡單呢,既然提到 Capybara 小弟就順便分享一下我曾踩過的兩個雷

  1. 有些元件被包太緊會找不到,要一層一層一層剝開它的心
  2. 在 selenium chrome(non-headless) 模式中曾經遇到預設開啟的視窗太小,所以找不到元件,可以的話在設定裡面定義一下應該能避免~

覺得文章不錯的話歡迎分享與追蹤我的個人帳號
順便拍拍手👏👏👏
謝謝🙇‍♂️

--

--

No responses yet