全球經濟面臨空頭襲擊,資金行情被美國聯準會升息潮打擊,很多人說 2022 是總經盤, 牛市階段,個股棒棒開花,投資人反倒覺得總經不夠靈敏,而現今熊市時刻,覆巢之下無完卵 ,投資人開始注意總經的影響力。市面上有不錯的總經平台,如「財經M平方」提供數據圖表,可惜沒提供財經數據API的服務,若要使用總經數據,還是得自己想辦法,所幸有Python爬蟲可以幫我們解決需求。貨幣總計數M1B和M2象徵「流動資金」與「保守資金」的消長,或能幫助資金行情判斷,這篇文章將示範如何爬取M1B和M2的年增率。
財經數據資料源
貨幣總計數的資料最源頭來自台灣中央銀行的新聞稿,每月23-30號間發布「上月金融狀況」,頁內有M1B和M2的年增率的表格資料。然而新聞稿區的早期資料不是那麼完全,網頁格式也變動多次,如果要在此爬蟲所有歷史資料,並非最佳解。
所幸 行政院主計處 也有M1B和M2的數據,而且看來是可以一次抓下JS圖表內的所有數據,會比央行省事省力的許多。然而不幸的是此資料並非完美,現在都已經2022/11/3了,主計處資料還停在8月數據,但中央銀行早在10/24就發布了,怎麼更新同步基調差那麼多?如果是10/31前公佈都還好,拖到11月就真的太慢了。
所以我們需要兩個Python爬蟲,一個爬主計處的財經數據歷史資料。一個爬中央銀行當月的貨幣總計數,作為之後更新最新資料使用。
主計處Python爬蟲
爬蟲開發的第一步是觀察網頁結構,如果資料是以html的table來呈現,那是用pandas的read_html,就非常好解析,據經驗,80%情況都是如此。然而如果不是table,就比較麻煩,若財經數據有直接渲染在網頁,可以用 Beatifulsoup 解析整份 html 檔,再定位標籤抓資料。
可以看到 行政院主計處 的最新M1B數據是7.55,我們可以在Chrome瀏覽器按右鍵選擇檢查,搜尋「7.55」放在哪邊?之後可以發現7.55出現在4個地方,然而table內只有一筆資料,由於我們要抓到歷史資料是放在圖表,圖表資料一般都放在<scripttype type=”text/javascript”>標籤裡的變數,經過搜尋發現我們要把chartValue變數內的資料解析出來。
Python爬蟲程式範例
流程和細節看程式註解,重點在BeautifulSoup網頁解析,和pandas如何產生目標時間序列。下列幾個要熟悉的工具說明。
from bs4 import BeautifulSoup
import pandas as pd
import requests
from datetime import datetime
def crawl_history_from_dgbas():
# 抓下網頁回傳資料
response = requests.get('https://www.dgbas.gov.tw/point.asp?index=10')
# 解析網頁
parsed_file = BeautifulSoup(response.text)
# 找出javascript區塊
js_text = parsed_file.find_all('script', type="text/javascript")
# 抓財經數據定位,資料為餘第3個javascript
data = js_text[3].string
# 文字資料定位,擷取數據部分,將js的日期型態Date.UTC取代成空白
m1b = data[data.index('chartValue[6]') + len('chartValue[6]='):data.index(';\r\nchartValue[7]')].replace(
'Date.UTC', '')
# 將文字轉陣列
eval_m1b = eval(m1b)
# 取出數值,迴圈內d變數已被轉成空白,無意義
m1b_values = [v for d, v in eval_m1b]
# 重複上述動作,觀察chartValue內陣列定位,抓出M2數據
m2 = data[data.index('chartValue[7]') + len('chartValue[7]='):data.index(';\r\nchartValue[8]')].replace(
'Date.UTC', '')
eval_m2 = eval(m2)
m2_values = [v for d, v in eval_m2]
# 日期處理,由於無法抓到即時公告日期,且央行公告日前每月不定,都在每月25號左右公告上月數據,為作業方便,目標將日期設為每月最後一天
# 取出陣列內起始日期、結束日期
start_date = eval_m1b[0][0]
end_date = eval_m1b[-1][0]
# 將日期格式轉為 pandas date_range 的參數格式,產生每月日期序列
start = f'{start_date[0]}-{start_date[1]}-{start_date[2]}'
end = f'{end_date[0]}-{end_date[1] + 1}-{end_date[2]}'
# 日期序列為每月1日,為產生本月底公告去年數據的效果,使用tseries.offsets將日期後推
dates = pd.date_range(start, end, freq='M') + pd.tseries.offsets.MonthEnd(2)
# 產生m1b與m2數據,將數據併表
m1b_df = pd.DataFrame({'stock_id': '貨幣總計數M1B', 'date': dates, '年增率(%)': m1b_values})
m2_df = pd.DataFrame({'stock_id': '貨幣總計數M2', 'date': dates, '年增率(%)': m2_values})
concat_df = pd.concat([m1b_df, m2_df])
concat_df = concat_df.set_index(['stock_id', 'date'])
return concat_df
Python爬蟲輸出結果
中央銀行Python爬蟲
這個爬蟲要分兩步驟,首先由於每月金融情況新聞稿的連結沒有規律,所以要先解析最新消息的>新聞稿的首頁,取出近月新聞稿的超連結,再將連結傳到 python requests 取得表格數據,之後再將資料稍微整理成前面主計處爬蟲的資料格式。
另外要注意若每月25號前就執行此爬蟲,可能會有當月資料還沒公告的問題,所以要加上例外狀況處理,回傳一個空的dataframe。
Python爬蟲程式範例
def central_bank_crawl():
# 資料目標日期,轉成民國型態的上月日期
now = datetime.now()
year = now.year - 1911
month = (now.month + 10) % 12 + 1
if month == 12:
year -= 1
# 解析出最新消息內近月金融情況新聞稿的超連結
menu_response = requests.get('https://www.cbc.gov.tw/tw/lp-302-1.html')
parsed_file = BeautifulSoup(menu_response.text)
text = parsed_file.find('a', title=f"{year}年{month}月金融情況")
# 沒資料則回傳空表
if text is None:
return pd.DataFrame()
# 取出超連結
href = text['href']
# read_html 解析表格數據
report_response = requests.get(f'https://www.cbc.gov.tw/{href}')
report_df = pd.read_html(report_response.text)[0]
report_df.columns = report_df.columns.get_level_values(1)
report_df = report_df.iloc[:, :3]
report_df = report_df.rename(columns={'項 目': 'stock_id', '年增率': '年增率(%)'})
report_df = report_df[['stock_id', '年增率(%)']]
report_df['date'] = datetime(now.year, now.month, 1) + pd.tseries.offsets.MonthEnd(1)
report_df = report_df.set_index(['stock_id', 'date'])
return report_df
結論
colab程式範例
這個爬蟲和證交所那類好爬的表格與穩定資料相比,有一些要注意的坑,處理上也比較多層,所以特別記錄一下。行政院主計處和央行還有許多總經數據,如果你有需求,可以自己用上述範例練習抓抓看,或直接使用 FinLab資料庫 來抓喔。
如果你對爬蟲想知道更多,可參考我們其他教學文章
超簡單台股每日爬蟲教學
超簡單用python抓取每月營收
三大法人爬蟲:Python實作教學
python上櫃資料爬蟲輕鬆做
財報爬蟲超簡單 – 用Python一次抓綜合損益、資產負債、營利分析