2026年7月4日 星期六

在樹莓派 Pi 400 (Trixie) 虛擬環境中佈署市圖爬蟲程式 (v14)

這兩天利用 Antigravity CLI 搞定市圖爬蟲程式 v14 升版後, 陸續佈署到 kaopi3 與 pi3aplus 主機上且順利運行中, 今天輪到 Pi 400 主機了, 有別於 Pi 3 主機直接在系統 Python 3.9.2 上執行 Python 程式, 我目前在 Pi 400 安裝的樹莓派 OS 是最新的 Trixie (內建 Python 3.13), 遵循 PEP 668 規範不允許直接在系統 Python 環境用 pip 安裝第三方套件 (從 Bookworm 開始), 必須建立虛擬環境後在虛擬環境裡面用 pip 安裝套件. 

目前 Pi 400 的爬蟲是在虛擬環境 myenv313 下執行, 所以先進入此虛擬環境 : 

pi@pi400:~ $ source ~/myenv313/bin/activate   
(myenv313) pi@pi400:~ $

因為之前就已在此環境下安裝 Numpy 時安裝過 OpenBLAS 及相關的底層依賴庫, 所以下面指令可以略過 :

sudo apt-get update
sudo apt update sudo apt install -y libopenblas-dev libatlas-base-dev 

接下來安裝 tesseract-ocr 套件 : 

(myenv313) pi@pi400:~ $ sudo apt-get install tesseract-ocr   
正在讀取套件清單... 完成
正在重建相依關係... 完成  
正在讀取狀態資料... 完成  
The following packages were automatically installed and are no longer required:
  alacarte gir1.2-gmenu-3.0 gnome-menus gtk-nop libevent-pthreads-2.1-7t64 libgnome-menu-3-0
  libwlroots-0.18 python3-gi-cairo retry
Use 'sudo apt autoremove' to remove them.
下列的額外套件將被安裝:
  libleptonica6 libtesseract5 tesseract-ocr-eng tesseract-ocr-osd
下列【新】套件將會被安裝:
  libleptonica6 libtesseract5 tesseract-ocr tesseract-ocr-eng tesseract-ocr-osd
升級 0 個,新安裝 5 個,移除 0 個,有 261 個未被升級。
需要下載 7,207 kB 的套件檔。
此操作完成之後,會多佔用 24.5 MB 的磁碟空間。
是否繼續進行 [Y/n]? [Y/n] y
下載:1 http://deb.debian.org/debian trixie/main arm64 libleptonica6 arm64 1.84.1-4 [994 kB]
下載:2 http://deb.debian.org/debian trixie/main arm64 libtesseract5 arm64 5.5.0-1+b1 [1,237 kB]
下載:3 http://deb.debian.org/debian trixie/main arm64 tesseract-ocr-eng all 1:4.1.0-2 [1,594 kB]
下載:4 http://deb.debian.org/debian trixie/main arm64 tesseract-ocr-osd all 1:4.1.0-2 [2,992 kB]
下載:5 http://deb.debian.org/debian trixie/main arm64 tesseract-ocr arm64 5.5.0-1+b1 [389 kB]
取得 7,207 kB 用了 3s (2,122 kB/s)      
選取了原先未選的套件 libleptonica6:arm64。
(讀取資料庫 ... 目前共安裝了 147525 個檔案和目錄。)
正在準備解包 .../libleptonica6_1.84.1-4_arm64.deb……
Unpacking libleptonica6:arm64 (1.84.1-4) ...
選取了原先未選的套件 libtesseract5:arm64。
正在準備解包 .../libtesseract5_5.5.0-1+b1_arm64.deb……
Unpacking libtesseract5:arm64 (5.5.0-1+b1) ...
選取了原先未選的套件 tesseract-ocr-eng。
正在準備解包 .../tesseract-ocr-eng_1%3a4.1.0-2_all.deb……
Unpacking tesseract-ocr-eng (1:4.1.0-2) ...
選取了原先未選的套件 tesseract-ocr-osd。
正在準備解包 .../tesseract-ocr-osd_1%3a4.1.0-2_all.deb……
Unpacking tesseract-ocr-osd (1:4.1.0-2) ...
選取了原先未選的套件 tesseract-ocr。
正在準備解包 .../tesseract-ocr_5.5.0-1+b1_arm64.deb……
Unpacking tesseract-ocr (5.5.0-1+b1) ...
設定 libleptonica6:arm64 (1.84.1-4) ...
設定 tesseract-ocr-eng (1:4.1.0-2) ...
設定 libtesseract5:arm64 (5.5.0-1+b1) ...
設定 tesseract-ocr-osd (1:4.1.0-2) ...
設定 tesseract-ocr (5.5.0-1+b1) ...
執行 man-db (2.13.1-1) 的觸發程式……
執行 libc-bin (2.41-12+rpt1+deb13u2) 的觸發程式……

最後安裝 pytesseract 與 Pillow 套件 :

(myenv313) pi@pi400:~ $ pip install pytesseract Pillow   
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting pytesseract
  Downloading https://www.piwheels.org/simple/pytesseract/pytesseract-0.3.13-py3-none-any.whl.metadata (11 kB)
Requirement already satisfied: Pillow in ./myenv313/lib/python3.13/site-packages (11.3.0)
Requirement already satisfied: packaging>=21.3 in ./myenv313/lib/python3.13/site-packages (from pytesseract) (25.0)
Downloading https://www.piwheels.org/simple/pytesseract/pytesseract-0.3.13-py3-none-any.whl (14 kB)
Installing collected packages: pytesseract
Successfully installed pytesseract-0.3.13

至此執行新版爬蟲所需的套件都齊了, 測試一下 :

(myenv313) pi@pi400:~ $ python ksml_lib_14.py abc 123456
主機 : pi400
[嘗試 1/3] 驗證碼辨識結果: 0003
[嘗試 1/3] 登入失敗,準備重試...
[嘗試 2/3] 驗證碼辨識結果: 43504
登入成功(第 2 次嘗試)
擷取借閱紀錄 ... OK
擷取預約紀錄 ... OK
資源已釋放
產生借書到期摘要 ... OK
產生預約書摘要 ... OK
{'message': abc 的資料已更新', 'status': 'success'}
執行時間:61.67458128929138

爬蟲程式可以順利執行. 這樣就可以為爬蟲程式添加可執行權限 :

pi@pi400:~ $ chmod +x ksml_lib_14.py   

由於 Pi 400 主要做為支援 pi3aplus 主機的爬蟲任務之用, 所以它所綁定的後端 render.com 伺服器為 fdof, 用 nano 修改 ksml_lib_14.py 中的網址 : 

    # --- 推送資料 ---
    if b_msg or r_msg:  # 任一不為空字串就更新資料表
        url = "https://serverless-fdof.onrender.com/function/update_ksml_books"
        payload = {
            "account": account,
            "borrow_books": b_msg,
            "reserve_books": r_msg
        }
        res = requests.post(url, json=payload)
        print(res.json())

另外, 從 render.com 截取資料的程式 get_ksml_books_messages.py 也是綁定 fdof : 

# get_ksml_books_messages.py
import requests
import socket

host_name=socket.gethostname()
print(f'主機 : {host_name}')
params={'crawler': f'{host_name}'}
# for kaopi3
# url='https://serverless-5e6i.onrender.com/function/send_books_messages'
# for pi3aplus & pi400 (備援)
url='https://serverless-fdof.onrender.com/function/send_books_messages'
res=requests.get(url, params=params)
print(res)

最後把 crontab 中的爬蟲程式由 v13 改成 v14 即可 (雖然目前都被註解掉未執行). 

如何擷取電腦上一抓就消失的畫面

有些 PC 上的電腦畫面無法用 Picpick 抓圖, 這時就需要用到延時截取工具, Win11 本身內建的剪取工具就派上用場了, 按 Win + S 搜尋 "剪取工具" 開啟此軟體 (或直接按 Win +Shift + S), 點右上方的時鐘按鈕, 勾選延遲時間 (為了有較長操作時間可選 10 秒), 然後按左上角的新增鈕, 這時就會倒數計時所選的延遲秒數, 要趁此空檔打開想抓取的電腦畫面, 等倒數結束, 電腦螢幕會變暗, 這時就可按滑鼠左鍵拉曳要截取的部分, 放開就會進行截取 : 




所截取的圖會放在 "文件/圖片/螢幕擷取畫面" 下面. 

DW100pro+ 手表手機的 WiFi 無線基地台連線方法

之前原本買給爸的 DW100pro+ 手錶因為他不習慣帶電子錶只好拿來自用, 使用幾個月下來覺得還蠻方便的, 尤其我每天需透過手機的小米 App 連線遍布鄉下老家裡裡外外的監視器確定爸的位置, 以便決定是打市內電話/手機, 還是直接透過監視器通話, 提醒他社區車子快來了要做好準備, 或者藥吃了沒有等等, 這時一邊看手機監視器畫面, 一邊撥打手錶手機電話就很方便. 另外設定與我的 S24U 手機同振, 去上廁所也不會漏接重要電話. 

DW100pro+ 手錶目前門號月租 150 元, 每月有 2GB 網路用量, 通常用不完, 就想說慢速下載檔案時也可以拿來利用, 但今天打開 DW100+pro 手錶熱點, 設定連線密碼後, 用 LG 筆電連線 DW100pro+ 手錶的熱點, 輸入密碼卻一直顯示需輸入 4 或 8 碼數字的 PIN 碼, 但我設置的熱點密碼含有英文字母啊! 一直卡在這邊. 問了 Gemini 才知是輸入密碼的地方不正確. 

點擊筆電右下角的 Wi-Fi 清單按鈕 (電波符號), 點選手錶熱點 DW100pro+, 當跳出提示輸入 4 或 8 碼 PIN 碼時, 不要輸入, 在 PIN 輸入框的下方有一個 "改用密碼連線" 連結, 按此連結會顯示一個輸入密碼的輸入框, 這才是輸入熱點密碼的地方 : 




輸入手錶的熱點密碼按下一步就能順利連線了 :



Python 學習筆記 : 市圖借書與預約爬蟲程式改版 v14

由於 6/18 市圖網站登入網頁改版, 加上了數字圖片驗證碼功能, v13 的爬蟲程式立馬崩潰無法登入帳戶擷取借閱與預約資訊, 整個六月又在忙著復原 MSI 電競桌機, 所以爬蟲改版事宜只好擺著, 直到今天才動手, 這次我使用剛上手的 Antigravity CLI 來重構舊版程式, 加上 OCR 圖形辨識功能, 選擇 Claude Sonnet 模型來規劃與實作, 參考 :


原始碼放在 GitHub :


但因為新版程式辨識驗證碼需要用到 Numpy 與其底層依賴庫, 必須安裝 OpenBLAS 與 tesseract-ocr 等套件, 這樣  ksml_lib_14.py 才能順利在 Pi 3 與 Pi 3A+ 上執行. 

# 更新套件清單
sudo apt-get update

# 安裝 OpenBLAS 及其相關的底層依賴庫
sudo apt update sudo apt install -y libopenblas-dev libatlas-base-dev

# 安裝 tesseract-ocr 套件 :
sudo apt-get install tesseract-ocr

# 安裝 pytesseract 與 Pillow 套件 : 
pip install pytesseract Pillow

# 把 ksml_lib_14.py 傳送到樹莓派後, 先用 chmod 添加可執行權限 :
chmod +x ksml_lib_14.py

# 修改 ksml_lib_14.py 中的 render.com 網址
# kaopi3 -> 5e6i 
# pi3aplus -> fdof 
# pi400 -> fdof (備用) 
nano ksml_lib_14.py

# 測試程式功能是否正常 :
python  ksml_lib_14.py <username> <password> 

# 更改 crontab 設定, 把 ksml_lib_13.py 改成 ksml_lib_14.py
crontab -e 

2026年7月3日 星期五

高科大還書 2 本 : Python資料可視化攻略 + LLM核心攻略制霸生成式AI

因有兩本預約書已到館, 中午拿下面兩本去換 : 
No.1 沒時間看, No.2 市圖可借. 炎夏的中午真是熱爆. 

Google Antigravity 學習筆記 : 重構市圖網站爬蟲

經過前面的 todo list 專案練習後, 我已大致熟悉 agy 的用法了, 本篇要先來解決一個實務問題. 我之前手刻的市圖爬蟲程式在 6/18 早上突然失靈了, 檢視市圖網站才知道登入頁面多了一個數字驗證碼輸入欄位, 需判讀數字輸入正確號碼才能登入成功. 



爬蟲停擺兩周了, 如果還是要手刻來解決恐怕曠日廢時, 這次要改用 agy 來升版. 


首先在 projects 下建立專案目錄 : 

PS D:\antigravity_cli\projects> mkdir ksml-clawler 
PS D:\antigravity_cli\projects> cd ksml-clawler  

然後將之前的爬蟲程式 ksml_lib_13.py 與從市圖網站抓下來的登入頁面截圖 jpg 檔 ksml_login.jpg 複製到專案目錄底下 :

PS D:\antigravity_cli\projects\ksml-crawler> dir  
    目錄: D:\antigravity_cli\projects\ksml-crawler
Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        2026/6/5  上午 12:43           8858 ksml_lib_13.py  (舊版爬蟲)
-a----       2026/6/27  上午 01:13         240936 ksml_login.jpg  (新登入頁面截圖)

接著啟動 agy :

PS D:\antigravity_cli\projects\ksml-clawler> agy

輸入下列提示詞 : 

這個現有的圖書館爬蟲程式因為網站最近在登入頁面加入了「數字圖形驗證碼」,導致舊的 Selenium 程式無法順利登入。

我已經把現有的爬蟲程式 `ksml_lib_13.py` 與登入頁面的實體截圖 `ksml_login.jpg` 放在當前目錄下了。

專案目標:
- 目標網址:https://webpacx.ksml.edu.tw/personal/
- 核心任務:只修改「登入功能」,使其能夠成功處理數字圖形驗證碼,其餘資料擷取邏輯保持不變

重構方向提示:
在 Python 中引入輕量級的 OCR 套件(例如 pytesseract 或 ddddocr),自動對驗證碼圖片進行局部截圖與辨識後自動輸入。
如果 OCR 辨識失敗導致登入錯誤,請讓程式具備自動重新整理驗證碼、重新截圖辨識並重試(Retry)最多 3 次的機制。

💡 【關鍵:帳密讀取與 Cron Job 相容性需求】
- 我原本的程式是在 Cron Job 中透過命令列參數帶入帳密執行的,格式為:`python ksml_lib_13.py <username> <password>`。
- 為了不破壞現有的排程自動化,重構後的登入機制必須採用命令列參數設計:
  檢查是否有命令列參數(`sys.argv`),若有則直接使用排程帶入的帳密。否則跳出程式.

請先不要修改程式碼。
1. 請先閱讀 `ksml_lib_13.py` 了解現有登入邏輯,並結合 `ksml_login.jpg` 截圖與目標網址,分析驗證碼的 HTML 結構與更新機制。
2. 為我產出一個重構的 Implementation Plan (實作計畫),並說明你需要安裝哪些額外的 Python 套件或工具(如 OCR 相關依賴)。
3. 專案成果為新版爬蟲程式 `ksml_lib_14.py`





Claude 規劃結果如下 :

▸ Thought for 5s
  The user wants me to first analyze the existing crawler program and the login pa...
  好的,我先來閱讀現有程式碼與截圖,然後分析目標網站的登入結構。

● Read(D:/antigravity_cli/projects/ksml-crawler/ksml_lib_13.py)
● Read(D:/antigravity_cli/projects/ksml-crawler/ksml_login.jpg) (ctrl+o to expand)

  截圖已清楚看到驗證碼樣式,接著我去實際抓取目標網站的 HTML 結構,了解驗證碼  <img>
  元素與刷新機制。

● ReadURL(https://webpacx.ksml.edu.tw/personal/)
● Read(C:/Users/tony1/.gemini/antigravi...tem_generated/steps/7/content.md) (ctrl+o to expand)
  這個 HTML
  是高度壓縮的,難以直接找到驗證碼結構。讓我用搜索的方式在原始碼中尋找驗證碼相關關鍵字。

● WebSearch(webpacx.ksml.edu.tw captcha img src HTML structure login)
● Search(Captcha keyword search in HTML) (ctrl+o to expand)
  網站的 HTML
  是壓縮過的,我已從截圖中收集到足夠的視覺資訊了。現在我整合所有分析,產出重構計畫。

● Create(C:/Users/tony1/.gemini/antigrav...5b6a6fe1/implementation_plan.md) (ctrl+o to expand)
  以下是完整的分析報告與實作計畫:
  ──────
  ## 📋 分析摘要
  ### 現有登入邏輯( ksml_lib_13.py )

   步驟                      | 程式碼                            | 說明
  ---------------------------|-----------------------------------|---------------------------
   1                         |  find_element(By.ID, 'logxinid')  | 填帳號
   2                         |  find_element(By.ID, 'pincode')   | 填密碼
   3                         |  .btn_grp  →  input  →  .click()  | 點登入按鈕
   ❌                        | 跳過驗證碼                        | 導致失敗
  ### 驗證碼特性(從截圖分析)
  從  ksml_login.jpg  可觀察到:
  • 類型:4-5 位純數字,彩色交錯(紫/藍/橘)
  • 背景:白色,干擾少 → OCR 友善
  • 旁邊有刷新按鈕(🔄) → 可程式化刷新重試
  ──────
  ## 🔧 實作計畫

  詳細計畫請見 → implementation_plan.md

  ### 核心決策
  #### 1. OCR 套件選型:選用  ddddocr  ✅
    pip install ddddocr

  • 優點:專為中文圖形驗證碼訓練、純 Python、無外部系統依賴
  • 比較: pytesseract  需額外安裝 Tesseract 可執行檔,在 Cron Job 環境更麻煩

  #### 2. 新版登入流程(含 3 次重試)

    填帳號 → 填密碼 → [最多3次迴圈]
       → 截取驗證碼圖片(Selenium element.screenshot_as_png)
       → ddddocr 辨識 → 填入驗證碼欄位
       → 點登入 → 判斷成功?
          ✓ 找到 .redblock → 登入成功,繼續爬取
          ✗ 找不到 → 點 🔄 刷新 → 重試
       → 3次仍失敗 → return (None, None)

  #### 3. 命令列相容性:完全不動 ✅

  原有  sys.argv[1]  /  sys.argv[2]  的 Cron Job 格式完全保留:

    python ksml_lib_14.py <username> <password>
    ──────
  ## ⚠️ 實作前的必要確認步驟

  由於網站 HTML 是壓縮的,在正式撰寫  ksml_lib_14.py  前,需要確認以下 3 個元素的確切
  ID/selector:

   元素                        | 預測可能的 ID              | 確認方法
  -----------------------------|----------------------------|--------------------------------
   驗證碼圖片  <img>           |  captchaImg 、 vcode_img   | F12 /  browser.page_source
   驗證碼輸入框  <input>       |  vcode 、 captcha          | F12 / placeholder 含「驗證碼」
   刷新按鈕                    |  refreshCaptcha            | F12 / onclick 含 refresh
  ──────
  ## ✅ 確認後即可開始撰寫  ksml_lib_14.py

  請問您是否要:

  1. 直接授權我產出  ksml_lib_14.py (我會在程式碼中加入自動偵測元素的邏輯)?
  2. 或先用瀏覽器 F12 確認驗證碼元素的 ID 後再告訴我?

Claude 要求我確認驗證碼圖片, 輸入框, Refresh 按鈕的 ID, 我用 F12 去查網頁原始碼, 發現只有輸入框元件有 ID, 其它兩個元件沒有 ID :

> 驗證碼相關的三個元件如下 :
<input name="captcha" id="captcha" type="text" placeholder="請輸入驗證碼,並區分大小寫" value="">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAAAyCAIAAAABYqRsAAAK/0lEQVR42u2beVTTVxbH/WOmZ452nHaO03amdWqrVj0erfuG1W7TVqtDrdXO6LR2mWkVN1y
... (略) ... ZCeQGuR1Bf0pWWwE+70pQPJME6H6Dik/4GGQ8Ih4Q2HhEPCGw4JbzgkHBLecEh4wyHhkPCGQ8Ih4Q2HhDcc0v9v+y/alGmPzd5YpQAAAABJRU5ErkJggmh5dzE3ODMwMDU1NDYxODllYg==" class="captcha" alt="驗證碼圖片如無法讀取可以移到右邊替代方案" style="background: none;">
<button type="button" class="btn reflashbtn">更換驗證碼</button>
其中只有驗證碼輸入框有 ID, 你可能需要用 class 或 xpath 來定位. 

Claude 規劃如下 :

▸ Thought for 1m 4s
  The user has provided the HTML for the three captcha elements:
  完美!三個元素都確認了:
   元素                                        | Selector
  ---------------------------------------------|---------------------------------------------
   驗證碼輸入框                                |  By.ID, 'captcha'
   驗證碼圖片                                  |  By.CSS_SELECTOR, 'img.captcha'
   刷新按鈕                                    |  By.CLASS_NAME, 'reflashbtn'

  還有一個重要發現:驗證碼圖片的  src  是  data:image/png;base64,...
  內嵌格式,這讓我可以直接從屬性取得 base64 bytes 餵給  ddddocr
  ,比截圖更精確、更快!現在直接產出  ksml_lib_14.py :

● Create(D:/antigravity_cli/projects/ksml-crawler/ksml_lib_14.py) (ctrl+o to expand)

  ksml_lib_14.py 已建立完成。以下是重點說明:
  ──────
  ## 🔑 關鍵實作細節
  ### 驗證碼圖片處理(最乾淨的方式)
  由於  src  是  data:image/png;base64,...  內嵌格式,不需要任何 HTTP 請求,直接解碼即可:

    img_src = captcha_img.get_attribute('src')
    b64_data = img_src.split(',', 1)[1]   # 去掉 "data:image/png;base64," 前綴
    img_bytes = base64.b64decode(b64_data) # 得到 PNG bytes
    result = ocr.classification(img_bytes) # ddddocr 辨識

  ### Implicit Wait 衝突處理

  登入成功判斷用  WebDriverWait(5秒)  而非  find_element ,為避免與  implicitly_wait(60)
  衝突,採用暫時停用再恢復的方式:
    browser.implicitly_wait(0)   # 暫停,讓 WebDriverWait 的 5 秒生效
    try:
        WebDriverWait(browser, 5).until(...)
    finally:
        browser.implicitly_wait(60)  # 無論成敗都恢復

  ### 確認的三個 Selector

   用途                                        | Selector
  ---------------------------------------------|---------------------------------------------
   驗證碼圖片                                  |  By.CSS_SELECTOR, 'img.captcha'
   驗證碼輸入框                                |  By.ID, 'captcha'
   刷新按鈕                                    |  By.CLASS_NAME, 'reflashbtn'
  ──────
  ## 📦 部署前安裝套件

  在執行 Cron Job 的主機上安裝:

    pip install ddddocr
    ──────
  ## ✅ 與舊版相容性
  • Cron Job 指令 完全不變: python ksml_lib_14.py <username> <password>
  • 借閱/預約資料擷取邏輯一行未動
  • 舊版  ksml_lib_13.py  保留不受影響

Cluade 已經完成重構實作, 由於爬蟲程式是在樹莓派執行, 先將 ksml_lib_14.py 傳送到樹莓派上, 然後安裝 ddddocr 套件, 但是此套件之依賴套件有些無法在 Pi 3 Bulleye 的 Python 3.9.2 上安裝, 所以要求 Claude 改用替代方案解決, 因為市圖驗證碼是簡單的數字圖片, 只要用經典的開源文字識別套件 Tesseract 就可以達到很高識別精確度 :

> 你在此專案使用的 ddddocr 套件無法在目標主機樹莓派 Pi 3B Bulleye 的 Python 3.9.2 安裝執行,
  請改用經典的 Tesseract OCR 實作
  The user wants to replace ddddocr with Tesseract OCR (pytesseract) because ddddo...

▸ Thought for 30s
  了解,Raspberry Pi 3B Bullseye 的 ARM 架構對  ddddocr  的 ONNX 依賴支援不佳。改用
  pytesseract  +  Pillow  搭配影像預處理是在樹莓派上最穩定的方案。

● Read(D:/antigravity_cli/projects/ksml-crawler/ksml_lib_14.py) (ctrl+o to expand)
  確認了需要修改的範圍,現在一次完成所有 OCR 相關的替換:

● Edit(D:/antigravity_cli/projects/ksml-crawler/ksml_lib_14.py) (ctrl+o to expand)

  修改完成,來驗證最終的  solve_captcha  與  login_with_captcha  函式完整正確:

● Read(D:/antigravity_cli/projects/ksml-crawler/ksml_lib_14.py) (ctrl+o to expand)

  第 107 行有一個多餘的空行,順手清掉:
● Edit(D:/antigravity_cli/projects/ksml-crawler/ksml_lib_14.py) (ctrl+o to expand)
  ksml_lib_14.py 已更新完成。
  ──────
  ## 📝 變更摘要
  ### 替換內容

   項目       | 舊版(ddddocr)                 | 新版(pytesseract)
  ------------|---------------------------------|--------------------------------------------
   imports    |  import ddddocr                 |  import io ,  import pytesseract ,  from
              |                                 | PIL import Image
   OCR 物件   |  ocr =                          | 不需要,pytesseract 為靜態呼叫
              | ddddocr.DdddOcr(show_ad=False)  |
   辨識呼叫   |  ocr.classification(img_bytes)  |  pytesseract.image_to_string(img,
              |                                 | config=...)
   影像預處理 | 無                              | 灰階 → 二值化 → 放大3倍

  ###  solve_captcha()  的影像預處理邏輯

    彩色 PNG  →  灰階 (L mode)  →  二值化 threshold=200  →  放大 3× (LANCZOS)

  • threshold=200:彩色文字(紫/藍/橘)在灰階下通常 < 200,白色背景 ≥ 200,切分乾淨
  • 放大 3×:原始驗證碼圖片較小,Tesseract 對低解析度圖片準確率差,放大後顯著改善
  • 白名單  0-9 :排除 Tesseract 誤判為字母的情況
  •  re.sub(r'[^0-9]', '', raw) :最後一道過濾,清除 Tesseract 殘留的換行或空白
  ──────
  ## 🔧 樹莓派部署指令

    # 1. 安裝系統套件(只需一次)
    sudo apt-get install tesseract-ocr

    # 2. 安裝 Python 套件
    pip install pytesseract Pillow

    # 3. 執行(與舊版完全相同)
    python ksml_lib_14.py <帳號> <密碼>

這樣就完成實作了.


2. 驗收專案成果 : 

修改為 tesseract 版後, 將此新版程式傳送到樹莓派, 但要先安裝必要套件 : 

安裝底層 OCR 套件 : 

pi@kaopi3:~ $ sudo apt-get install tesseract-ocr   
正在讀取套件清單... 完成
正在重建相依關係... 完成  
正在讀取狀態資料... 完成  
The following packages were automatically installed and are no longer required:
  chromium-codecs-ffmpeg-extra freeglut3 libfuse2 libglu1-mesa libmikmod3
  libportmidi0 libqt5designer5 libqt5help5 libqt5test5 librtimulib-dev
  librtimulib-utils librtimulib7 libsdl-mixer1.2 libsdl-ttf2.0-0 libturbojpeg0
  python3-kms++ python3-libcamera python3-opengl python3-piexif python3-prctl
  python3-pyqt5 python3-pyqt5.sip python3-rtimulib python3-v4l2
Use 'sudo apt autoremove' to remove them.
下列的額外套件將被安裝:
  liblept5 libtesseract4 tesseract-ocr-eng tesseract-ocr-osd
下列【新】套件將會被安裝:
  liblept5 libtesseract4 tesseract-ocr tesseract-ocr-eng tesseract-ocr-osd
升級 0 個,新安裝 5 個,移除 0 個,有 15 個未被升級。
需要下載 6,859 kB 的套件檔。
此操作完成之後,會多佔用 21.6 MB 的磁碟空間。
是否繼續進行 [Y/n]? [Y/n] y
下載:1 http://raspbian.raspberrypi.org/raspbian bullseye/main armhf liblept5 armhf 1.79.0-1.1+deb11u1 [899 kB]
下載:2 http://raspbian.raspberrypi.org/raspbian bullseye/main armhf libtesseract4 armhf 4.1.1-2.1+rpi1 [1,082 kB]
下載:3 http://raspbian.raspberrypi.org/raspbian bullseye/main armhf tesseract-ocr-eng all 1:4.00~git30-7274cfa-1.1 [1,592 kB]
下載:4 http://raspbian.raspberrypi.org/raspbian bullseye/main armhf tesseract-ocr-osd all 1:4.00~git30-7274cfa-1.1 [2,991 kB]
下載:5 http://raspbian.raspberrypi.org/raspbian bullseye/main armhf tesseract-ocr armhf 4.1.1-2.1+rpi1 [295 kB]
取得 6,859 kB 用了 15s (468 kB/s)                                              
選取了原先未選的套件 liblept5:armhf。
(讀取資料庫 ... 目前共安裝了 106135 個檔案和目錄。)
正在準備解包 .../liblept5_1.79.0-1.1+deb11u1_armhf.deb……
Unpacking liblept5:armhf (1.79.0-1.1+deb11u1) ...
選取了原先未選的套件 libtesseract4:armhf。
正在準備解包 .../libtesseract4_4.1.1-2.1+rpi1_armhf.deb……
Unpacking libtesseract4:armhf (4.1.1-2.1+rpi1) ...
選取了原先未選的套件 tesseract-ocr-eng。
正在準備解包 .../tesseract-ocr-eng_1%3a4.00~git30-7274cfa-1.1_all.deb……
Unpacking tesseract-ocr-eng (1:4.00~git30-7274cfa-1.1) ...
選取了原先未選的套件 tesseract-ocr-osd。
正在準備解包 .../tesseract-ocr-osd_1%3a4.00~git30-7274cfa-1.1_all.deb……
Unpacking tesseract-ocr-osd (1:4.00~git30-7274cfa-1.1) ...
選取了原先未選的套件 tesseract-ocr。
正在準備解包 .../tesseract-ocr_4.1.1-2.1+rpi1_armhf.deb……
Unpacking tesseract-ocr (4.1.1-2.1+rpi1) ...
設定 tesseract-ocr-eng (1:4.00~git30-7274cfa-1.1) ...
設定 liblept5:armhf (1.79.0-1.1+deb11u1) ...
設定 libtesseract4:armhf (4.1.1-2.1+rpi1) ...
設定 tesseract-ocr-osd (1:4.00~git30-7274cfa-1.1) ...
設定 tesseract-ocr (4.1.1-2.1+rpi1) ...
執行 man-db (2.9.4-2) 的觸發程式……
執行 libc-bin (2.31-13+rpt2+rpi1+deb11u13) 的觸發程式……

安裝 Pillow 與 pytesseract 套件 : 

pi@kaopi3:~ $ pip install pytesseract Pillow    
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting pytesseract
  Downloading https://www.piwheels.org/simple/pytesseract/pytesseract-0.3.13-py3-none-any.whl (14 kB)
Requirement already satisfied: Pillow in /usr/lib/python3/dist-packages (8.1.2)
Requirement already satisfied: packaging>=21.3 in ./.local/lib/python3.9/site-packages (from pytesseract) (26.2)
Installing collected packages: pytesseract
Successfully installed pytesseract-0.3.13

執行結果可以正常運作 : 

pi@kaopi3:~ $ python ksml_lib_14.py xyz 123456
主機 : kaopi3
[嘗試 1/3] 驗證碼辨識結果: 65495
登入成功(第 1 次嘗試)
擷取借閱紀錄 ... OK
擷取預約紀錄 ... OK
資源已釋放
產生借書到期摘要 ... OK
產生預約書摘要 ... OK
{'message': 'xyz 的資料已更新', 'status': 'success'}
執行時間:86.35315299034119

也有驗證兩次才過關的 : 

pi@kaopi3:~ $ python ksml_lib_14.py abc 123456   
主機 : kaopi3
[嘗試 1/3] 驗證碼辨識結果: 301
[嘗試 1/3] 登入失敗,準備重試...
[嘗試 2/3] 驗證碼辨識結果: 75530
登入成功(第 2 次嘗試)
擷取借閱紀錄 ... OK
擷取預約紀錄 ... OK
資源已釋放
產生借書到期摘要 ... OK
產生預約書摘要 ... OK
{'message': 'abc 的資料已更新', 'status': 'success'}
執行時間:155.63533067703247

檢查 render.com 上的爬蟲結果已更新 : 




哇, 原本要折騰一個禮拜以上的工作半天就搞定了. 


3. 上傳 GitHub : 

在 repo 根倉庫 antigravity_cli 下, 用 git add . 指令追蹤新加入的專案 :

PS D:\antigravity_cli> git add .   
warning: in the working copy of 'projects/ksml-crawler/ksml_lib_14.py', LF will be replaced by CRLF the next time Git touches it

用 git commit 提交變更 :

PS D:\antigravity_cli> git commit -m "feat: add ksml-crawler" 
[main c7e4816] feat: add ksml-crawler
 3 files changed, 581 insertions(+)
 create mode 100644 projects/ksml-crawler/ksml_lib_13.py
 create mode 100644 projects/ksml-crawler/ksml_lib_14.py
 create mode 100644 projects/ksml-crawler/ksml_login.jpg

最後用 git push 推送專案至 repo :  

PS D:\antigravity_cli> git push origin main   
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 16 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 210.16 KiB | 8.41 MiB/s, done.
Total 7 (delta 3), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (3/3), completed with 2 local objects.
To https://github.com/tony1966/antigravity_cli.git
   601e3ee..c7e4816  main -> main

完成後檢視 GitHub 已有此專案 :




檢視 token 用量餘額 :




2026年7月2日 星期四

Google Antigravity 學習筆記 : 網頁版待辦清單 (to-do list) 專案

在前兩篇測試中, 已利用 agy 完成 CLI 與 GUI 版的待辦清單專案, 本篇則是要製作網頁版的待辦清單, 並繼續使用 Coding 的王者 Claude Sonnet 4.6 模型來執行此專案. 



1. 建立專案目錄並啟動 agy : 

為了將專案成果上傳到 GitHub, 我將專案工作目錄調整為與 GitHub 一致 : 

PS D:\> tree antigravity_cli 
列出磁碟區 新增磁碟區 的資料夾 PATH
磁碟區序號為 00000233 1258:16B8
D:\ANTIGRAVITY_CLI
└─projects
    ├─todo-cli-app
    └─todo-gui-app

在 projects 下建立專案目錄 : 

PS D:\antigravity_cli\projects> mkdir todo-web-app 
PS D:\antigravity_cli\projects> cd todo-web-app  
PS D:\antigravity_cli\projects\todo-web-app> agy   

因為上個專案使用 Claude Sonnet, 所以登入 agy 後自動套用此底層模型, 如果要改用別的模型, 要用 /model 指令切換. 輸入下列網頁版待辦清單的提示詞 (Gemini 生成) : 

請幫我建立一個全新的 Todo Web App (網頁版)

需求與技術規格:
1. 後端 (Backend):使用 Python Flask 框架建立輕量級 Web Server。
2. 前端 (Frontend):HTML5 / CSS3,介面設計要求現代、乾淨且具備 RWD 行動裝置響應式排版(可引進 Bootstrap 5 CDN 簡化美化)。
3. 核心功能:
   - 支援完整操作:add (新增) / list (檢視) / done (標記完成) / delete (刪除)。
   - 前後端互動:前端操作時,使用 AJAX (JavaScript Fetch API) 非同步與後端通訊,點擊「完成」或「刪除」時網頁不重新整理,即時更新畫面。
4. 資料持久化:
   - 使用 JSON 檔案儲存資料。
   - 【關鍵相容性】:資料欄位格式與邏輯,必須與之前 CLI 和 GUI 版本的 todo.json 保持完全相容。

請先不要寫程式碼。
請先為我產出這個 Web 專案的 Implementation Plan (實作計畫) 以及預計的檔案架構 (File Structure)。




Claude 開始進行規劃, 首先它先要求授權去之前的 CLI 與 GUI 版專案蒐集相關資料 (CLI 是用 Gemini 實作的, 它怎麼知道的?), 比較之後才進行規劃 : 

▸ Thought for 1s
  The user wants me to create an implementation plan and file structure for a Todo...
  讓我先看看現有的專案結構與 todo.json 格式,以確保相容性。

● ListDir(D:/antigravity_cli/projects/todo-web-app)
● Search(Searching for todo.json)
● ListDir(D:/antigravity_cli/projects)
● ListDir(D:/antigravity_cli/projects/todo-cli-app)
● ListDir(D:/antigravity_cli/projects/todo-gui-app)
● Read(D:/antigravity_cli/projects/todo-cli-app/todo_data.json)
● ListDir(D:/antigravity_cli/projects/todo-gui-app/data)
● ListDir(D:/antigravity_cli/projects/todo-cli-app/todo)
● Read(D:/antigravity_cli/projects/todo-gui-app/data/todos.json)
● Read(D:/antigravity_cli/projects/todo-cli-app/todo/manager.py) (ctrl+o to expand)

  資料已收集完畢,現在產出完整的實作計畫。

● Create(C:/Users/tony1/.gemini/antigrav...dcec356eca/todo_web_app_plan.md) (ctrl+o to expand)

  以下是完整的實作計畫,請確認後點擊「Proceed」開始實作。
  ──────
  ### 🔍 調查結果摘要

  在分析現有的兩個版本後,發現資料格式有一個關鍵差異:

                                | CLI 版                       | GUI 版
  ------------------------------|------------------------------|-----------------------------
    id  型別                    |  int (自動遞增)            |  str (UUID)
   標題欄位                     |  title                       |  text

  Web 版將以 CLI 版為基準,使用  int  id +  title  欄位,因為 CLI
  版設計更嚴謹且易於遞增管理。
  ──────
  ### 📐 計畫亮點

  1. REST API — 4 個語意清晰的端點,標準 HTTP 動詞設計
  2. 模組化後端 —  storage.py  +  manager.py  架構沿用自 CLI 版,邏輯一致
  3. AJAX 零重新整理 — 所有操作透過 Fetch API 非同步完成
  4. 資料安全 —  threading.Lock  防止並發寫入損毀 JSON
  5. UI 設計 — Dark Mode + Glassmorphism + 微動畫,視覺震撼

  如果計畫符合您的期待,請點擊「Proceed」,我將立即開始逐步建立所有檔案!





輸入 Proceed 就開始實作表演了, 共有 4 個 phase :

> Proceed

▸ Thought for 1s
  The user wants to proceed with implementing the Todo Web App. Let me start build...
  開始實作!我將分階段建立所有檔案。

● Requested Permission: write_file(D:\antigravity_cli\projects\todo-web-app) (ctrl+o to expand

  ### Phase 1 — 後端核心

  建立後端所有 Python 模組:

● Create(D:/antigravity_cli/projects/todo-web-app/todo/__init__.py)
● Create(D:/antigravity_cli/projects/todo-web-app/requirements.txt)
● Create(D:/antigravity_cli/projects/todo-web-app/todo/storage.py)
● Create(D:/antigravity_cli/projects/todo-web-app/todo/manager.py)
● Create(D:/antigravity_cli/projects/todo-web-app/app.py) (ctrl+o to expand)

  ### Phase 2 — 前端頁面

● Create(D:/antigravity_cli/projects/todo-web-app/static/css/style.css)
● Create(D:/antigravity_cli/projects/todo-web-app/static/js/app.js)
● Create(D:/antigravity_cli/projects/todo-web-app/templates/index.html) (ctrl+o to expand)

  ### Phase 3 — README & 安裝、啟動

● Create(D:/antigravity_cli/projects/todo-web-app/README.md) (ctrl+o to expand)

  現在安裝相依套件並啟動伺服器:

● Bash(pip install -r requirements.txt) (ctrl+o to expand)

  Flask 已就緒,啟動開發伺服器:

● Bash(python app.py)
● ManageTask(Task: ca264670-3c07-430e-8a8b-48dcec356eca/task-45) (ctrl+o to expand)

  伺服器已成功啟動!讓我快速預覽一下畫面:

● GenerateImage(todo_web_app_preview) (ctrl+o to expand)

  ──────
  ### 🎉 Todo Web App 完成!
  所有檔案已建立完成,Flask 伺服器正在運行中。

  ## 📁 建立的檔案清單

   檔案                                        | 說明
  ---------------------------------------------|---------------------------------------------
   app.py                              | Flask 主程式 + REST API 路由
   storage.py                              | Thread-safe JSON 讀寫
   manager.py                              | 業務邏輯(add/list/done/delete)
   index.html                              | 語義化 HTML5 主頁面
   style.css                              | Dark Mode + Glassmorphism 主題
   app.js                              | Fetch API AJAX 前端邏輯
   requirements.txt                              | Python 相依套件
   README.md                              | 專案說明文件

  ## 🚀 現在就開啟

  → http://localhost:5000

  ## ✨ 實作重點

  • 資料相容性 —  todo_data.json  使用與 CLI 版相同的 Schema( id: int ,  title
  欄位),可直接共用現有資料
  • AJAX 零重整 — 完成、刪除操作全程透過 Fetch API,搭配淡入/滑出動畫
  • Thread-safe —  threading.Lock  保護所有 JSON 寫入操作
  • 無框架前端 — 純 Vanilla JS,無 jQuery 或其他相依

───────────────────────────────────────────────────────────────────────────────────────────────
>
───────────────────────────────────────────────────────────────────────────────────────────────
  ● [13:04:46] python app.py running





至此便完成整個專案的實作了, 後端測試伺服器已啟動, 專案網址為 http://localhost:5000. 


2. 驗收專案成果 : 

用 tree 檢視專案檔案目錄 :

PS D:\antigravity_cli\projects> tree todo-web-app /f   
列出磁碟區 新增磁碟區 的資料夾 PATH
磁碟區序號為 0000029A 1258:16B8
D:\ANTIGRAVITY_CLI\PROJECTS\TODO-WEB-APP
│  app.py
│  README.md
│  requirements.txt
│  todo_data.json
├─static
│  ├─css
│  │      style.css
│  │
│  └─js
│          app.js
├─templates
│      index.html
└─todo
    │  manager.py
    │  storage.py
    │  __init__.py
    │
    └─__pycache__
            manager.cpython-312.pyc
            storage.cpython-312.pyc
            __init__.cpython-312.pyc

用瀏覽器開啟網址 http://localhost:5000 即可看到成果 :




手動驗證功能正確. 


3. 上傳 GitHub : 

在 repo 根倉庫 antigravity_cli 下, 用 git add . 指令追蹤新加入的專案 :

PS D:\antigravity_cli> git add .   
warning: in the working copy of 'projects/todo-web-app/README.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-web-app/app.py', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-web-app/requirements.txt', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-web-app/static/css/style.css', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-web-app/static/js/app.js', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-web-app/templates/index.html', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-web-app/todo/__init__.py', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-web-app/todo/manager.py', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-web-app/todo/storage.py', LF will be replaced by CRLF the next time Git touches it

這些 warning 可以忽略. 接下來用 git commit 提交變更 :

PS D:\antigravity_cli> git commit -m "feat: add todo-web-app"   
[main 601e3ee] feat: add todo-web-app
 9 files changed, 1103 insertions(+)
 create mode 100644 projects/todo-web-app/README.md
 create mode 100644 projects/todo-web-app/app.py
 create mode 100644 projects/todo-web-app/requirements.txt
 create mode 100644 projects/todo-web-app/static/css/style.css
 create mode 100644 projects/todo-web-app/static/js/app.js
 create mode 100644 projects/todo-web-app/templates/index.html
 create mode 100644 projects/todo-web-app/todo/__init__.py
 create mode 100644 projects/todo-web-app/todo/manager.py
 create mode 100644 projects/todo-web-app/todo/storage.py

最後用 git push 推送專案至 repo :  

PS D:\antigravity_cli> git push origin main   
Enumerating objects: 20, done.
Counting objects: 100% (20/20), done.
Delta compression using up to 16 threads
Compressing objects: 100% (13/13), done.
Writing objects: 100% (18/18), 10.89 KiB | 1.56 MiB/s, done.
Total 18 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To https://github.com/tony1966/antigravity_cli.git
   5efe72e..601e3ee  main -> main

完成後檢視 GitHub 已有此專案 : 




本專案 repo 網址如下 :


最後用 /usage 檢視 token 用量餘額 :




即使是玩具專案, 還是很吃 Claude 的 token. 

蝦皮購買充電傳輸線 (Type C/Lightening/MicroUSB)

由於五月初去沖繩玩時發現帶去的充電線 (Type C, Lightening) 居然只剩一條能用, 今天上蝦皮各買三條, 另外有顆舊硬碟使用 MicroUSB 介面, 且樹莓派也要用, 也買三條 : 



明華智取 522 元. 

2026年7月1日 星期三

Google Antigravity 學習筆記 : GUI 待辦清單 (to-do list) 專案

在前一篇測試中, 使用 Antigravity CLI 規劃並執行了一個製作 CLI 介面的待辦清單 (to-do list) 專案, 透過預設的 Gemini 模型完成程式碼撰寫與測試, 最後人工驗證功能符合 AI 的規劃, 也完全與我們的預期一致. 本篇則是要製作 GUI 版的待辦清單, 並改用使用 Claude 模型來執行專案. 

另外, 本篇還要嘗試改用 Claude 模型來執行此專案. Google 的 Antigravity 平台在 2026 年的全新架構中採用了 "多模型聯合訂閱" 模式, 購買 Google AI Pro 或 Ultra 的方案後, 課金就已涵蓋了平台內整合的所有跨廠牌旗艦模型 (包括 Claude 3.5/4.6 系列, GPT-OSS 等). 以 Google 帳號授權登入後, Antigravity 的雲端後台會自動處理所有的 API 轉接與計費, 所有的 Token 用量會在計算扣除後反映在 /usage 輸出的剩餘額度中. 

本系列之前的文章參考 :



1. 建立專案目錄並啟動 agy : 

PS D:\agy> mkdir todo-gui-app 
PS D:\agy> cd todo-gui-app  
PS D:\agy\todo-gui-app> agy   

然後在提示號下斜線指令 /model 選擇 Claude Sonnet 做為執行此專案之底層模型 :




接下來就可以輸入專案需求了 :

> 請幫我將目前的 Todo 專案升級/建立一個 GUI 版本
需求 : 
Python GUI (使用 tkinter 與 ttk 套件)
支援完整功能 : add / list / done / delete
資料持久化 : 使用 JSON 儲存資料
介面要求 : 外觀要現代 & 乾淨 (使用 ttk 佈局) 並具備良好的使用者提示 (例如刪除時跳出確認視窗)
請先不要寫程式碼.
請先針對這個 GUI 專案產出 Implementation Plan (實作計畫) 以及預計的檔案架構 (File Structure). 

Claude 回覆的專案實作計畫如下 :

▸ Thought for 7s
  The user wants me to create an Implementation Plan and File Structure for a Pyth...
  讓我先看看現有的專案結構。

● ListDir(D:/agy/todo-gui-app) (ctrl+o to expand)

  專案目前是空目錄,我來為您產出完整的實作計畫。

● Create(C:/Users/tony1/.gemini/antigrav...0-b697217b954f/todo_gui_plan.md) (ctrl+o to expand)

  以上是完整的實作計畫,幾個重點決策說明:
  ──────
  ### 🔑 關鍵設計決策

  1. 元件化架構
  把 Header、InputBar、TodoItem、TodoList
  拆成獨立檔案,方便逐步開發與維護,而非全部塞在一個大檔案裡。

  2. 單向資料流
  所有 CRUD 操作都走  TodoStorage ,UI 元件只負責呈現,避免狀態散落難以追蹤。

  3. 自訂 ConfirmDialog vs  messagebox
  使用  tk.Toplevel  自製刪除確認視窗,才能套用一致的深色主題;系統  messagebox
  外觀無法客製化。

  4. 深色主題
   ttk  的樣式透過  ttk.Style  全域設定,讓整個 App 色調一致,不必在每個元件重複指定顏色。
  ──────
  請確認計畫後點選 Proceed 開始實作!若有任何調整(例如改用淺色主題、增加功能等)請告訴我。




輸入下列提示詞, 讓 agy 按照規劃進行實作 : 

> 這規劃可以, 請依照此 Implementation Plan 逐步實作專案
每一步請先說明要做什麼再執行

Claude 回覆 Phase 1 要做的項目並徵求核准實作 :

▸ Thought for 2s
  The user wants me to implement the project step by step according to the impleme...
  好的,我們依照計畫逐步實作。先從 Phase 1 開始。
  ──────
  ## Phase 1 — 建立目錄結構與設計系統

  要做什麼:

  1. 建立所有必要的資料夾與  __init__.py
  2. 實作  theme.py (全域設計 Token:色彩、字體、樣式)
  3. 實作  main.py (程式進入點)

  先建立完整的目錄骨架:

● Bash(New-Item -ItemType Directory -Force -Path "app", "app\components", "...) (ctrl+o to
expand)

Command
───────────────────────────────────────────────────────────────────────────────────────────────

  Requesting permission for:
     New-Item -ItemType Directory -Force -Path "app", "app\components", "app\dialogs",
  "data"

Do you want to proceed?
> 1. Yes
  2. Yes, and always allow in this conversation for commands that start with 'New-Item'
  3. Yes, and always allow for commands that start with 'New-Item' (Persist to settings.json)
  4. No




按 Yes 建立資料夾結構並要求授權建立 __init__.py :

  先建立完整的目錄骨架:

● Bash(New-Item -ItemType Directory -Force -Path "app", "app\components", "...) (ctrl+o to
expand)

  目錄建立完成,現在建立所有  __init__.py :

● Bash(New-Item -ItemType File -Force -Path "app\__init__.py", "app\compone...) (ctrl+o to
expand)

Command
───────────────────────────────────────────────────────────────────────────────────────────────

  Requesting permission for:
     New-Item -ItemType File -Force -Path "app\__init__.py", "app\components\__init__.py",
  "app\dialogs\__init__.py" | Out-Null; Write-Host "Done"

Do you want to proceed?
> 1. Yes
  2. Yes, and always allow in this conversation for commands that start with 'New-Item -
ItemType File -Force -Path "app\__init__.py", "app\components\__init__...'
  3. Yes, and always allow for commands that start with 'New-Item -ItemType File -Force -Path
"app\__init__.py", "app\components\__init__...' (Persist to settings.json)
  4. No




按 Yes 繼續實作到 Phase 5 : 

  目錄建立完成,現在建立所有  __init__.py :

● Bash(New-Item -ItemType File -Force -Path "app\__init__.py", "app\compone...) (ctrl+o to
expand)

  現在實作  theme.py  — 全域設計系統的核心:
● Create(D:/agy/todo-gui-app/app/theme.py) (ctrl+o to expand)

  ──────
  ## Phase 2 — 資料層(TodoStorage)
  要做什麼: 實作資料模型,負責 JSON 讀寫、add / toggle / delete 操作。
● Create(D:/agy/todo-gui-app/app/storage.py) (ctrl+o to expand)
  ──────
  ## Phase 3 — UI 元件開發
  要做什麼: 逐一建立四個 UI 元件:Header → InputBar → TodoItem → TodoList

  ### 3-1 Header(頂部標題列)

● Create(D:/agy/todo-gui-app/app/components/header.py) (ctrl+o to expand)
  ### 3-2 InputBar(新增輸入列)
● Create(D:/agy/todo-gui-app/app/components/input_bar.py) (ctrl+o to expand)
  要做什麼: 先建立對話框,因為 TodoItem 會依賴它。

● Create(D:/agy/todo-gui-app/app/dialogs/confirm_dialog.py) (ctrl+o to expand)

  ### 3-4 TodoItem(單筆 Todo 列)

● Create(D:/agy/todo-gui-app/app/components/todo_item.py) (ctrl+o to expand)

  ### 3-5 TodoList(可捲動列表容器)
  ### 3-3 ConfirmDialog(刪除確認視窗)

● Create(D:/agy/todo-gui-app/app/components/todo_list.py) (ctrl+o to expand)

  ──────
  ## Phase 4 & 5 — 主 App 與進入點整合

  要做什麼: 實作  app.py (主控制器,整合所有元件與資料層),以及  main.py
  (視窗初始化、置中、快捷鍵)。

● Create(D:/agy/todo-gui-app/app/app.py)
● Create(D:/agy/todo-gui-app/main.py) (ctrl+o to expand)

  最後建立  requirements.txt :

● Create(D:/agy/todo-gui-app/requirements.txt) (ctrl+o to expand)

  所有檔案就緒!現在執行看看:

● Bash(python main.py) (ctrl+o to expand)

Command
───────────────────────────────────────────────────────────────────────────────────────────────

  Requesting permission for:
     python main.py

Do you want to proceed?
> 1. Yes
  2. Yes, and always allow in this conversation for commands that start with 'python main.py'
  3. Yes, and always allow for commands that start with 'python main.py' (Persist to
settings.json)
  4. No





至此 Claude 已完成所有實作, 按 Yes 執行程式 :

● ManageTask(Task: f7de5e33-ecc3-4c99-93d0-b697217b954f/task-34)
● Requested Permission: read_file(C:\Users\tony1\.gemini\antigravity-cli\brain\f7de5e33-ecc3-
4...)
● ListDir(C:/Users/tony1/.gemini/antigrav...17b954f/.system_generated/tasks) (ctrl+o to expand
  App 正在運行中(無 crash 錯誤)。視窗應該已在您螢幕上開啟了。讓我驗證一下最終的檔案結構:

● ListDir(D:/agy/todo-gui-app)
● ListDir(D:/agy/todo-gui-app/app) (ctrl+o to expand)

  專案結構完整, __pycache__  出現表示 Python 已成功載入模組。
  ──────
  ## ✅ 實作完成總結

  所有 5 個 Phase 都已完成,App 正在運行中:

   Phase       | 內容                                                           | 狀態
  -------------|----------------------------------------------------------------|------------
   Phase 1     | 目錄結構 +  theme.py                                           | ✅
   Phase 2     |  storage.py (資料層 + JSON 持久化)                           | ✅
   Phase 3     |  header.py  /  input_bar.py  /  todo_item.py  /  todo_list.py  | ✅
   Phase 4     |  confirm_dialog.py (自訂刪除確認視窗)                        | ✅
   Phase 5     |  app.py  +  main.py (整合 & 進入點)                          | ✅

  已實作的功能:

  • ✅ Add — 輸入框 + Enter / 點擊按鈕新增,空輸入紅框警示
  • ✅ List — 捲動列表,最新項目在頂,時間戳記顯示
  • ✅ Done — 勾選框切換完成,刪除線文字 + 灰化效果
  • ✅ Delete — 🗑 按鈕 + 自訂深色確認對話框(淡入動畫)
  • ✅ JSON 持久化 — 關閉後重開資料不遺失
  • ✅ 快捷鍵 —  Ctrl+N  聚焦輸入、 Esc  關閉對話框、 Enter  確認

  執行方式:

    python main.py


 How's the CLI experience so far? Help us improve:
 [1] Good  [2] Fine  [3] Bad  [0] Skip


2. 驗收專案成果 : 

開啟一個新的 PS 視窗, 切到專案目錄下, 用 tree /f 檢視專案結構 : 

PS D:\agy\todo-gui-app> tree /f   
列出磁碟區 新增磁碟區 的資料夾 PATH
磁碟區序號為 000000AF 1258:16B8
D:.
│  main.py
│  requirements.txt
├─app
│  │  app.py
│  │  storage.py
│  │  theme.py
│  │  __init__.py
│  │
│  ├─components
│  │  │  header.py
│  │  │  input_bar.py
│  │  │  todo_item.py
│  │  │  todo_list.py
│  │  │  __init__.py
│  │  │
│  │  └─__pycache__
│  │          header.cpython-312.pyc
│  │          input_bar.cpython-312.pyc
│  │          todo_item.cpython-312.pyc
│  │          todo_list.cpython-312.pyc
│  │          __init__.cpython-312.pyc
│  │
│  ├─dialogs
│  │  │  confirm_dialog.py
│  │  │  __init__.py
│  │  │
│  │  └─__pycache__
│  │          confirm_dialog.cpython-312.pyc
│  │          __init__.cpython-312.pyc
│  │
│  └─__pycache__
│          app.cpython-312.pyc
│          storage.cpython-312.pyc
│          theme.cpython-312.pyc
│          __init__.cpython-312.pyc
└─data
        todos.json

可見 Claude 將此專案做了結構化設計, 元件與對話框放在不同資料夾裡面, 程式碼就不一一檢視了. 


3. 驗證程式功能 : 

在專案目錄下執行主程式 :

PS D:\agy\todo-gui-app> python main.py   

執行結果可正常增刪待辦事項 :






整體外觀設計有專業感, 唯一美中不足的是, 點選待辦事項時字的顏色會改變為與背景色類似, 導致無法看清, 這可以叫 agy 進一步修改. 

最後用 /usage 指令檢視執行此專案耗用了多少 Claude 模型額度 :




吃掉 8% 額度, 看起來比之前跑 Gemini 的 CLI App (不到 1%) 還耗得兇啊!


4. 上傳 GitHub : 

參考前一篇測試作法, 將 todo-gui-app 專案上傳到 GitHub : 

用 git add. 指令讓 Git 開始追蹤新加入的專案 : 

PS D:\agy\antigravity_cli> git add .   
warning: in the working copy of 'projects/todo-gui-app/app/app.py', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-gui-app/app/components/header.py', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-gui-app/app/components/input_bar.py', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-gui-app/app/components/todo_item.py', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-gui-app/app/components/todo_list.py', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-gui-app/app/dialogs/confirm_dialog.py', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-gui-app/app/storage.py', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-gui-app/app/theme.py', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-gui-app/main.py', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'projects/todo-gui-app/requirements.txt', LF will be replaced by CRLF the next time Git touches it

這些 warning 無妨. 接下來用 git commit 提交變更 :

PS D:\agy\antigravity_cli> git commit -m "feat: add todo-gui-app"   
[main 5efe72e] feat: add todo-gui-app
 13 files changed, 1497 insertions(+)
 create mode 100644 projects/todo-gui-app/app/__init__.py
 create mode 100644 projects/todo-gui-app/app/app.py
 create mode 100644 projects/todo-gui-app/app/components/__init__.py
 create mode 100644 projects/todo-gui-app/app/components/header.py
 create mode 100644 projects/todo-gui-app/app/components/input_bar.py
 create mode 100644 projects/todo-gui-app/app/components/todo_item.py
 create mode 100644 projects/todo-gui-app/app/components/todo_list.py
 create mode 100644 projects/todo-gui-app/app/dialogs/__init__.py
 create mode 100644 projects/todo-gui-app/app/dialogs/confirm_dialog.py
 create mode 100644 projects/todo-gui-app/app/storage.py
 create mode 100644 projects/todo-gui-app/app/theme.py
 create mode 100644 projects/todo-gui-app/main.py
 create mode 100644 projects/todo-gui-app/requirements.txt

最後用 git push 推送專案至 repo :

PS D:\agy\antigravity_cli> git push origin main   
Enumerating objects: 20, done.
Counting objects: 100% (20/20), done.
Delta compression using up to 16 threads
Compressing objects: 100% (17/17), done.
Writing objects: 100% (18/18), 17.15 KiB | 3.43 MiB/s, done.
Total 18 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/tony1966/antigravity_cli.git
   239b617..5efe72e  main -> main

完成後檢視 GitHub 已有此專案 : 




本專案 repo 網址如下 :