Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 5 — Xử lý tình huống động: chờ, iframe, popup, upload/download

Đã đọc 0/12 mục · còn khoảng 3 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Web thật đầy cạm bẫy: nội dung tải sau (AJAX), iframe lồng nhau, popup che nút, tải file. Đây là nơi 80% agent gãy. Bài này trang bị cách xử lý từng loại.

1. Chờ đúng cách — kẻ thù số một

Đừng bao giờ sleep(3) mù quáng. Chờ theo điều kiện:

page.wait_for_selector("text=Kết quả")        # chờ phần tử xuất hiện
page.wait_for_load_state("networkidle")        # chờ mạng lắng
page.get_by_role("button", name="Lưu").wait_for(state="visible")

Playwright có auto-wait cho hầu hết action, nhưng nội dung do JS render sau vẫn cần chờ tường minh.

2. Iframe — nội dung trong khung riêng

Nhiều widget (thanh toán, chat, CAPTCHA) nằm trong iframe. Selector ở page chính không thấy được nó:

frame = page.frame_locator("iframe#payment")
frame.get_by_label("Số thẻ").fill("4242...")

Quy tắc: nếu không tìm thấy phần tử "rành rành trên màn hình", nghi ngờ nó nằm trong iframe.

3. Popup, modal, tab mới

# Bắt tab/popup mới mở
with page.expect_popup() as pi:
    page.get_by_text("Mở báo cáo").click()
popup = pi.value
popup.wait_for_load_state()

Modal che nút: agent phải đóng modal (nút X / Esc) trước khi thao tác tiếp — đây là bước observe phải phát hiện được.

4. Upload file

page.get_by_label("Tải CV").set_input_files("cv.pdf")

Không cần mô phỏng hộp thoại hệ điều hành — set_input_files gán trực tiếp, ổn định hơn nhiều so với computer-use click vào dialog OS.

5. Download file

with page.expect_download() as di:
    page.get_by_role("button", name="Export").click()
download = di.value
download.save_as("bao-cao-thang-6.csv")

Luôn verify file tồn tại và có nội dung sau khi tải, đừng tin nút "đã bấm".

Các bước xử lý một trang lạ

  • Sau khi navigate, wait_for_load_state("networkidle").
  • Kiểm tra có modal/cookie banner che không → đóng trước.
  • Nếu thiếu phần tử mong đợi → dò iframe.
  • Với action mở cửa sổ mới → bọc trong expect_popup.
  • Với tải/đăng file → dùng API chuyên dụng, không dùng dialog OS.
  • Verify kết quả bằng tín hiệu khách quan.

Checklist "trang này có bẫy gì"

  • [ ] Có cookie banner / modal che nội dung không?
  • [ ] Nội dung có load sau (AJAX/infinite scroll) không?
  • [ ] Phần tử có nằm trong iframe không?
  • [ ] Click này có mở tab/popup mới không?
  • [ ] Có CAPTCHA / xác thực 2 lớp chặn không?
  • [ ] File tải về đã kiểm tra tồn tại + kích thước chưa?

Ví dụ cụ thể

Agent điền form trợ cấp mãi báo lỗi "không thấy ô Ngày sinh". Nguyên nhân: một cookie banner phủ toàn trang chặn tương tác. Thêm bước observe phát hiện banner và bấm "Đồng ý" trước, agent chạy trơn tru.

CAPTCHA và xác thực 2 lớp — biết điểm dừng

Một số rào cản được thiết kế để chặn tự động hóa: CAPTCHA, OTP qua điện thoại, xác thực sinh trắc. Đừng cố "phá" chúng — vừa vi phạm điều khoản dịch vụ, vừa mong manh. Cách vận hành đúng:

- Phát hiện dấu hiệu (iframe reCAPTCHA, ô nhập OTP) trong bước observe
- DỪNG và escalate cho người xử lý phần xác thực
- Sau khi người vượt qua, agent tiếp tục từ checkpoint

Thiết kế "human-in-the-loop tại điểm chặn" bền vững hơn nhiều so với tự động vượt rào.

Infinite scroll và nội dung tải dần

Nhiều trang chỉ tải thêm khi cuộn. Để lấy đủ dữ liệu:

prev = 0
while True:
    page.mouse.wheel(0, 3000)
    page.wait_for_load_state("networkidle")
    count = page.locator(".item").count()
    if count == prev: break     # không thêm nữa -> hết
    prev = count

Đặt trần số lần cuộn để tránh vòng lặp vô tận trên trang "vô hạn" thật sự.

Sai lầm thường gặp

  • sleep() cố định: hoặc chờ thừa (chậm) hoặc chờ thiếu (gãy). Luôn chờ theo điều kiện.
  • Bỏ quên iframe: agent "mù" trước widget thanh toán/CAPTCHA rồi kết luận sai là trang lỗi.
  • Mô phỏng dialog OS để upload: cực kỳ mong manh; đã có set_input_files.
  • Không đóng modal/cookie banner: mọi click sau đó thất bại khó hiểu.
  • Tin "đã tải" mà không kiểm tra file: pipeline chạy tiếp với file rỗng.
Bài sau bước sang địa hạt khó hơn: computer-use điều khiển cả máy tính bằng pixel.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi