位元詩人 [Selenium] 程式設計教學:如何到 Yahoo Finance 抓股票訊息

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

免責聲明:我們盡力確保本文的正確性,但本文不代表任何投資的建議,我們也無法擔保因使用本文的內容所造成的任何損失。如對本文內容有疑問,請詢問財經相關的專家。

除了手動瀏覽網站並抓取交易數據外,使用爬蟲 (crawlers) 可以達到同樣的效果,而且省下機械化的手動操作。本文的目標是學習如何透過爬蟲自動化獲得交易數據的過程。如果只要單次抓取少量資料,爬蟲不是很必要,但長期來說會節省時間。

本節透過一個實例來說明如何撰寫 Selenium 程式。Selenium 有數種 language binding,我們這裡以 Python 為例。由於網頁過一陣子可能會改版,不要硬背教程所提供的爬蟲的程式碼,而要透過閱讀程式碼學習如何自行手動撰寫。

我們這個爬蟲的動作拆解如下:

  1. 前往 Yahoo Finance 網頁
  2. 在搜尋框輸入我們感興趣的投資標的,像是 SPY (標普指數)
  3. 按下輸入鈕,刷到 SPY 所在的頁面
  4. 切換到 Historical Data 所在的分頁
  5. 開啟 Time Period 的設定框
  6. 將時距調到 5 年 (5Y)
  7. 按下 Done 按鈕關閉該設定框
  8. 按下 Apply 按鈕確認該設定生效
  9. 按下 Download Data 連結下載 CSV 檔案

讀者可先手動操作一下,感受這個過程。Selenium 程式就是把這個過程轉成程式碼,寫起來沒有什麼複雜的邏輯。由於整個範例程式碼偏長,我們將完整的程式碼放在這裡。在本文中,我們將這個爬蟲拆解,讓讀者感受一步步完成爬蟲的感覺。

一開始要先引入相關的模組:

from selenium import webdriver

在此處,我們將搜尋目標設為 "SPY":

# We want to get the data of SPDR S&P 500 ETF (SPY)
targetAsset = "SPY"

在本範例,我們使用 Chrome 瀏覽器:

# Create a new instance of the Chrome driver
driver = webdriver.Chrome()

撰寫 Selenium 程式時不一定要使用 Chrome,目前幾個主流的瀏覽器都有相對應的 web driver 可下載。

一開始先前往 Yahoo Finance 的頁面:

# go to the Yahoo Finance page
driver.get("https://finance.yahoo.com/")

我們將錨點定到搜尋框,輸入搜尋目標,並執行搜尋的動作:

# find the input box
inputElement = driver.find_element_by_css_selector("#fin-srch-assist input")

# type in the search
inputElement.send_keys(targetAsset)

# submit the form (although google automatically searches now without submitting)
inputElement.submit()

定錨的方式有很多,像是 HTML tag、class、id 等,基本上,CSS selector 可用的方式都可以用來定錨。Selenium 提供數個函式呼叫,以對應不同的錨點,在這些函式中,以 CSS selector 為錨點的函式算是通用性最好的,筆者大部分都會用這類函式來操作瀏覽器。

由於我們要等頁面刷新,故讓程式休息 10 秒:

# Wait the page to refresh.
time.sleep(10)

有時候要讓程式暫停數秒,等網頁刷完,跑出新的 elements,爬蟲才可進行下一步動作。以 Python 來說,可搭配 time 模組來暫停程式。

切換到 Historical Data 所在的分頁:

items = driver.find_elements_by_css_selector("a span")
for item in items:
    if item.text == "Historical Data":
        item.click()
        break

要注意到這個函式回傳的東西是串列,要透過迴圈取出其內的 web element。檢查 element 的文字來確認 element 是一個相對簡單且常用的方式。

接下來打開選擇時距的選單,選擇 5 年後按確認:

arrows = driver.find_elements_by_css_selector(".historical div div span svg")
arrows[0].click()

durations = driver.find_elements_by_css_selector("[data-test=\"date-picker-menu\"] div span")
for duration in durations:
    if duration.text == "5Y":
        duration.click()
        break

buttons = driver.find_elements_by_css_selector("[data-test=\"date-picker-menu\"] div button")
for button in buttons:
    if button.text == "Done":
        button.click()
        break

這裡其實包含三個步驟,開啟選單、選擇時距、按 Done 按鈕以結束選取的動作。我們不會硬要選定單一 element,而是會先選一個小範圍的 elements,再進行第二次篩選,這樣寫起來比較簡單。

按下 Apply 按鈕確認我們的選擇:

buttons = driver.find_elements_by_css_selector("button span")
for button in buttons:
    if button.text == "Apply":
        button.click()
        break

選擇 Download Data 的連結以下載 CSV 表格:

links = driver.find_elements_by_css_selector("a span")
for link in links:
    if link.text == "Download Data":
        link.click()
        break

最後別忘了關掉瀏覽器:

driver.quit()

讀者可參考本文,自行寫出爬取 Yahoo Finance 抓資料的爬蟲。

關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。