2025年7月29日 星期二

台灣銀行 牌告匯率--Python TKInter

台灣銀行 牌告匯率--Python TKInter 




import tkinter as tk

from tkinter import ttk, messagebox

import requests

from bs4 import BeautifulSoup

import datetime


def fetch_exchange_rates():

    """

    從台灣銀行網站抓取即時匯率數據。

    """

    url = "https://rate.bot.com.tw/xrt?Lang=zh-TW"

    headers = {

        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'

    } # 加上 User-Agent 模擬瀏覽器請求,避免被網站阻擋


    try:

        response = requests.get(url, headers=headers)

        response.raise_for_status()  # 檢查 HTTP 請求是否成功

        soup = BeautifulSoup(response.text, 'html.parser')


        # 找到匯率表格

        exchange_table = soup.find('table', class_='table-bordered')


        if not exchange_table:

            messagebox.showerror("解析錯誤", "無法找到匯率表格。網站結構可能已改變。")

            return None


        rates_data = []

        # 遍歷表格的每一行 (從第二行開始,因為第一行是表頭)

        # 注意:使用 tbody 可以確保我們只處理數據行

        for row in exchange_table.find('tbody').find_all('tr'):

            cols = row.find_all('td')

            if len(cols) >= 6: # 確保有足夠的欄位來包含所有匯率類型 (通常是 6 個 td)

                currency_name = cols[0].find('div', class_='print_show').text.strip()

                # 移除幣別名稱中的換行符和多餘空格

                currency_name = currency_name.replace('\n', ' ').strip()

                currency_name = ' '.join(currency_name.split()) # 將多個空格替換為單一空格


                # 現金匯率

                cash_buy_rate = cols[1].text.strip() # 現金買入

                cash_sell_rate = cols[2].text.strip() # 現金賣出


                # 即期匯率

                spot_buy_rate = cols[3].text.strip() # 即期買入

                spot_sell_rate = cols[4].text.strip() # 即期賣出


                # 過濾掉沒有匯率的項目 (例如 "-" )

                if (cash_buy_rate != '-' and cash_sell_rate != '-') or \

                   (spot_buy_rate != '-' and spot_sell_rate != '-'):

                    rates_data.append({

                        'currency': currency_name,

                        'cash_buy': cash_buy_rate,

                        'cash_sell': cash_sell_rate,

                        'spot_buy': spot_buy_rate,

                        'spot_sell': spot_sell_rate

                    })

        return rates_data


    except requests.exceptions.RequestException as e:

        messagebox.showerror("網路錯誤", f"無法連接到台灣銀行網站:{e}")

        return None

    except Exception as e:

        messagebox.showerror("擷取錯誤", f"處理網頁資料時發生錯誤:{e}")

        return None


def update_exchange_display():

    """

    擷取匯率數據並更新 Tkinter 介面。

    """

    current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    status_label.config(text=f"最後更新時間: {current_time} - 擷取中...")

    root.update_idletasks() # 強制更新 GUI 以顯示訊息


    rates = fetch_exchange_rates()

    if rates:

        # 清除舊數據

        for item in tree.get_children():

            tree.delete(item)


        # 插入新數據

        for rate in rates:

            tree.insert('', tk.END, values=(

                rate['currency'],

                rate['cash_buy'],

                rate['cash_sell'],

                rate['spot_buy'],

                rate['spot_sell']

            ))

        status_label.config(text=f"最後更新時間: {current_time} - 數據已更新")

    else:

        # 如果沒有抓到數據,顯示錯誤訊息

        for item in tree.get_children():

            tree.delete(item)

        tree.insert('', tk.END, values=("未能載入匯率資料,請檢查網路或網站結構", "", "", "", ""))

        status_label.config(text=f"最後更新時間: {current_time} - 數據載入失敗")

    

    # 每 5 分鐘自動更新 (300000 毫秒)

    root.after(300000, update_exchange_display)



# --- Tkinter 介面設定 ---

root = tk.Tk()

root.title("台灣銀行即時牌告匯率")

root.geometry("800x750") # 調整視窗大小以容納更多欄位


# 框架用於容納 Treeview 和捲軸

frame = tk.Frame(root, padx=10, pady=10)

frame.pack(expand=True, fill="both")


# 創建 Treeview 來顯示表格數據

columns = ('currency', 'cash_buy', 'cash_sell', 'spot_buy', 'spot_sell')

tree = ttk.Treeview(frame, columns=columns, show='headings')


# 設定欄位標題

tree.heading('currency', text='幣別')

tree.heading('cash_buy', text='現金買入')

tree.heading('cash_sell', text='現金賣出')

tree.heading('spot_buy', text='即期買入')

tree.heading('spot_sell', text='即期賣出')


# 設定欄位寬度

tree.column('currency', width=150, anchor='center')

tree.column('cash_buy', width=120, anchor='center')

tree.column('cash_sell', width=120, anchor='center')

tree.column('spot_buy', width=120, anchor='center')

tree.column('spot_sell', width=120, anchor='center')


# 添加捲軸

scrollbar = ttk.Scrollbar(frame, orient="vertical", command=tree.yview)

tree.configure(yscrollcommand=scrollbar.set)

scrollbar.pack(side="right", fill="y")


tree.pack(expand=True, fill="both")


# 狀態標籤,顯示最後更新時間和狀態

status_label = tk.Label(root, text="準備載入匯率...", font=("Arial", 10), anchor="w")

status_label.pack(side="bottom", fill="x", padx=10, pady=5)


# 更新按鈕

update_button = tk.Button(root, text="手動更新匯率", command=update_exchange_display, font=("Arial", 12))

update_button.pack(pady=10)


# 初始化顯示匯率

update_exchange_display()


root.mainloop()


沒有留言:

張貼留言

ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite

 ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite  ESP32 VS Code 程式 ; PlatformIO Project Configuration File ; ;   Build op...