Python 瀏覽器自動化:用 Playwright 自動登入、下載報告、批量填表

香港好多文職同事每日開工第一件事,就係逐個平台登入:銀行後台下載月結單、供應商網站查存貨、物流平台追運單、政府網站交表、廣告平台抄報告數字。每個動作本身只係幾十秒,但乘十幾個平台、乘每個月二十個工作天,就係一段唔細嘅時間,而且一式一樣、做完又冇乜滿足感。

呢類「喺瀏覽器入面重複點擊」嘅工作,正正係瀏覽器自動化(Browser Automation)嘅強項。Python 有幾個工具可以做,Playwright 係近年最順手嘅一個:它會開一個真瀏覽器,照住你寫嘅步驟去撳、去填、去等下載,速度同真人操作一樣,但唔會攰、唔會漏步驟。

Playwright 同 Selenium 有咩分別?

Selenium 係老牌工具,但實戰上最多人撞板嘅係「元素未載入就撳」——網頁慢半秒就報錯,於是四圍加 sleep(3),結果又慢又唔穩。Playwright 內置自動等待:撳一個按鈕之前,會自動等該元素出現、可視、可點擊,超過時限先報錯。另外它支援 Chromium、Firefox、WebKit,亦可以用 codegen 錄製操作成 code,對唔熟前端嘅同事友善好多。

第一步:安裝

先裝 Python 套件,再下載瀏覽器本體(Chromium 大約 150MB):

pip install playwright playwright install chromium

第二句唔可以漏。Playwright 用自己嘅獨立瀏覽器,唔用你部機嘅 Chrome,確保每部機行為一致。

場景一:自動登入,下載月結單

以下係最常見嘅場景。假設每月一號要登入銀行或供應商後台,下載一份 PDF 月結單:

from playwright.sync_api import sync_playwright import os, datetime USER = os.environ["PORTAL_USER"] PWD = os.environ["PORTAL_PASS"] month = datetime.date.today().strftime("%Y%m") with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page(accept_downloads=True) page.goto("https://portal.example.com/login") page.get_by_label("帳號").fill(USER) page.get_by_label("密碼").fill(PWD) page.get_by_role("button", name="登入").click() page.wait_for_url("**/dashboard") with page.expect_download() as dl: page.get_by_role("link", name="下載月結單").click() dl.value.save_as("statement_" + month + ".pdf") browser.close() print("已下載 statement_" + month + ".pdf")

逐行解釋

  • sync_playwright() —— 建立一個自動化環境,所有操作寫喺 with 區塊入面,離開時自動收尾。
  • launch(headless=True) —— 唔顯示瀏覽器視窗,背景執行。第一次寫建議改成 False,親眼睇住它做乜,debug 快好多。
  • accept_downloads=True —— 一定要開,否則點擊下載連結之後檔案會消失喺空氣中。
  • get_by_label / get_by_role —— 用畫面見到嘅文字去搵元素(「帳號」「密碼」「登入」),唔使研究 HTML 結構,網站改版都無咁易爛。
  • wait_for_url("**/dashboard") —— 等跳轉完成先做下一步,係最實用嘅「登入成功」判斷。
  • expect_download() —— 包住會觸發下載嘅點擊,之後就可以 save_as() 存去指定位置同檔名。
  • os.environ —— 帳號密碼由環境變數讀入,唔好寫死喺 code 度,尤其唔好上載去 GitHub。

場景二:由 CSV 讀資料,批量查詢同截圖

另一個高頻場景:手上有一批訂單編號或者客戶編號,要逐個貼入系統查狀態,再截圖存檔。呢種「同一版位、唔同輸入」嘅工作,用迴圈處理就最快:

import csv from pathlib import Path from playwright.sync_api import sync_playwright Path("shots").mkdir(exist_ok=True) with sync_playwright() as p: browser = p.chromium.launch(headless=True) context = browser.new_context(storage_state="login.json") page = context.new_page() page.goto("https://portal.example.com/orders") with open("orders.csv", encoding="utf-8") as f: for row in csv.DictReader(f): oid = row["order_id"] page.get_by_label("訂單編號").fill(oid) page.get_by_role("button", name="查詢").click() page.wait_for_selector(".result-card") page.screenshot(path="shots/" + oid + ".png", full_page=True) print("已截圖", oid) browser.close()

注意 storage_state="login.json" 呢一句。Playwright 可以將登入後嘅 cookie 同 session 存成 json,之後開新 context 直接載入,就唔使每次由登入頁開始,亦唔怕改密碼令程式停。第一次手動登入後加一句 context.storage_state(path="login.json") 存檔即可。

實戰四個要留意嘅位

  • Selector 唔好用位置 —— 用 page.locator("div:nth-child(3) > button") 呢類寫法,網站一改版就即刻爛;用畫面上嘅文字(get_by_role、get_by_text)穩陣得多。
  • 兩步驗證(2FA)要人手處理 —— 有 SMS 驗證碼嘅系統,用 storage_state 保存 session 通常可以避開;一定要每次輸入嘅,就改為半自動,等人打驗證碼。
  • 唔好用嚟搶名額或者違反網站條款 —— 自動化係幫自己做重複工作,唔係繞過對方規則;高頻請求只會令你被封 IP。
  • 加錯誤處理同紀錄 —— 用 try / except 包住每一步,出錯時截圖同寫 log,就知係邊個平台、邊一步出問題。

實際效益大概係點

以一個每月要處理六個平台報告、每平台八分鐘嘅文職同事計,一個月大約用 48 分鐘純粹喺「登入、按鈕、下載、改名」。寫好 script 之後,跑一次大約兩至三分鐘,仲可以排喺開機時自動跑,返到公司檔案已經齊。批量查訂單更明顯:一百張訂單人手做,每張一分鐘就係一個半鐘,程式做十至十五分鐘,中間可以做其他嘢。

自動化真正嘅價值,係將呢類零碎、易漏、無需判斷嘅步驟固定落嚟——唔會有人請假就漏做,亦唔會抄錯數字。

總結

Python 教學:Playwright 嘅入門門檻比想像中低,安裝兩句指令,核心就係「開瀏覽器、去網址、填欄位、撳按鈕、等下載」五個動作。建議由最簡單、最無風險嘅場景開始:例如每朝自動登入某個平台下載一份報告,先確認穩定,再逐步加上 CSV 迴圈同截圖。記得三個原則:憑證放環境變數、selector 用畫面文字、每一步都要有錯誤紀錄。