還記得我們之前從證交所取得台積電的歷史資料嗎?為了成交數量更準確,我們從Yahoo轉換到證交所。
(不得不說,Yahoo、Google取資料真方便!)
但我們只有拿到每日的盤後資料,要拿到歷史的資料卻要如何做呢?
證交所的各股盤後資料可以從這邊收集資料
https://www.twse.com.tw/zh/page/trading/exchange/STOCK_DAY.html
在這邊,可以輸入股票名稱或代碼,然後選擇日期,就可以在下方表格得到股票在該月份的交易資訊。並且可以用HTML
、CSV
的格式下載下來。
這種方式對於一般人下載使用,或是觀看很方便,但是我們需要抓下來後,進行計算與整理卻十分不便。假設我們直接爬取整個網站的資料,必須輸入時間和股票,再找到表格進行處理。
這時候發現有個API,可以把表格的資料變成方便我們進行解析的形式:
https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date=202009&stockNo=2330
那我們就拿這個資料,放到我們Azure中,並且有日期,不用擔心每日交易資料沒有日期,會有錯誤。之前用作業時間抓日期,會有過0點的事情發生,導致日期錯誤。這個歷史資料就不會有囉!
抓到資料後會變成這樣:
{
"stat": "OK",
"date": "20200926",
"title": "109年09月 2330 台積電 各日成交資訊",
"fields": [
"日期",
"成交股數",
"成交金額",
"開盤價",
"最高價",
"最低價",
"收盤價",
"漲跌價差",
"成交筆數"
],
"data": [
[
"109/09/01",
"50,129,577",
"21,681,382,412",
"430.00",
"435.00",
"428.00",
"435.00",
"+8.50",
"17,137"
],
[
"109/09/02",
"42,013,407",
"18,268,716,092",
"441.00",
"441.00",
"430.50",
"433.00",
"-2.00",
"20,242"
],
......
[
"109/09/25",
"41,263,269",
"17,522,224,043",
"427.00",
"428.00",
"421.00",
"424.00",
"+1.00",
"23,290"
]
],
"notes": [
"符號說明:+/-/X表示漲/跌/不比價",
"當日統計資訊含一般、零股、盤後定價、鉅額交易,不含拍賣、標購。",
"ETF證券代號第六碼為K、M、S、C者,表示該ETF以外幣交易。"
]
}
呈現方式幾乎跟網頁一樣,如果把response=json
換成response=html
就跟我們在證交所搜尋網頁中看到的一模一樣。而在json
格式中,我們只需要fields
、data
。
我們把Day16的資料再進行修改成讀取歷史資料的:
# API位置
# address = "http://www.twse.com.tw/exchangeReport/STOCK_DAY_ALL?response=open_data"
stock = "2330"
date = "202009"
address = f"https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date={date}&stockNo={stock}"
# 取得資料
response = requests.get(address)
# 解析
# 有幾個部分:stat, date, title, fields, data, notes
data = response.text # 這是json格式的資料
a_json = json.loads(data) # 轉成dict
df = pandas.DataFrame.from_dict(a_json["data"]) # 轉成dataframe
# 修改欄位名稱
new_headers = create_new_header(a_json["fields"])
df.columns = new_headers # 設定資料欄位的名稱
# print(df)
_ = save_data_to_azure_db(stock, df)
print("===finished===")
其中欄位功能稍微修改,增加日期:
if data == "日期":
new_headers.append("trade_date")
存擋的時候調整兩個部分:
def save_data_to_azure_db(symbol, tock_data)
convert_date(row.trade_date)
其中缺少了「年份」轉換的功能。我們需要把民國年轉成西元年
,用法是取得民國年,然後加上1911
。
def convert_date(data_ROC):
"""因為格式為109/1/1,為民國年,需轉換成西元年"""
date_arr = data_ROC.split("/")
new_year = int(date_arr[0]) + 1911
return f"{new_year}-{date_arr[1]}-{date_arr[2]}"
這樣就大功告成囉!