Python 爬蟲實戰範例

使用 Selenium 抓取

鉅亨網 高年化配息債券型基金

提供給想學習 Python 爬蟲的朋友們,分享 Python 爬蟲的步驟與方法,並提供完整的程式碼,只要常透過不同主題的實戰練習,就可以駕輕就熟爬蟲技術,往後要抓取網頁資料,就能夠輕易上手

Python 網路爬蟲(web scraping)是一個非常夯的主題,而且也很容易入門,只要有一些 Python 的基礎,幾次的練習,就可以慢慢上手。在本文的主題實作中,我們會使用到 Selenium 套件,它可以直接用程式來自動操作瀏覽器,以及 BeautifulSoup 用來解析網頁內容,並擷取出所需的資料,在使用 Pandas 套件就可以將擷取出來的資料整理好並儲存至 csv 檔案當中,最後這份檔案就可以使用 Excel、Google Sheets 或是 Numbers 來開啟

如果你還你還不知道網路爬蟲是什麼,可以先閱讀這一篇:認識網路爬蟲

我們將打造 Python 基金爬蟲程式,使用 Selenium 套件自動操作瀏覽器,抓取鉅亨網高年化配息債券型基金,並將搜尋的結果給抓取下來儲存至檔案當中

鉅亨網債券型基金搜尋器網址:https://fund.cnyes.com/Fixedincome/search.aspx

那我們開始吧!

本文中 Python 基金爬蟲實戰範例程式碼可以直接在 Google Drive 下載

第一步:檢視要抓取的資料

在抓取我們所需的內容前,要先了解資料的來源,我們將使用鉅亨網債券型基金搜尋器選擇【1】計價幣別為【美金】,【2】基金組別為【全球市場高收益債】,【3】年化配息率為【7%至10%以上】,【4】配息頻率【月】並且按【搜尋】,取得結果後,在使用【5】【三年】的績效來做排序,最後在表格中【晨星評級超過三顆星】的就會是我們要的結果

Python 爬蟲實戰範例|使用 Selenium 抓取 鉅亨網 高年化配息債券型基金

這操作的流程目前是使用手動的方式來操作,待會我們就會使用程式來自動模仿這流程。

第二部:安裝套件與驅動程式

環境可以使用 Jupyter Notebook 或是自己習慣的文字編輯器,要先安裝以下所需的套件。

pip install selenium
pip install bs4
pip install lxml
pip install pandas

另外 Selenium 需要瀏覽器的驅動程式才可以正常運作,而我們將以 Google Chrome 作為範例,首先要知道目前電腦的 Google Chrome 版本,點選瀏覽器右上角【三個點的圖示選擇】,再點【設定】,或是直接前往連結 chrome://settings/help,就可以看到目前的版本,就以我目前的電腦是使用 Windows 作業系統,Google Chrome 瀏覽器版本為 90。

Python 爬蟲實戰範例|使用 Selenium 抓取 鉅亨網 高年化配息債券型基金

知道 Google Chrome 版本後,就可以前往 ChromeDriver – WebDriver for Chrome 根據自己電腦的作業系統和版本來下載驅動程式,並解壓縮。

第三步:使用 Selenium 操作瀏覽器

先 impot 全部所需的套件,定義 url 為鉅亨網債券型基金搜尋器網址,在建立 Chrome driver 物件,executable_path 要丟入剛剛下載的 chromedriver 位置,而【./】代表當前路徑,在這是將 chromedriver 放到與 Jupyter Notebook 相同的路徑,最後在使用 driver.get(url) 讓瀏覽器前往 url 網址,執行之後,會看到程式自動開啟一個瀏覽器,並前往鉅亨網債券型基金搜尋器的網頁

import time
from datetime import datetime
from selenium import webdriver
from bs4 import BeautifulSoup
import pandas as pd

url = 'https://fund.cnyes.com/Fixedincome/search.aspx'

driver = webdriver.Chrome(executable_path='./chromedriver')
driver.get(url=url)

接著透過 find_element_by_xpath來取得元素的位置【以計價幣別為例】,並使用 click() 來點擊,XPath 為 XML Path Language,是一種用來尋找文件中某個節點位置的查詢語言

# 計價幣別
driver.find_element_by_xpath('//*[@id="ctl00_ContentPlaceHolder1_DD_classCurrent"]').click()
driver.find_element_by_xpath('//*[@id="ctl00_ContentPlaceHolder1_DD_classCurrent"]/option[7]').click()

欲要取得網頁元素【以計價幣別為例】的 XPath 可以直接在下拉式選單中,【1】按右鍵 > 檢查,就會開啟 Chrome 開發人員工具,並在【2】元素程式碼上按右鍵選擇 【3】Copy >【4】 Copy XPath 來取得

Python 爬蟲實戰範例|使用 Selenium 抓取 鉅亨網 高年化配息債券型基金

理解原理後,就能夠使用相同的邏輯,透過之前流程來操作,選擇計價幣別為【美金】,基金組別為【全球市場高收益債】,年化配息率為【7%至10%以上】,配息頻率【月】並且按【搜尋】,取得結果後,在使用【三年】的績效來做排序,在途中加上 time.sleep(5) 來等待5秒,等搜尋的結果出現後再繼續執行

# 投資區域(全球市場)
driver.find_element_by_xpath('//*[@id="ctl00_ContentPlaceHolder1_DropDownList1"]').click()
driver.find_element_by_xpath('//*[@id="ctl00_ContentPlaceHolder1_DropDownList1"]/option[8]').click()

# 基金組別(高收益債)
driver.find_element_by_xpath('//*[@id="ctl00_ContentPlaceHolder1_DropDownList2"]').click()
driver.find_element_by_xpath('//*[@id="ctl00_ContentPlaceHolder1_DropDownList2"]/option[7]').click()

# 年化配息率(7%)
driver.find_element_by_xpath('//*[@id="aspnetForm"]/div[4]/div[1]/select[1]').click()
driver.find_element_by_xpath('//*[@id="aspnetForm"]/div[4]/div[1]/select[1]/option[9]').click()

# 至(10%以上)
driver.find_element_by_xpath('//*[@id="aspnetForm"]/div[4]/div[1]/select[2]').click()
driver.find_element_by_xpath('//*[@id="aspnetForm"]/div[4]/div[1]/select[2]/option[4]').click()

# 配息頻率
driver.find_element_by_xpath('//*[@id="div_type"]').click()
driver.find_element_by_xpath('//*[@id="div_type"]/option[4]').click()

# 搜尋
driver.find_element_by_xpath('//*[@id="aspnetForm"]/div[4]/div[3]/button').click()

time.sleep(5)

# 三年績效排序
driver.find_element_by_xpath('/html/body/div[2]/section[3]/div/div[4]/table[2]/thead/tr/th[3]/select').click()
driver.find_element_by_xpath('/html/body/div[2]/section[3]/div/div[4]/table[2]/thead/tr/th[3]/select/option[6]').click()

time.sleep(5)

html_source = driver.page_source

driver.close()

soup = BeautifulSoup(html_source, 'lxml')

執行完成後,就可以透過 driver.page_source 來取的當前網頁的 HTML 原始碼,並處存至 html_source 變數中,這時就可以透過 driver.close() 來關掉瀏覽器,最後在建立 BeautifulSoup 物件,而官方建議使用 lxml 的解析方法,因為速度快,相容性也較佳

下個步驟,我們就能解析網頁的內容並擷取我們所需的資料

第四步:解析與擷取所需資訊

先建立一個字典,用來暫存基金的資料,在使用 soup.select_one(‘tbody’).select(‘tr’) 取出網頁原始碼中第一個 tbody 標籤裡所有 tr 標籤,然後跑 for 迴圈,也就是基金表格中每筆基金資料,在各別從中取出基金名稱、淨值、三年績效、配息日、配息金額、年化配息率以及晨星評級,另外多加一個判斷式,過濾掉所有晨星評級3星以下的基金

fund_dict = {
	'基金名稱': [],
	'淨值': [],
	'三年績效': [],
	'配息日': [],
	'配息金額': [],
	'年化配息率': [],
	'晨星評級': [],
	'連結': []
}

for tr in soup.select_one('tbody').select('tr'):

    morning_star = len(tr.select('td')[5].select('li.on'))

    if morning_star >= 3:

        fund_dict['基金名稱'].append(tr.select('td')[0].text.strip())
        fund_dict['淨值'].append(tr.select('td')[1].text.strip().split('\n')[0])
        fund_dict['三年績效'].append(tr.select('td')[2].text.strip())
        fund_dict['配息日'].append(tr.select('td')[3].text.strip().split('\n')[-1].strip())
        fund_dict['配息金額'].append(tr.select('td')[4].text.strip().split('\n')[0].strip())
        fund_dict['年化配息率'].append(tr.select('td')[4].text.strip().split('\n')[-1].strip())
        fund_dict['晨星評級'].append(morning_star)
        fund_dict['連結'].append('https://fund.cnyes.com' + tr.select('td')[0].a['href'].strip().replace(' ', '%20'))

跑完 for 迴圈後,最後 fund_dict 字典中的資料將會如下

{
    '基金名稱': ['NN (L) 環球高收益基金X股對沖級別美元(月配息) (美元|月配)',
    'NN (L) 環球高收益基金X股美元(月配息) (美元|月配)',
    '法巴全球高收益債券基金/月配(美元)避險 (美元|月配)'],
    '淨值': ['186.4600', '71.7300', '75.9900'],
    '三年績效': ['+17.14%', '+16.85%', '+16.19%'],
    '配息日': ['2021/06/02', '2021/06/02', '2021/06/01'],
    '配息金額': ['1.4200', '0.5500', '0.5600'],
    '年化配息率': ['9.12%', '9.16%', '8.83%'],
    '晨星評級': [3, 3, 3],
    '連結': ['https://fund.cnyes.com/detail/NN%20(L)%20環球高收益基金X股對沖級別美元(月配息)/B33,173/report',
    'https://fund.cnyes.com/detail/NN%20(L)%20環球高收益基金X股美元(月配息)/B33,081/report',
    'https://fund.cnyes.com/detail/法巴全球高收益債券基金/月配(美元)避險/B06,298/report']
}

第五步:儲存資料

接著要將擷取的資料,儲存至 csv 檔案中,直接透過字典來建立一個 DataFrame,並將【基金名稱】設定為 index,其中 inplace=True 代表不建立新的 DataFrame 物件,直接對本身 DataFrame 物件進行修改

df = pd.DataFrame(fund_dict)
df.set_index('基金名稱', inplace=True)
df

執行後,可以整理出以下表格

Python 爬蟲實戰範例|使用 Selenium 抓取 鉅亨網 高年化配息債券型基金

最後在使用 DataFrame 的 to_csv 方法,並丟入要建立的檔案名稱,就可以直接將整理好的 DataFrame 表個寫入 csv 檔案中 (新建立的檔案會在 Jupyter Notebook 相同的路經中找到),而為了避免儲存之後中文出現亂碼需加上帶入 encoding=’utf_8_sig’ 

date = datetime.today().strftime("%Y%m%d")
file_name = '{}_全球高收益債基金.csv'.format(date)
df.to_csv(file_name, encoding='utf_8_sig')

執行上方程式碼之後,就可以在 Jupyter Notebook 相同路徑中看到 csv 檔案,內容就是在鉅亨網中前幾名的高年化配息債券型基金資料

Python 爬蟲實戰範例|使用 Selenium 抓取 鉅亨網 高年化配息債券型基金

以上就是使用 Selenium 抓取鉅亨網高年化配息債券型基金的 Python 基金爬蟲實作範例;以下可以看到完整的程式碼,也可以直接下載 Jupyter Notebook 基金爬蟲程式碼檔案。

可繼續閱讀 Python 基金爬蟲Part 2,將篩選出來的基金更進一步取得各基金的細節資料,包含了管理費、成立日期、基金規模、風險評等、申購手續費、夏普值和表準差等資訊。

結語

現今已經有很多的工具與套件(像是本文中提到的 Selenium、BeautifulSoup 與 Pandas)能夠快速的開發適合自己需求的網路爬蟲工具,而 Python 非常最適合寫爬蟲,程式看起來很清楚、優雅、可以快速入門,而且只需要有些 Python 程式語言的基礎,透過實作範例練習,就能夠開發出網路爬蟲工具

之後我們會再陸續出其它 Python 網路爬蟲主題實作,可以訂閱我們,當推出新的文章時,我們將會把第一首消息通知給你喔,如果你有其他問題,或是想要我們推出什麼樣的爬蟲實作,可以直接寄信至 webscrapingpro.tw@gmail.com 聯絡我們喔

全方位 Python 課程

無論你是初學者還是有經驗的開發者,這裡的課程都能滿足你的需求。精心設計的8堂課程,涵蓋不同類型的Python主題,幫助你在各個領域中脫穎而出。