Dlaczego wyczerpały się próby żądania proxy
Problem
Wywołanie POST /api/proxy/ zwraca błąd i brak danych. Komunikat jest krótki i ma zawsze taką samą strukturę:
{
"error": "Download maxTry limit reached",
"total": 34.812,
"request": { "...": "..." }
}
To zdanie brzmi identycznie niezależnie od tego, czy każdy węzeł wyjściowy był zablokowany, każdy węzeł wyjściowy był martwy, czy też FourA pobrało właściwą stronę przy niemal każdej próbie, a Twoje własne reguły validate ją odrzuciły. Te trzy przypadki wymagają zupełnie innych rozwiązań.
Rozwiązanie: attemptReport
Każde wywołanie Proxy, które wykonało swoje próby i zakończyło się niepowodzeniem, zawiera obiekt attemptReport obok błędu, w tym także takie, które zakończyło się kodem "error": "Timeout". Nazwa hosta, która się nie rozwiązuje, kończy się błędem przed jakąkolwiek próbą, ze statusem status: 0 i bez raportu. Zlicza to, na co faktycznie natrafiły próby:
{
"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
}
Ciąg error celowo pozostaje niezmieniony, aby klient dopasowujący się do niego nadal działał. Odczytaj attemptReport.summary, aby uzyskać jednozdaniową odpowiedź, lub użyj liczników, jeśli chcesz na ich podstawie tworzyć warunki logiczne.
Pola
| Pole | Typ | Co zlicza |
|---|---|---|
total |
integer | Podjęte próby |
noResponse |
integer | Węzeł wyjściowy nie odpowiedział lub strona nie odpowiedziała na czas |
defense |
integer | Strona odpowiedziała i w tej odpowiedzi rozpoznano dostawcę weryfikacji botów |
contentRejected |
integer | HTTP 200, brak weryfikacji botów, odrzucono tylko przez Twoje validate.data |
statusRejected |
integer | Strona odpowiedziała, brak weryfikacji botów, odrzucono przez Twoje validate.status |
other |
integer | Odpowiedziano i żaden z powyższych przypadków nie wystąpił |
vendors |
string[] | Każdy dostawca weryfikacji botów rozpoznany w dowolnym miejscu zadania |
profilesTried |
string[] | Profile przeglądarek wysłane przez zadanie, w kolejności pierwszego użycia. default oznacza, że żądanie wyszło dokładnie tak, jak zostało napisane. |
summary |
string | Jedno zdanie zbudowane na podstawie liczników. Bezpieczne do rejestrowania w logach lub wyświetlenia użytkownikowi. |
Interpretacja wyników
contentRejected ma wysoką wartość
Strony zostały pobrane. Twoja reguła validate.data nie została do nich dopasowana.
To problem, który możesz naprawić samodzielnie, i który jest maskowany przez każdy inny sygnał: żądania wyglądają na nieudane w każdej metryce, a FourA przez cały czas dostarczało rzeczywistą treść. Pobierz stronę raz przez POST /api/single/ całkowicie bez validate, zobacz, co faktycznie wraca, i napisz regułę na nowo na podstawie otrzymanej odpowiedzi.
Częstą przyczyną jest jedna reguła zastosowana do zestawu stron, które nie są identyczne. Selektor, który istnieje na stronach artykułów, a nie istnieje na stronach wideo, zawiedzie za każdym razem, gdy trafi na stronę wideo, bez końca, generując pełny koszt.
statusRejected ma wysoką wartość
Strona odpowiedziała, a Twoja reguła validate.status ją odrzuciła. Jeśli te statusy to 401, 403, 429 lub 503, strona odrzuca klienta, zamiast informować, że strona nie istnieje. Wypróbuj:
- Inny profil przeglądarki (
browser,os,versionw wewnętrznym obiekcierequest) exitCountries, jeśli treść ma blokadę regionalnąPOST /api/browser/, jeśli odrzucenie wymaga uruchomienia JavaScriptu do przejścia
defense ma wysoką wartość
W odpowiedziach rozpoznano weryfikację botów, a vendors wskazuje którego dostawcę. Zobacz Site checks, aby dowiedzieć się, co FourA obecnie omija, a co jedynie raportuje. Jeśli dostawca nie jest omijany na tym punkcie końcowym, przenieś wywołanie do POST /api/browser/ lub POST /api/auto/.
noResponse ma wysoką wartość
Węzły wyjściowe w ogóle nie odpowiedziały, więc niczego nie ustalono na temat celu. Zwiększ maxTries, zwiększ timeout_ms i sprawdź, czy adres URL jest osiągalny z publicznego internetu.
other ma wysoką wartość
Strona odpowiedziała ze statusem, nie rozpoznano weryfikacji botów, a próba nie powiodła się z innego powodu, takiego jak reguła validate.headers. Cel wolniejszy niż Twój timeout_ms jest zliczany w noResponse.
Rotacja profili przeglądarki
Gdy witryna odrzuca przeglądarkę wysłaną przez FourA, Proxy przestaje przy niej obstawać i próbuje innej rodziny z publicznego katalogu profili. Nie kosztuje to żadnej dodatkowej próby: rotacja zmienia to, co wysyła ponowienie, a nie to, czy w ogóle do niego dochodzi.
Proxy zapamiętuje również dla każdej witryny rodzinę, która ostatnio tam zadziałała po odrzuceniu wartości domyślnej. Kolejny request do tej witryny może wystartować z tej rodziny już przy pierwszej próbie, a FourA przechodzi do następnej rodziny, gdy witryna zacznie odrzucać również tę. Przeglądarka mobilna jest zapamiętywana tylko dla witryny zwracającej JSON.
profilesTried pozwala sprawdzić ten proces. Jeden wpis oznacza, że każda próba wysłała tę samą przeglądarkę: default to request w pierwotnej postaci, a identyfikator z katalogu to rodzina, której FourA nauczyło się wcześniej dla tej witryny. Kilka wpisów oznacza, że uruchomiono rotację i witryna odrzuciła każdą z nich, co jest inną sytuacją niż brak jakiejkolwiek rotacji.
W udanym response Proxy pole profile pojawia się tylko wtedy, gdy rotacja wybrała przeglądarkę inną niż wskazana w zapytaniu:
{
"status": 200,
"data": "<!doctype html>...",
"proxy": "A1B2C3",
"profile": "...",
"total": 4.108
}
Wartość to identyfikator katalogowy z GET /api/profiles. Brak oznacza, że request został wysłany dokładnie w podanej postaci. Obecność oznacza, że przeglądarka, która zadziałała, była inna niż wpisana, więc w kolejnych wywołaniach przekaż ten identyfikator jako profile zamiast powtarzać ten, który zawiódł. Dashboard Playground robi to automatycznie za pomocą opcji Carry.
Jawnie zdefiniowane parametry profile, browser, os lub version w Twoim requeście nigdy nie są nadpisywane. Dotyczy to również requestu zawierającego Twój własny header User-Agent lub Cookie, ponieważ clearance jest powiązany z sygnaturą, która go uzyskała.
Odczytywanie w kodzie
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", [])))
Powiązane
- API Endpoints: Pełna dokumentacja request i response Proxy
- Site checks: Dostawcy,
defensei ponowne użycie clearance - Request Outcomes: Jak odrzucona response jest klasyfikowana i rozliczana
- Common Issues: Inne problemy i ich rozwiązania
- Choosing the Right Endpoint: Kiedy Proxy nie jest odpowiednim narzędziem