Войти

Как устроен SDK

PHP SDK - это тонкая обёртка над тем же HTTP API, который описан в API Reference. Каждый параметр Crawling API, который вы добавили бы как query string в прямом HTTP-вызове, доступен в SDK как ключ в массиве опций - имена, значения по умолчанию и поведение соответствуют один к одному. SDK не добавляет ни одного параметра; SDK не скрывает ни одного параметра.

Что вы получаете, используя его вместо cURL или Guzzle напрямую:

  • URL-кодирование, валидация параметров и парсинг ответов работают из коробки.
  • Автозагрузка PSR-4 - подключается к любому современному PHP-фреймворку (Laravel, Symfony, Slim) без церемоний.
  • По одному клиентскому классу на каждый Crawlbase API, все с одинаковой формой конструктора и вызовов.
  • Разумные значения по умолчанию (тайм-аут 90 секунд, автоматический парсинг JSON для ответов format=json, тела в кодировке UTF-8).

Исходники на github.com/crawlbase/crawlbase-php. Issues и PR приветствуются.

Установка

Последняя версия на Packagist. Требуется PHP 7.4+; протестировано вплоть до PHP 8.3.

composer require crawlbase/crawlbase

# Or add to composer.json directly:
# "crawlbase/crawlbase": "^1.0"

Аутентификация

Каждый Crawlbase API использует одну и ту же модель аутентификации по token. На одном аккаунте существуют два типа токенов:

  • Normal Token (TCP) - для статического HTML, JSON-эндпоинтов, всего, что не требует браузера. Быстрее и дешевле.
  • JavaScript Token - для SPA, лениво загружаемых лент, всего, что скрывает контент за клиентским рендерингом. Обязателен для использования page_wait, ajax_wait, scroll и css_click_selector.

Используйте переменные окружения (или конфиг вашего фреймворка - config() в Laravel, параметры в Symfony) в production. SDK сам не читает env-переменные - это сделано намеренно, чтобы вы контролировали, откуда берутся учётные данные. Шаблон:

<?php
require 'vendor/autoload.php';

use Crawlbase\CrawlingAPI;

// Pick the right token at instantiation; the SDK doesn't switch
// tokens per-call, so keep two clients if you alternate.
$api = new CrawlingAPI(['token' => getenv('CRAWLBASE_TOKEN')]);
$js = new CrawlingAPI(['token' => getenv('CRAWLBASE_JS_TOKEN')]);

$api->get('https://github.com/anthropic');
$js->get('https://feed.example.com', ['page_wait' => 2000]);

Полная модель токенов и расположение в дашборде — на странице Authentication.

Быстрый старт

Три строки от autoload до полученного HTML:

<?php
require 'vendor/autoload.php';

$api = new \Crawlbase\CrawlingAPI(['token' => 'YOUR_TOKEN']);
$res = $api->get('https://github.com/anthropic');

if ($res->statusCode == 200) {
 echo $res->body;
}

Ветвитесь по ->statusCode (HTTP-статус SDK к Crawlbase) и ->headers->pc_status (вердикт Crawlbase - см. Ошибки ниже) при принятии решения о повторе. Передайте ['format' => 'json'], чтобы получить JSON-конверт вместо сырого содержимого страницы.

Все API в одном пакете

У каждого Crawlbase API есть соответствующий клиентский класс. Один и тот же конструктор, те же глаголы get / post.

<?php
use Crawlbase\{CrawlingAPI, ScraperAPI, LeadsAPI, ScreenshotsAPI, StorageAPI};

$token = ['token' => 'YOUR_TOKEN'];

$crawl = new CrawlingAPI($token); // general-purpose page fetch
$scraper = new ScraperAPI($token); // parsed JSON for supported sites
$leads = new LeadsAPI($token); // domain-scoped email extraction (legacy)
$shots = new ScreenshotsAPI($token); // screenshots of any URL
$storage = new StorageAPI($token); // Cloud Storage CRUD

// Push high-volume async jobs to the Enterprise Crawler via the Crawling API:
// $api->get($url, ['async' => true, 'callback' => '...', 'crawler' => 'YourCrawler']).
// See /docs/crawler for the queue workflow.

Распространённые паттерны

JavaScript-рендеринг

Для SPA, лениво загружаемых лент и страниц, где исходный HTML пуст, создавайте инстанс с JavaScript token и передавайте любую комбинацию page_wait, ajax_wait, scroll и css_click_selector. Порядок, о котором стоит думать: фиксированное ожидание, затем network-idle, затем скролл для ленивой загрузки, затем клик по любому блокирующему элементу UI.

$api = new \Crawlbase\CrawlingAPI(['token' => 'YOUR_JS_TOKEN']);
$res = $api->get('https://spa.example.com', [
 'page_wait' => 2000,
 'ajax_wait' => true,
 'scroll' => true,
]);

Использование встроенного scraper'а

Пропустите парсер целиком на поддерживаемых сайтах. Передайте 'scraper' => 'NAME', и тело ответа станет JSON-строкой со структурированными полями, описанными на странице конкретного scraper'а.

<?php
use Crawlbase\ScraperAPI;

$api = new ScraperAPI(['token' => 'YOUR_TOKEN']);
$res = $api->get('https://www.amazon.com/dp/1098145356',
 ['scraper' => 'amazon-product-details']);
$data = json_decode($res->body, true);
echo $data['name'] . ' - ' . $data['price'];

Гео-маршрутизация

Передайте 'country' => 'ISO', чтобы маршрутизировать crawl через выходные узлы указанной страны. Используйте всякий раз, когда целевой сайт отдаёт локализованный контент в зависимости от IP.

$api = new \Crawlbase\CrawlingAPI(['token' => 'YOUR_TOKEN']);

// Hit the German Amazon catalog from a German residential IP
$res = $api->get('https://www.amazon.com/dp/1098145356', ['country' => 'DE']);

Повторы с backoff

Рекомендуемая форма повторов: экспоненциальный backoff с ограничением в 3–5 попыток, повторять только на временных ошибках (5xx или пустое тело), не повторять на 4xx.

<?php
use Crawlbase\CrawlingAPI;

function crawl(CrawlingAPI $api, string $url, int $attempts = 5) {
 for ($i = 0; $i < $attempts; $i++) {
 $res = $api->get($url);
 if ($res->statusCode === 200 && (int) $res->headers->pc_status === 200) {
 return $res;
 }
 if ($res->statusCode >= 400 && $res->statusCode < 500) {
 throw new RuntimeException("client error {$res->statusCode}: $url");
 }
 usleep((int) (mt_rand() / mt_getrandmax() * pow(2, $i) * 1_000_000));
 }
 throw new RuntimeException("Failed: $url");
}

Async-краулы и вебхуки

Режим fire-and-forget. Вызов SDK немедленно возвращается с rid; Crawlbase отправит POST с результатом на ваш callback URL, когда страница будет готова. Полезно для пакетных задач и медленных целей.

$api = new \Crawlbase\CrawlingAPI(['token' => 'YOUR_TOKEN']);
$res = $api->get('https://example.com', [
 'async' => true,
 'callback' => 'https://your-app.com/webhook',
]);
$rid = $res->rid; // correlate the eventual webhook delivery

// Your Laravel / Symfony / Slim webhook receives a POST with:
// { rid, url, original_status, pc_status, body }

Для очень больших объёмов (миллионы URL) используйте Enterprise Crawler, который стоит перед тем же async-конвейером.

Sticky-сессии

Некоторые сценарии требуют одного и того же residential IP между несколькими вызовами. Передайте cookies_session со стабильным идентификатором, и Crawlbase будет переиспользовать тот же выходной узел в течение примерно 30 минут.

$api = new \Crawlbase\CrawlingAPI(['token' => 'YOUR_JS_TOKEN']);

$session = "checkout-{$userId}";
$api->get('https://shop.example.com/cart', ['cookies_session' => $session]);
$api->get('https://shop.example.com/checkout', ['cookies_session' => $session]);
$api->get('https://shop.example.com/confirm', ['cookies_session' => $session]);

Ошибки и повторы

Платформа возвращает два статус-кода в каждом ответе: собственный ->statusCode SDK (HTTP-статус запроса к самой Crawlbase) и ->headers->pc_status (вердикт Crawlbase по целевому сайту - полный список см. в таблице ошибок Crawling API). Всегда ветвитесь по ->headers->pc_status при принятии решения о повторе - целевой сайт может вернуть 200 с пустым телом, и тогда ->statusCode будет 200, а ->headers->pc_status - 520.

$res = $api->get($url);
$pc = (int) $res->headers->pc_status;

switch (true) {
 case $pc === 200:
 use_body($res->body);
 break;
 case in_array($pc, [520, 525], true):
 // 520 = empty body, 525 = anti-bot couldn't be solved.
 // Switch to JS token and retry.
 retry_with_js_token($url);
 break;
 case in_array($pc, [521, 522, 523], true):
 // Target unreachable or timed out. Retry with backoff.
 schedule_retry($url);
 break;
 default:
 $logger->error('crawl failed', ['url' => $url, 'pc_status' => $pc]);
}

Все повторы запросов к платформе бесплатны - только успешные ответы (pc_status: 200) учитываются в вашей квоте.

Производительность и лучшие практики

  • Переиспользуйте один клиент на token. Создавайте его один раз при старте приложения (service provider в Laravel, service container в Symfony) и инжектьте везде - каждый экземпляр открывает собственное соединение.
  • Используйте самый дешёвый token, который справляется. Не используйте JavaScript token по умолчанию «на всякий случай» - запросы с Normal token быстрее и используют меньше параллелизма. Переходите на JS только тогда, когда ответ Normal пустой или заблокирован анти-бот-защитой.
  • Предпочитайте ajax_wait, а не page_wait. Фиксированные задержки расходуют конкурентность на каждом запросе, даже на быстрых.
  • Для пакетных задач: async + webhook или отправка в Enterprise Crawler. Воркеры очереди, синхронно вызывающие SDK, насытят ваш лимит конкурентности; async + webhook освобождает слот в момент постановки запроса в очередь.
  • Следите за заголовком ответа remaining. В нём указано, сколько слотов конкурентности у вас осталось.

Справочник методов

Все клиентские классы имеют одинаковую поверхность. Конструктор принимает массив опций; глаголы зеркалят соответствующие HTTP-методы.

new CrawlingAPI(['token' => T, 'timeout' => N])
конструктор
Инициализирует клиент с вашим токеном. Опционально: 'timeout' в секундах (по умолчанию 90).
->get($url, $options = [])
метод
Отправляет GET. $options сопоставляет любой параметр Crawling API с его значением.
->post($url, $data, $options = [])
метод
Отправить POST. $data - это body: передайте массив для form-encoded или строку для raw.

Форма ответа - публичные свойства объекта ответа, возвращаемого каждым методом:

->statusCode
int
HTTP-статус запроса SDK к Crawlbase.
->body
string
Содержимое страницы (или JSON-строка, если использовался format=json / scraper=).
->headers
object
Заголовки ответа в виде объекта. Специфичные для Crawlbase поля статуса доступны здесь:
  • ->headers->pc_status: вердикт Crawlbase по целевому сайту (ветвитесь по нему для решений о повторе).
  • ->headers->original_status: HTTP-статус, который целевой сайт вернул Crawlbase.
  • ->headers->storage_url / ->headers->rid: устанавливаются, когда вызов содержал 'store' => true.