A Playwright-based automation script for a configurable web reservation flow.
This repository is intended for personal learning, testing, and automation practice. Configure your own target site locally and avoid committing private credentials, login state, logs, or real service URLs.
- Copy
pe.config.json.exampletope.config.json. - Fill in your local account, target page URL, login options, and booking preferences.
- Run
run-pe.bat. - The script will open a browser, check login state, wait until the configured time, switch through the configured booking flow, and attempt the selected reservation.
- After submission or failure, the browser remains open until you close it manually.
Do not commit these files:
pe.config.json: local account, real target URL, OTP payload, and booking preferencesplaywright-state.json: saved browser login statelogs/: runtime logs and OCR debug samples.tesseract-cache/: local OCR cache/runtime data
Each run writes terminal output to logs/pe-<timestamp>.log while still printing normally in the terminal. For OCR debugging, the newest log file includes OCR worker startup time plus per-captcha preprocessing, recognition, total time, and confidence.
site.entryUrl is the target reservation page URL. Keep the real URL only in your local pe.config.json; the public example uses a placeholder.
login.mode supports:
manual: always log in manuallystorage_state: reuse saved login state first, fallback to manual login if neededotp: generate a dynamic OTP from QR payload and log in automatically
Related config fields:
login.saveStorageStateAfterLoginlogin.captcha.enabledlogin.captcha.expectedLengthlogin.captcha.maxAttemptslogin.otp.venueOptionTextlogin.otp.minSecondsRemaininglogin.otp.qrPayloadBase64
When a numeric image captcha appears on the login form:
- The script captures the captcha image automatically
- Runs local OCR to recognize it
- Fills the result into the input field
Retry logic:
login.captcha.expectedLengthis strictly enforced- If the OCR result length is incorrect, the captcha is refreshed immediately
- If the page shows a captcha-related error, the script refreshes the captcha and retries
- The script retries up to
login.captcha.maxAttempts
OTP is generated after captcha recognition and right before clicking login, reducing the chance of OTP expiration caused by OCR delays.
browser.mode supports:
auto: prefer local Chrome/Edge, fallback to Playwrightlocal: force local Chrome/Edgeplaywright: use browser installed vianpx playwright install chromiumcustom: use path specified inbrowser.executablePath
payment.autoPay controls whether the script continues automatically into payment after order submission.
When payment.autoPay = true, the script waits for the payment page, selects the leftmost coupon if needed, prints the payable amount, clicks the final payment confirmation button, and keeps the browser open.
When payment.autoPay = false, the script submits the order only, stops before payment, and keeps the browser open for manual handling.
Test mode is controlled by test.mode in pe.config.json, so the script does not ask for test mode in the terminal.
off: normal reservation flow; submit order; auto-pay followspayment.autoPayselect_only: test selection flow; select slots and agreement only; skip submit and auto-paysubmit_only: test selection flow; submit order; skip auto-paysubmit_and_pay: test selection flow; submit order and auto-paylogin_fill_only: login-form test flow; keep filling OTP login fields after page load/refresh; never click login
The script follows a config-first approach:
- If a field is defined in
pe.config.json, it will be used - If missing, the script will prompt for input at runtime
Supported fields:
booking.dateTargetbooking.courtPrioritybooking.startHourbooking.waitUntilbooking.bookTwoSlots
booking.dateTarget supports weekday number 1-7, fixed date MM/DD, or special value next7d for today + 7 days.
booking.courtPriority supports either string form like "1,2,4" or array form like ["1", "2", "4"].
booking.startHour uses only the starting hour, such as 18, interpreted as 18:00. If booking.bookTwoSlots = true, the second slot is the following hour.
booking.waitUntil uses HH:mm:ss, such as 17:42:40.
Before entering the waiting phase, the script prints a booking summary:
Booking target: date=next7d, time=18:00, 19:00, courts=1号场, 2号场, 4号场
This helps verify configuration correctness before execution.
- The browser will not close automatically after submission
- If booking fails, the browser remains open for inspection
- Currently supports up to 2 consecutive hours
- For consistent behavior across machines, install the Playwright browser in advance and use
browser.mode: "playwright"