今天是第九天!前面八天我們已經在不知不覺中做了好多東西耶,昨天我們已經能收到文字警報了,但看股票如果能「看圖」,視覺上會直觀非常多。
Telegram API 不只支援傳送純文字,還支援傳送圖片。今天我們就來學習如何用 Python 把本地端產生的 kline.png 圖片,自動打包上傳到 Telegram!
步驟一:解釋程式碼邏輯
如果用 Python 內建的 urllib 來寫 sendPhoto 檔案上傳,需要手動寫非常複雜的表單標頭(Header)編碼。
為了維持程式碼的簡潔與新手友好的原則,今天我們要引入一個 Python 界的熱門第三方套件——requests!
還是老樣子,記得在終端機前面檢查有沒有(venv)。
步驟二:安裝第三方套件 requests
requests 是 Python 最經典的網路請求工具,處理檔案上傳只需要短短幾行程式碼。
接下來,請在 VS Code 終端機輸入以下命令安裝:
pip install requests
會長下面這樣!
步驟三:撰寫「繪圖與多媒體發送」完整程式碼
今天我們會用到 Telegram 的 sendPhoto API,用來發送 local 儲存好的圖片檔案。
請打開 main.py,照著下面的完整程式碼寫(記得把 Token 和 Chat ID 換成你自己的喔!):
import pandas as pd
import yfinance as yf
import mplfinance as mpf
import urllib.request
import urllib.parse
import json
# 1. 通訊金鑰
TOKEN = "你的_BOT_TOKEN"
CHAT_ID = "你的_CHAT_ID"
# 2. 抓取股票資料
print(" 正在下載股票資料並繪製 K 線圖...")
df = yf.download("2330.TW", period="6mo")
# 防呆檢查
if df.empty:
print(" 錯誤:無法下載股票資料,請檢查網路或股票代碼!")
exit()
# 清理 yfinance 多層索引
if isinstance(df.columns, pd.MultiIndex):
df.columns = df.columns.get_level_values(0)
# 計算 5MA 與 20MA
df['MA5'] = df['Close'].rolling(window=5).mean()
df['MA20'] = df['Close'].rolling(window=20).mean()
# 取最近 60 天的資料來畫圖
df_plot = df.tail(60).copy()
# 3. 設定 K 線圖樣式並存檔
ap = [
mpf.make_addplot(df_plot['MA5'], color='orange', width=1.5),
mpf.make_addplot(df_plot['MA20'], color='blue', width=1.5)
]
mpf.plot(
df_plot,
type='candle',
volume=True,
addplot=ap,
title="2330.TW 60-Day K-Line Chart",
savefig='stock_chart.png'
)
print(" K 線圖已順利繪製並存檔為 stock_chart.png!")
# 4. 判斷最新一天訊號作為圖片文字說明 (Caption)
latest = df.iloc[-1]
prev = df.iloc[-2]
caption_text = f" 【2330 台積電 最新盤後分析】\n"
caption_text += f" 日期:{df.index[-1].strftime('%Y-%m-%d')}\n"
caption_text += f" 收盤價:{latest['Close']:.2f}\n"
if prev['MA5'] <= prev['MA20'] and latest['MA5'] > latest['MA20']:
caption_text += " 訊號:【黃金交叉】5MA 向上突破 20MA,多頭轉強!"
elif prev['MA5'] >= prev['MA20'] and latest['MA5'] < latest['MA20']:
caption_text += " 訊號:【死亡交叉】5MA 向下跌破 20MA,注意風險!"
else:
caption_text += "橫盤整理中,尚未出現重大交叉訊號。"
# 5. 發送圖片與說明文字給 Telegram (修正編碼問題的版本)
print(" 正在發送圖片到 Telegram...")
url = f"https://api.telegram.org/bot{TOKEN}/sendPhoto"
boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'
# 讀取圖片檔案
with open('stock_chart.png', 'rb') as f:
photo_data = f.read()
# 嚴格將所有欄位轉為 bytes 並使用 utf-8 編碼
parts = [
f'--{boundary}\r\nContent-Disposition: form-data; name="chat_id"\r\n\r\n{CHAT_ID}\r\n'.encode('utf-8'),
f'--{boundary}\r\nContent-Disposition: form-data; name="caption"\r\n\r\n{caption_text}\r\n'.encode('utf-8'),
f'--{boundary}\r\nContent-Disposition: form-data; name="photo"; filename="stock_chart.png"\r\nContent-Type: image/png\r\n\r\n'.encode('utf-8') + photo_data + b'\r\n',
f'--{boundary}--\r\n'.encode('utf-8')
]
payload = b''.join(parts)
headers = {
'Content-Type': f'multipart/form-data; boundary={boundary}'
}
try:
req = urllib.request.Request(url, data=payload, headers=headers)
with urllib.request.urlopen(req) as response:
print(" 成功發送 K 線圖與分析訊息到 Telegram!")
except Exception as e:
print(f" 發送失敗,錯誤訊息:{e}")
步驟四:執行程式與成果確認
python main.py
最後長這樣!
小結一下:
今天我們不僅學會了用 mplfinance 畫出專業的台股 K 線圖,還打通了發送圖片與多媒體訊息到 Telegram 的管道!
現在我們的機器人已經有模有樣了,但每次都要自己手動按 python main.py 還是有點麻煩。
明天就是第十天的最後總結與升級預告!我們要把這整套工具佈署成自動化腳本,讓它每天台股開盤/收盤時自動發送最新盤後圖表與訊號到你手機,真正實現「打造個人專屬台股自動看盤小幫手」!