Selenium 網路爬蟲教學: 用 Selenium 到 Yahoo Finance 抓股票訊息

PUBLISHED ON OCT 18, 2018 — WEB
FacebookTwitter 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 抓資料的爬蟲。

    TAGS: SELENIUM