Cách tránh captcha khi scraping (mà không vi phạm quy định)
Hầu hết captcha xuất hiện khi scraping là phản ứng với lưu lượng trông giống tự động hóa. Cách rẻ nhất để xử lý là ngừng kích hoạt chúng. Điều đó có nghĩa là trước tiên tìm một nguồn dữ liệu hợp pháp, hỏi quy định của website xem bạn được phép làm gì, gửi ít yêu cầu hơn và chậm hơn, và không tải cùng một trang hai lần. Giải captcha là phương án dự phòng cho những trường hợp không thể tránh, không phải là kế hoạch chính.
Kiểm tra API hoặc nguồn dữ liệu chính thức trước
Nhiều website bị scraping đã có sẵn cách lấy cùng dữ liệu mà không gặp captcha: API công khai, xuất dữ liệu, feed RSS hoặc sitemap, hay một chương trình đối tác. Nguồn chính thức đáng tin cậy hơn, ít thay đổi mà không báo trước, và cho chủ website quyền quyết định cách bạn sử dụng. Hãy tìm:
- mục dành cho nhà phát triển hoặc API ở chân trang website,
sitemap.xmlđể có danh sách trang,- liên kết RSS hoặc Atom trong phần
<head>của trang, - trang "data" hoặc "download" để xuất dữ liệu hàng loạt.
Nếu một trong các nguồn này đáp ứng nhu cầu của bạn, hãy dùng nó. Bạn sẽ tránh được hầu hết captcha nhờ không phải yêu cầu HTML nào cả.
Tôn trọng robots.txt và tốc độ mà nó yêu cầu
robots.txt cho biết những đường dẫn nào các client tự động được phép truy cập và đôi khi cho biết nên chờ bao lâu giữa các yêu cầu. Thư viện chuẩn của Python có thể đọc nó giúp bạn:
import time
from urllib.robotparser import RobotFileParser
import requests
USER_AGENT = "ExampleBot/1.0 (+https://example.com/bot)"
parser = RobotFileParser()
parser.set_url("https://example.com/robots.txt")
parser.read()
delay = parser.crawl_delay(USER_AGENT) or 5 # quay về mức thận trọng 5 giây
urls = [
"https://example.com/products?page=1",
"https://example.com/products?page=2",
]
last_request = 0.0
for url in urls:
if not parser.can_fetch(USER_AGENT, url):
print("skipped by robots.txt:", url)
continue
wait = delay - (time.monotonic() - last_request)
if wait > 0:
time.sleep(wait)
resp = requests.get(url, headers={"User-Agent": USER_AGENT}, timeout=30)
last_request = time.monotonic()
print(url, resp.status_code)
Nếu robots.txt cấm một đường dẫn, cách trung thực là bỏ qua nó hoặc hỏi chủ website. Đi vòng qua bằng trình duyệt không thay đổi điều website đã yêu cầu.
Chậm lại và giãn đều yêu cầu
Một nhịp độ đều đặn, vừa phải hiếm khi kích hoạt thử thách, trong khi một đợt bùng nổ hầu như luôn kích hoạt. Vài thói quen tạo ra khác biệt lớn:
- Chọn một tốc độ yêu cầu cho mỗi website và giữ nguyên, thay vì chạy hết tốc lực.
- Thêm độ lệch ngẫu nhiên (jitter) để thời gian không quá đều đặn.
- Dừng lại và lùi một khoảng thời gian khi thấy mã 429 hoặc một trang captcha.
- Chạy công việc vào giờ thấp điểm nếu tải của website là một mối lo.
Lưu cache và không tải lại
Mỗi yêu cầu bạn không gửi là một yêu cầu website không phải xử lý. Lưu các trang bạn đã tải cùng ngày và hash của nội dung, chỉ tải lại khi nội dung có khả năng đã thay đổi. Các yêu cầu có điều kiện với header If-Modified-Since hoặc ETag cho phép máy chủ trả lời "not modified" một cách nhẹ nhàng khi nó hỗ trợ.
Tái sử dụng phiên và gửi header bình thường
Một phiên giữ cookie giữa các yêu cầu hoạt động giống một khách truy cập hơn là một script bắt đầu lại từ đầu mỗi lần. Dùng requests.Session() cho mỗi website, và gửi một User-Agent rõ ràng, trung thực, nêu tên bot của bạn cùng thông tin liên hệ. Đừng giả mạo trình duyệt để vượt qua một quy định. Nếu website cần JavaScript để hiển thị nội dung, hãy dùng công cụ trình duyệt cho các trang đó, và giữ nguyên giới hạn tốc độ.
Khi captcha vẫn xuất hiện
Một số website sẽ hiển thị captcha bất kể bạn cư xử cẩn thận đến đâu. Hãy phát hiện nó trong code và dừng công việc đó thay vì liên tục gõ vào trang. Việc phát hiện và tùy chọn giải captcha PopularCaptcha được trình bày trong captcha khi web scraping.
Lên kế hoạch thu thập trước khi bắt đầu
Một lần thu thập tải mọi thứ mỗi ngày là cách dễ nhất để kích hoạt captcha. Hãy lên kế hoạch công việc trước:
- Ưu tiên. Quyết định trang nào thay đổi thường xuyên và trang nào hiếm khi thay đổi. Thu thập các trang thường xuyên thường hơn, và các trang còn lại ít hơn.
- Dùng ngày trong sitemap. Nhiều sitemap có giá trị
lastmod. Bỏ qua các URL chưa thay đổi kể từ lần ghé thăm trước. - Thu thập tăng dần. Lưu lần tải thành công gần nhất cho mỗi URL, và tiếp tục từ đó thay vì bắt đầu lại từ trang đầu sau một lỗi.
- Trải đều tải. Chia danh sách lớn thành các lô và chạy chúng rải trong ngày, không chạy tất cả cùng lúc.
Một kế hoạch như vậy làm giảm số lượng yêu cầu, và đó là đòn bẩy lớn nhất bạn có.
Hãy ghi kế hoạch thành một file cấu hình ngắn hoặc một bảng: các website, các mục, khoảng thời gian làm mới và ngân sách yêu cầu hằng ngày cho từng mục. Khi hết ngân sách, công việc dừng lại cho đến khi cửa sổ tiếp theo mở ra. Coi ngân sách là giới hạn cứng chứ không phải gợi ý, đó là điều giữ cho crawler không trôi dần vào kiểu lưu lượng gây ra captcha. Hãy xem lại ngân sách vài tuần một lần, vì một website đang phát triển cũng có thể tăng lưu lượng, và điều từng là hợp lý quý trước có thể không còn hợp lý bây giờ.
Thu thập dữ liệu có trách nhiệm
- Kiểm tra
robots.txtvà điều khoản sử dụng trước khi bắt đầu, và tôn trọng những gì chúng quy định. - Giữ tốc độ yêu cầu thấp và dừng khi website báo hiệu nó đang quá tải.
- Không thu thập dữ liệu cá nhân mà bạn không có lý do để giữ, và xóa khi không còn cần.
- Không tái đăng nội dung có bản quyền với số lượng lớn. Hãy dùng dữ liệu để phân tích, so sánh hoặc cho sản phẩm riêng của bạn, và ghi nguồn khi phù hợp.
- Liên hệ chủ website nếu bạn cần khối lượng lớn hơn. Họ có thể cung cấp feed.