Python – 透過證交所API抓取台股歷史資料

Python – 透過證交所開放資料API抓取台股當日交易資訊

目錄

    原始文章

    Python – 透過證交所開放資料API抓取台股當日交易資訊


    個股日成交資訊

    證交所在政府開放資料平台上提供了一個資料集個股日成交資訊這裡面的資料會每日更新,並且只保留最新的資料。如果你想抓歷史股價資料,可以參考另一篇文章〈使用Python及Yahoo Finance API抓取台股歷史資料〉

    資料格式

    在這個資料集中,雖然它標示的檔案格式是csv,但我用Python的request套件抓下來後,發現它的資料結構很像json。我不是很了解這兩種格式之間的轉換邏輯,總之我後來順利使用json的方式成功處理,並轉成pandas的dataframe。

    Python - 透過證交所開放資料API抓取台股當日交易資訊

    不要抓錯網址

    點擊「檢視資料」按鈕後,會跳出彈出式視窗,注意你要抓的網址是上面的「資料下載網址」,而不是下面「點此下載」的連結,不要看到json格式就開心複製,結果抓了好幾天的資料,卻發現價錢怎麼都一樣。即使網頁上已加註了提醒文字如下,但我也曾經當過那個笨蛋。

    以下連結為本平臺協助提供多元格式參考資料 (轉檔時間:2021-06-02 11:55:44), 非即時資料, 完整資料請以機關 原始連結 為主。

    直接點擊「資料下載網址」的話,瀏覽器會自動下載一個csv檔,建議跟看盤軟體比較一下當日股價是否一致。

    完整程式碼

    import requests
    import pandas as pd
    import numpy as np
    import datetime
    def conv_to_list(obj):
        '''
        將物件轉換為list
        '''
        if not isinstance(obj, list) :
            results = [obj]
        else:
            results = obj
        return results
    
    def df_conv_col_type(df, cols, to, ignore=False):
        '''
        一次轉換多個欄位的dtype
        '''
        cols = conv_to_list(cols)
        for i in range(len(cols)):
            if ignore :
                try:
                    df[cols[i]] = df[cols[i]].astype(to)
                except:
                    print('df_conv_col_type - ' + cols[i] + '轉換錯誤')
                    continue
            else:
                df[cols[i]] = df[cols[i]].astype(to)
        return df
    
    def date_get_today(with_time=False):
        '''
        取得今日日期,並指定為台北時區
        '''
        import pytz
        central = pytz.timezone('Asia/Taipei')
        
        if with_time == True:
            now = datetime.datetime.now(central)
        else:
            now = datetime.datetime.now(central).date()
        return now
    
    # 下載證交所資料 ------
    link = 'https://www.twse.com.tw/exchangeReport/STOCK_DAY_ALL?response=open_data'
    data = pd.read_csv(link)
    # ['證券代號', '證券名稱', '成交股數', '成交金額', '開盤價',
    #  '最高價', '最低價', '收盤價', '漲跌價差', '成交筆數']
    data.columns = ['STOCK_SYMBOL', 'NAME', 'TRADE_VOLUME', 'TRADE_VALUE', 
                    'OPEN', 'HIGH' ,'LOW', 'CLOSE', 'PRICE_CHANGE', 'TRANSACTION']   
    # 標註今日日期
    data['WORK_DATE'] = date_get_today()
    cols = data.columns.tolist()
    cols = cols[-1:] + cols[:-1]
    data = data[cols]
    # 除了證券代號外,其他欄位都是str,且部份資料中有''
    data = data.replace('', np.nan, regex=True)
    # 將data type轉為float
    data = df_conv_col_type(df=data, 
                            cols=['VOLUME', 'TRADE_VALUE', 'OPEN', 'HIGH' ,'LOW',
                                  'CLOSE', 'PRICE_CHANGE', 'TRANSACTION'],
                            to='float')

    台股歷史股價與趨勢預測

    〈台股歷史股價與趨勢預測〉就是從Yahoo Finance抓取歷史資料,並透過證交所API每日更新。實際佈署方式是使用PythonAnyWhere和Plotly,可以參考〈在網頁上發佈動態資料圖表 – 方案評估與技術問題全記錄〉

    20230116更新

    比起證交所的開放資料或Yahoo Finance API,我發現另外一個更優質的資料來源 ─ 富果Fugle,請參考〈使用Python與富果API下載台股歷史資料〉



    推薦文章

    Aron

    搭載商業思維的資料科學家,工業設計系畢業,曾任職知名品牌行銷企劃。下班後寫機器學習模型,寫網站,也寫文章。興趣是把Side Project當成創業題目來玩,把人生當成遊戲破關。

    facebook telegram

    推薦書單

    好懂秒懂的財務思維課
    好懂秒懂的財務思維課 ⭐⭐⭐⭐
    器識
    器識 ⭐⭐⭐⭐⭐
    研究生完全求生手冊:方法、秘訣、潛規則
    研究生完全求生手冊:方法、秘訣、潛規則 ⭐⭐⭐⭐⭐
    蘭亭序密碼 (裴玄靜系列 1)
    蘭亭序密碼 (裴玄靜系列 1) ⭐⭐⭐⭐⭐

    8 則留言

    1. 李先生

      要成立指數期貨操盤室、需要專用电腦看盤軟體、請問有那些廠商可報價.

    2. LUWM

      您好有一問題請教,
      依您上述建議下載資料程式碼,

      仍有錯誤訊息, 如下:
      PS C:\Python\Python396> & C:/Python/Python396/python.exe c:/Python/Python396/daystock.py
      Traceback (most recent call last):
      File “c:\Python\Python396\daystock.py”, line 64, in
      data = data.replace(”, np.nan, regex=True)
      NameError: name ‘np’ is not defined

      不知要如何修改呢?

      1. Aron

        是我少寫了一行,沒有匯入numpy,只要加上下面這一行應該就可以囉。
        import numpy as np

      2. LUWM

        初學者請多包涵.

        我加了一行import numpy as np, 就出現以下資訊:

        Traceback (most recent call last):
        File “C:\Python\Python396\lib\site-packages\pandas\core\indexes\base.py”, line 3361, in get_loc
        return self._engine.get_loc(casted_key)
        File “pandas\_libs\index.pyx”, line 76, in pandas._libs.index.IndexEngine.get_loc
        File “pandas\_libs\index.pyx”, line 108, in pandas._libs.index.IndexEngine.get_loc
        File “pandas\_libs\hashtable_class_helper.pxi”, line 5198, in pandas._libs.hashtable.PyObjectHashTable.get_item
        File “pandas\_libs\hashtable_class_helper.pxi”, line 5206, in pandas._libs.hashtable.PyObjectHashTable.get_item
        KeyError: ‘VOLUME’

        The above exception was the direct cause of the following exception:

        Traceback (most recent call last):
        File “c:\Python\Python396\daystock.py”, line 68, in
        data = df_conv_col_type(df=data,
        File “c:\Python\Python396\daystock.py”, line 31, in df_conv_col_type
        df[cols[i]] = df[cols[i]].astype(to)
        File “C:\Python\Python396\lib\site-packages\pandas\core\frame.py”, line 3455, in __getitem__
        indexer = self.columns.get_loc(key)
        File “C:\Python\Python396\lib\site-packages\pandas\core\indexes\base.py”, line 3363, in get_loc
        raise KeyError(key) from err
        KeyError: ‘VOLUME’

    3. King

      https://bsr.twse.com.tw/bshtm/
      請問這個分點資訊,您有找到不用驗證碼的API可以下載嗎?

      1. Aron

        我沒有找到其他類似的資料源,但如果你是用Python的話,可以試試看用OpenCV的方式辨識驗證碼的文字,但就有會有一些技術工作要做,搜尋python recognize captcha之類的關鍵字應該就會有了。以下是我找到的兩篇內容,讓你參考。

        Decoding captchas using Python
        Bypass Captcha using 10 lines of code with Python, OpenCV & Tesseract OCR engine

    4. Egbert

      您好,想請問您在政府開放資料平台上抓取的個股日成交資訊是否也會有亂碼跟錯位的問題?

      1. Aron

        我抓下來是正常的,或是你可以在requests後面加上下面這一行試試看。

        r.encoding = ‘utf-8’

    發佈留言

    • * 表示必填欄位
    • 您填寫的電子郵件不會被公開
    • 請確認您的電子郵件正確無誤,當您的留言收到新的回覆時,我們會寄送通知信件給您

    發佈留言必須填寫的電子郵件地址不會公開。