Scrape các trang render bằng JavaScript với trình duyệt headless và proxy
Trong bài này
Một số trang chẳng hiện gì hữu ích trong HTML thô — giá, danh sách hay đánh giá chỉ xuất hiện sau khi JavaScript chạy trong trình duyệt. requests thường không thấy nội dung đó, nên người ta dùng trình duyệt headless như Playwright hay Puppeteer. Nó chạy được, nhưng trình duyệt rất nặng: tốn nhiều băng thông hơn hẳn và dễ bị nhận diện vân tay hơn. Bài này nói về khi nào bạn thật sự cần nó, cách gắn proxy vào, và cách giữ chi phí lẫn việc bị chặn ở mức thấp.
Bạn có thật sự cần trình duyệt không?
Hãy kiểm tra trước khi dùng, vì phương án thay thế rẻ hơn nhiều:
- Xem HTML thô ("View source" của trình duyệt). Nếu dữ liệu đã nằm sẵn ở đó,
requeststhường là đủ. - Nhìn tab Network khi trang tải. Nhiều trang lấy dữ liệu từ một endpoint JSON mà bạn gọi thẳng được — nhẹ hơn nhiều so với render cả trang.
- Chỉ dùng trình duyệt khi nội dung thật sự cần JavaScript hoặc thao tác người dùng mới hiện.
Phần cơ bản của scrape bằng request thường có trong bài proxy cho thu thập dữ liệu web.
Chi phí khi chạy một trình duyệt
Trình duyệt headless tải trang như trình duyệt thật: HTML, CSS, JavaScript, ảnh và font. Trên proxy 4G, nó ngốn 200GB nhanh gấp nhiều lần so với một request đơn lẻ. Hai thói quen giúp giảm:
- Chặn thứ không cần — ảnh, font và media hiếm khi quan trọng cho việc scrape.
- Dùng lại một browser context cho cả lượt chạy thay vì mở trình duyệt mới cho mỗi trang.
Cấu hình proxy trong Playwright
Playwright nhận proxy khi bạn khởi chạy trình duyệt. Cài bằng pip install playwright và playwright install chromium, đặt HOST, PORT, USER và PASS theo proxy của bạn, và chặn tài nguyên nặng để tiết kiệm băng thông:
from playwright.sync_api import sync_playwright
PROXY = {
"server": "http://HOST:PORT", # hoac socks5://HOST:PORT
"username": "USER",
"password": "PASS",
}
with sync_playwright() as p:
browser = p.chromium.launch(proxy=PROXY, headless=True)
page = browser.new_page()
# Tiet kiem bang thong: bo anh, font va media
page.route(
"**/*",
lambda route: route.abort()
if route.request.resource_type in ("image", "font", "media")
else route.continue_(),
)
page.goto("https://example.com/product/1", wait_until="domcontentloaded")
page.wait_for_selector(".price") # cho du lieu, khong phai sleep co dinh
print(page.inner_text(".price"))
browser.close()Puppeteer (Node) cùng ý tưởng: truyền --proxy-server khi khởi chạy và đưa thông tin đăng nhập bằng page.authenticate.
Chờ nội dung, không phải hẹn giờ cố định
Lỗi phổ biến nhất là sleep(5) rồi cầu may. Nó chậm khi trang nhanh và chập chờn khi trang chậm. Thay vào đó:
wait_for_selectorcho đúng phần tử chứa dữ liệu của bạn, hoặc- chờ mạng rảnh (network idle) khi trang cứ tải thêm từng phần.
Cách này nhanh hơn và đáng tin hơn nhiều, càng quan trọng khi đi qua proxy 4G nơi độ trễ thay đổi.
Trình duyệt vẫn bị chặn
Một engine trình duyệt thật có ích, nhưng tự động hoá vẫn để lại dấu vết, và trình duyệt mang theo cả bộ vân tay cần khớp:
- Một hồ sơ cho mỗi IP và đừng chạy nhiều hồ sơ cùng lúc qua một địa chỉ.
- Đổi IP hợp lý, không phải mỗi trang — cách gọi link đổi IP từ script và chờ IP mới có trong bài đổi IP proxy bằng API.
- Để quản lý nhiều danh tính, một trình duyệt antidetect chuyên dụng ổn định hơn tự động hoá thô — xem cài proxy vào trình duyệt antidetect.
- Các quy tắc hành vi trong bài cách scrape mà không bị chặn cũng áp cho trình duyệt.
Proxy 4G Singapore của 65Proxy
IP di động Singapore của chúng tôi chạy được với Playwright, Puppeteer và mọi trình duyệt antidetect, qua HTTP hoặc SOCKS5, đổi IP bằng link (áp quy tắc 5 phút) và 200GB mỗi gói, giá 1 ngày $4, 7 ngày $13, 1 tháng $40. Vì trình duyệt tốn băng thông nhanh, hãy chặn ảnh và font và ưu tiên endpoint JSON nếu có. Xem bảng giá.
Câu hỏi thường gặp
Playwright hay requests thường — nên dùng cái nào?
Dùng requests thường bất cứ khi nào dữ liệu nằm trong HTML hoặc một endpoint JSON; nó nhanh hơn và nhẹ hơn nhiều. Chỉ dùng Playwright khi nội dung cần JavaScript mới hiện.
Trình duyệt headless có thật sự tốn băng thông hơn nhiều không?
Có — nó tải cả trang, kể cả script và tài nguyên. Chặn ảnh, font và media, và dùng lại một context, sẽ giảm mạnh. Hãy đo một lượt chạy so với 200GB mỗi gói.
Tôi có thể đổi IP ở mỗi trang không?
Có thể, nhưng thường không nên — đổi IP giữa phiên làm hỏng đăng nhập và trông đáng ngờ, và mỗi proxy 65Proxy đổi IP tối đa một lần mỗi 5 phút. Hãy giữ một phiên trên một IP và chỉ đổi khi bị giới hạn.