Python - Download Taiwan Stock Data With TWSE Open 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,可以參考〈在網頁上發佈動態資料圖表 – 方案評估與技術問題全記錄〉



    推薦文章

    Aron

    工業設計系畢業,曾任職知名品牌行銷企劃,做點設計,寫文案也寫網站;目前擔任零售業數據分析師。最近開始研究Python量化投資和虛擬貨幣。

    facebook telegram
    Content Protection by DMCA.com

    7 則留言

    1. 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’

    2. 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

    3. Egbert

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

      1. Aron

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

        r.encoding = ‘utf-8’

    發佈回覆給「King」的留言 取消回覆

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

    發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *