Python爬蟲:TWSE 臺灣證券交易所的每5秒大盤指數歷史數據

MinKuan
8 min readDec 18, 2021

--

使用pandas的read_html爬蟲和 matplotlib畫出5秒價格線圖

前言

今天將會分享如何使用python爬取證交所的大盤指數價格並畫出線圖。

在開始爬蟲時都要先研究 目標是誰?結構是甚麼?我要什麼資料?希望最後的資料長怎麼樣? 在腦中有些許畫面後,我們就可以開始了!!!
完整程式碼將在最下方

將學習到

· pandas的read_html抓取網站表格以及簡單的整理表格

· matplotlib畫出價格線圖以及簡易的外觀

環境設定

windows Anaconda的jupyter(6.0.3)

使用套件

import pandas as pd
from datetime import datetime,timedelta
import matplotlib.pyplot as plt

開始工作

步驟1:檢查目標

下圖是證交所公布的數據,它有提供”列印/HTML”(黃色標記處),請點開。

https://www.twse.com.tw/zh/page/trading/exchange/MI_5MINS_INDEX.html

點開後會發現就是一個完整的表格,這就是我們本篇的目標,將它爬取下來。注意網址(url)在後面有date=20211217,當輸入不同日期,就會切換到不同日的5秒報價了,如輸入20211215就會是2021年12月15日了。

https://www.twse.com.tw/exchangeReport/MI_5MINS_INDEX?response=html&date=20211217

步驟2:使用pandas爬取網站並整理

pandas的read_html非常的方便,當爬蟲發現目標網站有表格樣式的結構,可以多多利用read_html可以直接找到我們所需要的表格。

import pandas as pd
#目標網站
date = '20211122'
url ='https://www.twse.com.tw/exchangeReport/MI_5MINS_INDEX?response=html&date={0}'.format(date)
df = pd.read_html(url)
#確認有幾個表格
len(df)
#取得抓取到的表格
df = df[0]
df
初步印出df的樣子
只取得df[0]的樣子

上述其實就已經完成爬蟲的一大步驟了,但上面的數據並非我們想要的,我們想要的是乾淨有條理,只保留”發行量加權股價指數”和”時間”,因此將會整理爬取下來的資料。

#保留需要的欄位
df = df.iloc[:,:2]
df.columns = df.columns.get_level_values(1)#因為有兩個標頭,但只需要第1個
df.columns = ['time','price']#重新命名columns名子
#將日期加入資料中
df['date'] = date
df
保留時間、加權指數,以及新增日期
#想要將日期與時間結合
df[‘datetime’] = df[‘date’]+’ ‘+df[‘time’]
display(df)
成功完成1日5秒報價

透過上述的步驟可以簡易的將1日的5秒報價抓取下來,但我們在使用加權指數的時候都是需要一段時間的資料,因此接著我們就會用迴圈方式,將指定期間的報價抓取下來。要注意的是我們用了timedelta達成日期加1天,不過難以避免有遇到休假日,故使用了tryexcept,可以避免因為沒有表格而停止run。我們還用到了pd.concat,這是可以將陣列中多個的DataFrame疊加的指令,上述的套件指令將會附在最下面的參考資料。

import pandas as pd
from datetime import datetime,timedelta
tick=[] #儲存每日的5秒K#爬蟲起始日
start_date = '2021-12-06'
start_date_p = datetime.strptime(start_date,'%Y-%m-%d')
#爬蟲終止日
end_date = '2021-12-17'
end_date_p = datetime.strptime(end_date,'%Y-%m-%d')
while start_date_p <= end_date_p:
#當爬蟲有資料時
try:
#日期型態調整
start_date = datetime.strftime(start_date_p,'%Y-%m-%d')
date = start_date.replace('-','')

#爬取5秒K網站
url ='https://www.twse.com.tw/exchangeReport/MI_5MINS_INDEX?response=html&date={0}'.format(date)
df = pd.read_html(url)[0]

#資料整理
df = df.iloc[:,:2]
df.columns = df.columns.get_level_values(1)
df.columns = ['time','price']

#將日期加入columns
df['date'] = start_date

#秀出pandas表格
display(df.head(3))
print(url)

#將當日爬取的5秒K先加入陣列
tick.append(df)

#加1日到隔日
start_date_p += timedelta(1)

#當爬蟲無資料時
except:
print('pass',start_date_p)
#加1日到隔日
start_date_p += timedelta(1)
#將已經爬完的tick陣列合併成DataFrame
dfs = pd.concat(tick)
dfs['datetime'] = dfs['date'] +' '+ ['dfs.time']
display(dfs)
#將DataFrame輸出成csv檔
dfs.to_csv('tick.csv')
爬取20211206至20211217的報價並輸出至csv

步驟3:使用matplotlib畫圖

我們將上述所儲存的csv再讀取進來,將多餘的Unnamed: 0欄位去除,datetime欄位的格式也調整成"時間型態",可以有利於繪製線圖的速度。
除了有5秒的資料外,可以視覺化才能夠快速的分析,以下用了幾的基本的外觀設定,有關顏色參數、外觀設計街皆放在參考資料。

df = pd.read_csv(‘tick.csv’)# 讀取上面所存的csv
df.drop(columns=['Unnamed: 0'], inplace=True)# 發現多了'Unnamed: 0'這個欄位,因此清除它
df['datetime'] = pd.to_datetime(df['datetime'])# 將時間型態轉換成"時間型態"
import matplotlib.pyplot as pltfig, ax = plt.subplots()fig.set_size_inches(15, 4)# 設定圖片大小ax.set_facecolor('k')# 設定圖片背景顏色ax.plot(df['datetime'], df['price'], color='orange')# 要繪製的x軸、y軸數據以及線的顏色ax.grid(axis='x')# 設定x軸畫直線plt.xlabel('datetime')# 設定x軸的名稱plt.ylabel('price')# 設定y軸的名稱plt.title('5 second')# 設定圖的表頭名稱plt.savefig('5second.png')# 將圖片儲存plt.show()

完整程式碼

小結

寫完本篇除了是自己想要在學習路上作筆記外,同時也想分享給剛入坑的同學們,如果你對於以上的內容有建議歡迎提出,一起討論絕對是成長的捷徑!!

參考資料

pandas的dataframe合併:Merge, join, concatenate and compare

Python | datetime.timedelta() function

如何在 Pandas 中將 DataFrame 列轉換為日期時間

matplotlib color 参数

How to Change Background Color in Matplotlib (With Examples)

如何在 Matplotlib 中更改圖形大小及格式

--

--

MinKuan
MinKuan

No responses yet