Повечето скрапери се провалят, преди да бъде прочетен дори един header.
Сървърът анализира сигнатурата на ниво връзка, която вашият клиент изпраща по мрежата, и решава дали сте браузър или библиотека, преструваща се на такъв. Python requests, net/http в Go, чист curl: всички те предават отличителен отпечатък в момента, в който кажат здравей. Сайтовете, които следят за това (Datadome, Akamai, Imperva, управляваната защита на Cloudflare), прекъсват връзката или показват challenge страница, преди вашият User-Agent string изобщо да има значение.
Точно това решава unblocker: true във FourA. През последния месец фиксирахме компонентите, които гарантират неговата надеждна работа.
Какво ново
unblocker: true е единичен флаг при всяко /api/single извикване. Активирайте го и ние правим три неща: добавяме набора от браузърни headers, изпращаме заявката през транспортен слой, който съответства на този на реален браузър, и декомпресираме върнатите от сървъра данни (gzip, brotli, deflate). Първите две са налични още от бетата. Третото (автоматична brotli декомпресия) влезе в продукция на 25 март, а фиксирането на версиите беше завършено на следващия ден, за да се поддържат headers и транспортният слой в пълен синхрон.
Как работи
Ето как изглежда една заявка:
curl -X POST "https://api.foura.ai/api/single" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"url": "https://example.com/products",
"method": "GET",
"unblocker": true
}'
Отдолу работят три слоя.
Инжектиране на хедъри. Задаваме пълния набор от браузърни хедъри: User-Agent, Sec-Ch-Ua, Sec-Ch-Ua-Platform, Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-Dest, Accept, Accept-Language и Accept-Encoding. Подредбата има значение. Реалните браузъри ги изпращат в специфична последователност, а библиотеките за детекция проверяват за това.
Сигнатура на връзката. Нашият транспорт съответства на байтово ниво с актуална браузърна сесия: същата подредба на разширенията, същите предпочитания за шифри, същите особености при handshake. Стандартният curl, Python requests и Go net/http генерират сигнатури, които се маркират автоматично за милисекунди от защитената инфраструктура.
Автоматична декомпресия. Когато unblocker е включен, задаваме Accept-Encoding на gzip, deflate, br и транспортният слой декомпресира тялото. Получавате декодиран низ (или Buffer, ако подадете returnBuffer: true). Без ръчна обработка на brotli, без разминавания между хедъри и тяло, когато сайтът избере deflate вместо gzip.
Защо фиксирането на версиите има значение
Сигнатурите на връзката са обвързани с конкретна версия. Детайлите на мрежово ниво за даден браузър този месец се различават от тези през миналия, а сайт, който прави прецизен фингърпринтинг, ще забележи отклонението. Фиксираме променящите се компоненти заедно, така че хедърите, navigator обектите и сигнатурата на връзката да отчитат една и съща версия на браузъра.
Ако това звучи пипкаво, така е. Бяхме засегнати от разминаване по време на миграцията на монорепото през март, когато един компонент се обнови автоматично, а останалите се разминаха. Решението отне два комита: фиксиране на променящия се компонент и пълно недоверие към пакетния мениджър за поддържането на синхрона.
Резултат
При вътрешни тестове срещу сайтове, които проверяват източника на заявката (финанси, туризъм, големи платформи за електронна търговия), разликата между unblocker: false и unblocker: true е разликата между challenge страница и статус 200. Обикновен HTTP клиент често получава 403 още при първия опит. Същият URL с unblocker: true зарежда страницата, защото заявката изглежда точно като браузъра, който описва.
Но за сайтове без фингърпринтинг (повечето публични API, по-стари CMS шаблони, всичко с ограничения само по IP rate limit), оставянето на unblocker изключен е напълно нормално и спестява няколко милисекунди от договарянето. Използвайте го там, където е необходим.
За напреднали
Няколко полезни модела за работа.
Комбинирайте unblocker с жилищно (residential) прокси, когато целта проверява и репутацията на IP адреса. IP адреси от центрове за данни с перфектна сигнатура на връзката все пак биват блокирани при ASN мрежи, които сайтът е поставил в черен списък. Нашият proxy endpoint (/api/proxy) ротира по целеви домейн, така че добавянето на "proxy": "residential" към заявката обикновено е достатъчно.
Пропуснете unblocker при извикване на JSON API, които не изискват браузърни параметри. Допълнителните хедъри всъщност могат да изглеждат подозрително за API, което очаква програмен клиент, например бекенд, извикващ собствен микросървиз.
Ако сайтът проверява посетителя с JavaScript, преди да покаже страницата, само unblocker няма да бъде достатъчен. Нуждаете се от browser endpoint, който изпълнява JavaScript на страницата в пълен браузър. Това е различен продукт с различно ценообразуване на кредитите, като го описахме в Browser Tasks: How to Scrape JavaScript-Heavy Sites.
Също така можете да комбинирате unblocker с блока validate, за да отхвърляте отговори, които технически връщат 200, но съдържат страница с предизвикателство:
{
"url": "https://example.com/products",
"method": "GET",
"unblocker": true,
"validate": {
"data": { "fail": ["captcha", "Access Denied"] }
}
}
Това превръща тихите грешки в класифицирани такива, което е важно за проследяването на процента на успеваемост в dashboard.
Какво следва
Браузърите пускат нова стабилна версия на всеки четири седмици. Ние обновяваме нашия стек съответно. Няма нужда да променяте нищо от ваша страна: unblocker: true продължава да сочи към версията на браузъра, която сме тествали изцяло.
По-трудната част тепърва предстои. HTTP/3 проверките вече се появяват при по-големите сайтове, QUIC транспортният слой е по-труден за пресъздаване от по-стария транспорт, а преходът от статични пакети с хедъри към наистина динамична емулация вече започва. Защитените сайтове преминаха към проверка на подредбата на HTTP/2 рамките, а разликата между "библиотека, която изглежда като браузър" и "браузър" ще се смалява и от двете страни. Ще пишем за това, когато го пуснем.