Chuyển tới nội dung chính

Migration: Selenium → Playwright (.NET)

Chiến lược chốt: viết bộ engine thứ 2 dùng Playwright song song với bộ Selenium hiện có. Runtime bật cái nào thì chạy cái đó (feature flag / config). Không xoá Selenium cho tới khi Playwright chạy ổn định ngang bằng.

Phạm vi đo được (từ source thật)

Hạng mụcSố lượngGhi chú
File dùng Selenium (active)16+1 file QBCC comment-out vẫn ref Selenium
File dùng EO.WebBrowser (riêng biệt)13CoreLogic, GoogleRealestate, toàn bộ Share\Winform
Lớp trừu tượng trung tâmCó (một phần)SearchBaseService.chrome + DeSearchHelper gánh ~70%
Target framework các project workernet4.5.2Dưới mức tối thiểu của Playwright
Selenium.WebDriver3.141.0 (đa số) / 4.10.0 (AutoLoad)Lệch version trong cùng solution
Spike Playwright sẵn cóMicrosoft.Playwright 1.41.2 đã ref trong .ShareFolder Playwright\ rỗng — chưa wire

Hai tầng kiến trúc cần xử lý KHÁC NHAU

  1. Worker config-driven (dễ) — đi qua SearchBaseService.chrome + DeSearchHelper.GetWebsiteElement/GetValue (đọc selector Id/Css/XPath từ JSON). Port tập trung 2 lớp này là phủ được phần lớn worker.
  2. Scraper static + EO WinForm (khó)AsicSelenium, VevoSelenium, AutoLoad tự ôm driver riêng; CoreLogic/GoogleRealestate dùng EO WebView.LoadUrl/EvalScript trong WinForm. Không có abstraction chung → phải port từng cái.

Đầu việc lớn (epics)

EPIC 0 — Retarget framework (điều kiện tiên quyết)

  • Spike: retarget 1 worker đơn giản (AccessCanberra_Act) net4.5.2 → net8.0, chuyển csproj sang SDK-style. Verify: project build + chạy 1 lượt search thật.
  • Đánh giá độ vỡ: EF6 EDMX, EO.WebBrowser, DevExpress trên .NET 8.
  • Quyết định: retarget toàn bộ hay tách worker Playwright thành assembly .NET 8 mới gọi qua IPC.

EPIC 1 — Lớp trừu tượng Playwright (nền tảng)

  • Thiết kế interface IBrowserSession thay cho việc ISearch_Base lộ ChromeDriver ra ngoài. Verify: Selenium impl cũ vẫn chạy qua interface mới (giữ tương thích).
  • Port DeSearchHelper.GetWebsiteElement/GetValue sang Playwright locator (Id/Css/XPath → page.Locator). Verify: unit test resolve selector từ JSON mẫu của 1 site.
  • Port vòng đời driver: OpenChrome/CloseChromePlaywright.Chromium.LaunchAsync + download API. Verify: mở/đóng sạch, không còn process mồ côi.
  • Cơ chế switch engine (Selenium ↔ Playwright) qua config. Verify: đổi flag, cùng input ra cùng output.

EPIC 2 — Port worker config-driven (mỗi worker 1 task)

Thứ tự từ dễ → khó: AccessCanberra_ActOneGovNSW_AUTPBGovAuAbrBusinessGov (có hardcode selector + switch tab) → WhitePages.

  • Mỗi worker: override StartSearchAndDownload/GetDataFromWebsite bản Playwright. Verify: chạy song song Selenium vs Playwright, so khớp bản ghi TextSearch_Data_*.

EPIC 3 — Port các tính năng hạ tầng khó

  • Captcha + human-in-the-loop: hiện reCaptcha được phát hiện → alert Google Chat → busy-wait chờ người RDP vào server giải trong cùng browser session đang chạy headed. Playwright chạy browser riêng → phải thiết kế lại luồng này (persistent context / CDP attach / headed bắt buộc). Verify: mô phỏng 1 lần chặn captcha, người giải, flow tiếp tục.
  • Download PDF: thay hack "diff thư mục download trước/sau click" bằng Playwright download API. Verify: tải đúng file, không phụ thuộc polling.
  • Anti-bot: chuyển --disable-blink-features=AutomationControlled, override navigator.webdriver, xoay user-agent sang Playwright context options. Verify: site nguồn không chặn.
  • Bỏ KillOrphanedChromeDriverProcesses (Playwright tự quản process).

EPIC 4 — Port scraper static + EO WinForm (khó nhất)

  • AsicSelenium (419 dòng, có retry captcha 15×, xoay UA). Verify: ASIC search ra PDF + parse field đúng.
  • VevoSelenium (login form, download PDF). Verify: so với output cũ.
  • CoreLogic (EO → Playwright): thay WebView.LoadUrl/EvalScript + inject JS login bằng Playwright. Nhớ phụ thuộc AutoLoad giữ session. Verify: login + lấy data.
  • GoogleRealestate (EO → Playwright): gallery ảnh + screenshot Google Map. Verify: ra ImageURLs + GoogleMapImage.
  • AutoLoad: app WinForm giữ phiên CoreLogic bằng reload timer → cân nhắc Playwright persistent context. Verify: session sống qua nhiều giờ.

3 thứ khó nhất (đã xác nhận từ source)

  1. Retarget framework là tiên quyết — toàn bộ worker net4.5.2, dưới mức tối thiểu Playwright. Không reference được cho tới khi retarget xong.
  2. Luồng captcha human-in-the-loop — headed browser + phát hiện reCaptcha + alert Google Chat + busy-wait chờ người giải trong chính session live. Playwright chạy browser riêng → phải thiết kế lại, không port 1-1.
  3. Hai stack browser sau UI WinForms/WPF — một nửa code là EO.WebBrowser nhúng trong WinForm với EvalScript thô. Playwright không có control nhúng → cần đổi kiến trúc (browser out-of-process), không phải swap thư viện.

Rủi ro & lưu ý

  • Lệch version Selenium (3.141 vs 4.10) → đừng giả định API đồng nhất khi đọc code cũ.
  • Một số selector hardcode trong C# (ASIC, ABR) chứ không nằm trong JSON → không port được tập trung hoàn toàn.
  • 9 worker không nằm trong solution nào → build/migrate từng cái riêng.
  • Microsoft.Playwright 1.41.2 đã được ref sẵn trong .Share (spike cũ) nhưng chưa wire — kiểm tra trước khi thêm mới.