Tại sao proxy request đã dùng hết số lần thử
Vấn đề
Một lệnh gọi POST /api/proxy/ trả về lỗi và không có dữ liệu. Thông báo rất ngắn và luôn có cùng một định dạng:
{
"error": "Download maxTry limit reached",
"total": 34.812,
"request": { "...": "..." }
}
Câu đó có ý nghĩa giống hệt nhau dù mọi exit node đều bị chặn, mọi exit node đều chết, hay FourA đã tìm nạp trang thực trên hầu hết các lần thử nhưng chính các quy tắc validate của bạn đã loại bỏ nó. Ba trường hợp này cần các cách xử lý hoàn toàn trái ngược nhau.
Câu trả lời: attemptReport
Mỗi response Proxy thất bại đều mang theo một đối tượng attemptReport bên cạnh lỗi. Nó thống kê những gì các lần thử thực sự gặp phải:
{
"error": "Download maxTry limit reached",
"attemptReport": {
"total": 25,
"noResponse": 0,
"defense": 0,
"contentRejected": 25,
"statusRejected": 0,
"other": 0,
"vendors": [],
"profilesTried": ["default"],
"summary": "25 attempt(s): 25 returned HTTP 200 with no defense present and were rejected only by your validate.data - the page was fetched, your content rule did not match it"
},
"total": 34.812
}
Chuỗi error được cố ý giữ nguyên không đổi, để client khớp theo chuỗi này tiếp tục hoạt động. Hãy đọc attemptReport.summary để xem câu trả lời ngắn gọn một dòng, hoặc xem các số lượng đếm khi bạn muốn phân nhánh xử lý theo chúng.
Các trường
| Trường | Kiểu dữ liệu | Ý nghĩa đếm |
|---|---|---|
total |
integer | Số lần thử đã thực hiện |
noResponse |
integer | Điểm exit không phản hồi, do đó chưa bao giờ kết nối tới trang web |
defense |
integer | Trang web đã phản hồi và phát hiện đơn vị cung cấp giải pháp bot-check trong phản hồi đó |
contentRejected |
integer | HTTP 200, không có bot check, chỉ bị từ chối bởi validate.data của bạn |
statusRejected |
integer | Trang web đã phản hồi, không có bot check, bị từ chối bởi validate.status của bạn |
other |
integer | Đã phản hồi, và không thuộc các trường hợp trên |
vendors |
string[] | Mọi đơn vị cung cấp bot-check được ghi nhận ở bất kỳ đâu trong tác vụ |
profilesTried |
string[] | Các browser profile mà tác vụ đã gửi, theo thứ tự sử dụng đầu tiên. default nghĩa là request được gửi đi chính xác như bạn đã viết. |
summary |
string | Một câu được tổng hợp từ các số lượng đếm. An toàn để ghi log hoặc hiển thị cho người dùng. |
Cách đọc hiểu
contentRejected cao
Các trang đã trả về. Quy tắc validate.data của bạn không khớp với chúng.
Đây là trường hợp bạn có thể tự khắc phục, và cũng là trường hợp bị ẩn đi bởi mọi tín hiệu khác: các request trông giống như thất bại ở mọi chỉ số, nhưng FourA thực tế vẫn đang phân phối nội dung thực trong suốt quá trình. Hãy fetch trang một lần qua POST /api/single/ mà không có bất kỳ validate nào, xem nội dung thực sự trả về là gì, và viết lại quy tắc cho phù hợp.
Một nguyên nhân phổ biến là áp dụng một quy tắc duy nhất cho một tập hợp các trang không đồng nhất. Một selector tồn tại trên các trang bài viết nhưng không có trên các trang video sẽ luôn thất bại mỗi khi gặp trang video, liên tục, và tốn toàn bộ chi phí.
statusRejected cao
Trang web đã phản hồi và quy tắc validate.status của bạn từ chối. Nếu các mã trạng thái đó là 401, 403, 429, hoặc 503, trang web đang từ chối client thay vì báo rằng trang không tồn tại. Hãy thử:
- Một browser profile khác (
browser,os,versiontrên đối tượngrequestbên trong) exitCountriesnếu nội dung bị khóa theo khu vực địa lýPOST /api/browser/nếu trường hợp từ chối cần JavaScript để vượt qua
defense cao
Đã nhận diện bot check trên các phản hồi, và vendors nêu rõ tên đơn vị cung cấp nào. Xem Anti-Bot Defenses để biết FourA xử lý vượt qua những loại nào hiện nay và chỉ báo cáo những loại nào. Nếu đơn vị cung cấp đó không thuộc diện được vượt qua trên endpoint này, hãy chuyển lệnh gọi sang POST /api/browser/ hoặc POST /api/auto/.
noResponse cao
Các điểm exit không phản hồi, do đó không thu thập được thông tin nào về mục tiêu. Hãy tăng maxTries, tăng timeout_ms, và kiểm tra xem URL có phân giải được từ internet công cộng hay không.
other cao
Đã phản hồi, và không được phân loại vào bất kỳ trường hợp nào ở trên. Hãy kiểm tra total_time so với timeout_ms của bạn: mục tiêu phản hồi chậm hơn mức thời gian dự tính của bạn sẽ rơi vào đây.
Luân phiên Browser Profile
Khi một trang web từ chối trình duyệt mà FourA gửi đến, Proxy sẽ dừng việc cố chấp sử dụng nó và thử một nhóm khác từ danh mục profile công khai. Quá trình này không tính thêm lượt thử: việc luân chuyển thay đổi nội dung gửi đi khi retry, hoàn toàn không làm phát sinh thêm lượt gửi mới.
profilesTried là cách bạn theo dõi quá trình này. Một mục đồng nghĩa request đã được gửi đi đúng như thiết lập ban đầu trong mọi lần thử. Nhiều mục nghĩa là quá trình luân chuyển đã diễn ra và trang web từ chối từng profile trong số đó, một trường hợp hoàn toàn khác với việc chưa từng luân chuyển.
Trên một response Proxy thành công, trường profile chỉ xuất hiện khi cơ chế luân chuyển chọn một trình duyệt mà bạn không yêu cầu ban đầu:
{
"status": 200,
"data": "<!doctype html>...",
"proxy": "A1B2C3",
"profile": "...",
"total": 4.108
}
Giá trị là ID danh mục từ GET /api/profiles. Vắng mặt nghĩa là request đã được gửi đi chính xác như được viết. Hiện diện nghĩa là trình duyệt hoạt động không phải là trình duyệt bạn đã nhập, vì vậy hãy truyền ID đó lại dưới dạng profile trong các lệnh gọi tiếp theo thay vì phát lại trình duyệt đã thất bại. Trang tổng quan Playground thực hiện điều này cho bạn với Carry.
profile, browser, os, hoặc version rõ ràng trên request của bạn sẽ không bao giờ bị ghi đè. Request mang header User-Agent hoặc Cookie của riêng bạn cũng vậy, vì clearance được liên kết với signature đã tạo ra nó.
Đọc giá trị trong mã nguồn
import requests
API = "https://eu.api.foura.ai"
H = {"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"}
r = requests.post(f"{API}/api/proxy/", headers=H, json={
"maxTries": 5,
"request": {
"method": "GET",
"url": "https://example.com/product/42",
"validate": {"data": {"accept": ["Add to cart"]}},
},
}).json()
if "error" in r:
rep = r.get("attemptReport", {})
print(rep.get("summary", r["error"]))
if rep.get("contentRejected", 0) > rep.get("total", 0) / 2:
# The pages arrived. The validate rule is what threw them away.
raise SystemExit("validate.data did not match the real page")
if rep.get("defense", 0):
print("bot check met:", ", ".join(rep.get("vendors", [])))
Liên quan
- API Endpoints: Tài liệu tham khảo đầy đủ về request và response của Proxy
- Anti-Bot Defenses: Các nhà cung cấp,
defense, và phát lại clearance - Request Outcomes: Cách phân loại và tính phí response bị từ chối
- Common Issues: Các sự cố khác và cách khắc phục
- Choosing the Right Endpoint: Khi Proxy không phải là công cụ phù hợp