iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 9
2
Software Development

Python 程式交易 30 天新手入門系列 第 9

Day-09 資料蒐集:取得個股當日基本資訊 + 解析 PDF

安裝所需套件

使用 pip 安裝

# PDF 表格解析
pip install opencv-python camelot-py

下載 GhostScript 9.27 (Win32) 並安裝
https://www.ghostscript.com/download/gsdnld.html

解析 PDF 表格

以取得個股當日基本資訊為例。

分析資料結構

https://www.twse.com.tw/pdf/ch/1101_ch.pdf
個股當日基本資訊

  1. 基本資訊內容位於第 1 表格。
  2. 但欄位標頭並非位於第 1 行,而是第 1 欄。

下載資料並解析出個股當日基本資訊

import ctypes
import datetime
import os

import camelot
import camelot.ext.ghostscript._gsprint
import loguru
import requests

# 因為 camelot 0.7.3 尚未修正 win32/win64 呼叫函式的格式問題(GitHub 上的
# master 分支已修正),故要覆寫 camelot 內呼叫 GhostScript API 的定義格式
camelot.ext.ghostscript._gsprint.c_stdstream_call_t = ctypes.WINFUNCTYPE(
    ctypes.c_int,
    camelot.ext.ghostscript._gsprint.gs_main_instance,
    ctypes.POINTER(ctypes.c_char),
    ctypes.c_int
)

def main(code):
    resp = requests.get(f'https://www.twse.com.tw/pdf/ch/{code}_ch.pdf')
    if resp.status_code != 200:
        loguru.logger.error('RESP: status code is not 200')
    loguru.logger.success('RESP: success')

    filename = f'{code}.pdf'
    filepath = f'{filename}'

    with open(filepath, 'wb') as f:
        f.write(resp.content)

    # 透過 camelot 辨識出 PDF 檔案內的表格
    tables = camelot.read_pdf(filepath)
    # 印出第 1 表格的 DataFrame
    print(tables[0].df)

if __name__ == '__main__':
    loguru.logger.add(
        f'{datetime.date.today():%Y%m%d}.log',
        rotation='1 day',
        retention='7 days',
        level='DEBUG'
    )
    # 傳入股票代碼
    main('1101')

執行結果
如果需要實收資本額,可以知道位於第 0 欄第 3 行

import ctypes
import datetime
import os

import camelot
import camelot.ext.ghostscript._gsprint
import loguru
import requests

camelot.ext.ghostscript._gsprint.c_stdstream_call_t = ctypes.WINFUNCTYPE(
    ctypes.c_int,
    camelot.ext.ghostscript._gsprint.gs_main_instance,
    ctypes.POINTER(ctypes.c_char),
    ctypes.c_int
)

def main(code):
    resp = requests.get(f'https://www.twse.com.tw/pdf/ch/{code}_ch.pdf')
    if resp.status_code != 200:
        loguru.logger.error('RESP: status code is not 200')
    loguru.logger.success('RESP: success')

    filename = f'{code}.pdf'
    filepath = f'{filename}'

    with open(filepath, 'wb') as f:
        f.write(resp.content)

    # 透過 camelot 辨識出 PDF 檔案內的表格
    tables = camelot.read_pdf(filepath)
    loguru.logger.info('DataFrame' + os.linesep + repr(tables[0].df))

    # 取出第 1 表格的 DataFrame 中的實收資本額
    paidin = tables[0].df[0][3]
    paidin.replace('新台幣', '').replace(',', '').strip()
    loguru.logger.info(f'實收資本額 {paidin}')

if __name__ == '__main__':
    loguru.logger.add(
        f'{datetime.date.today():%Y%m%d}.log',
        rotation='1 day',
        retention='7 days',
        level='DEBUG'
    )
    # 傳入股票代碼
    main('1101')

重新執行得到輸出結果。
執行結果

Would You Like To Know More?

https://camelot-py.readthedocs.io/


團隊系列文:

CSScoke - 金魚都能懂的這個網頁畫面怎麼切 - 金魚都能懂了你還怕學不會嗎
Clarence - LINE bot 好好玩 30 天玩轉 LINE API
Hina Hina - 陣列大亂鬥
King Tzeng - IoT沒那麼難!新手用JavaScript入門做自己的玩具
Vita Ora - 好 Js 不學嗎 !? JavaScript 入門中的入門。
TaTaMo - 用Python開發的網頁不能放到Github上?Lektor說可以!!


上一篇
Day-08 資料蒐集:取得個股每月各交易日盤後資訊 + 解析 CSV
下一篇
Day-10 資料保存:使用 MySQL 資料庫
系列文
Python 程式交易 30 天新手入門30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言