登录

SDK 的设计结构

PHP SDK 是对 API Reference 中所记录的 HTTP API 的轻量封装。在原始 HTTP 调用中作为查询字符串附加的每个 Crawling API 参数,都可以通过 SDK 的 options 数组中的键访问:名称、默认值和行为均一一对应。SDK 不会额外添加任何参数,也不会隐藏任何参数。

相比直接使用 cURL 或 Guzzle,使用它能获得:

  • 开箱即用的 URL 编码、参数校验和响应解析。
  • PSR-4 自动加载:可无缝集成到任何现代 PHP 框架中(Laravel、Symfony、Slim)。
  • 每个 Crawlbase API 对应一个客户端类,共享相同的构造函数和调用形式。
  • 合理的默认值(90 秒超时、自动解析 format=json 响应、UTF-8 编码的请求体)。

源码托管于 github.com/crawlbase/crawlbase-php。欢迎提交 Issue 和 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 模型进行认证。每个账号下有两种 token 类型:

  • Normal Token (TCP) - 用于静态 HTML、JSON 端点以及任何不需要浏览器的场景。更快、更便宜。
  • JavaScript Token - 用于 SPA、懒加载内容流以及任何在客户端渲染中隐藏内容的场景。使用 page_waitajax_waitscrollcss_click_selector 时必需。

在生产环境中请使用环境变量(或您框架的配置:Laravel 的 config()、Symfony 的 parameters)。SDK 本身不会读取环境变量,这是有意为之,以便您完全掌控凭证的来源。模式如下:

<?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]);

完整的 token 模型及在控制面板中的位置请参见 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(SDK 与 Crawlbase 之间的 HTTP 状态)和 ->headers->pc_status(Crawlbase 的判定结果,参见下文的 Errors)进行分支判断。传入 ['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_waitajax_waitscrollcss_click_selector。建议的执行顺序:先固定等待,再等待网络空闲,然后滚动以触发懒加载,最后点击任何拦截 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' 即可通过该国家的出口节点进行抓取。当目标站点根据 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']);

带退避的重试

推荐的重试策略:指数退避,最多重试 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");
}

异步抓取 + Webhook

即发即忘模式。SDK 调用立即返回一个 rid;页面就绪后,Crawlbase 会通过 POST 将结果推送到您的回调 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,它就部署在同一条异步管道之前。

粘性会话

有些流程需要在多次调用之间使用相同的住宅 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]);

错误处理与重试

平台会在每个响应中返回两个状态码:SDK 自身的 ->statusCode(向 Crawlbase 发起请求的 HTTP 状态)和 ->headers->pc_status(Crawlbase 对目标站点的判定结果,完整列表参见 Crawling API errors table)。在决定是否重试时,始终应根据 ->headers->pc_status 进行分支判断:目标站点可能返回 200 但响应体为空,此时 ->statusCode200,而 ->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 复用单一客户端实例。 在应用启动时构建一次(Laravel 的 service provider、Symfony 的服务容器),然后在各处注入使用:每个实例都会打开自己的连接。
  • 使用能完成任务的最便宜 token。 不要「以防万一」默认使用 JavaScript token:Normal-token 请求更快,并占用更少的并发额度。仅在 Normal 响应为空或被反爬虫拦截时,再升级到 JS。
  • 优先使用 ajax_wait 而非 page_wait 固定延迟会在每次请求(包括快请求)上消耗并发资源。
  • 批量任务请使用 async + webhook,或推送到 Enterprise Crawler。 同步调用 SDK 的队列工作进程会迅速占满您的并发上限;async + webhook 在请求入队的瞬间就会释放槽位。
  • 关注响应头中的 remaining 它表示您当前剩余的并发槽位数。

方法参考

所有客户端类都共享相同的接口。构造函数接收一个选项数组;方法名与底层 HTTP 方法对应。

new CrawlingAPI(['token' => T, 'timeout' => N])
构造函数
使用您的 token 初始化客户端。可选: 'timeout'(以秒为单位,默认 90)。
->get($url, $options = [])
方法
发送 GET 请求。$options 将任意 Crawling API 参数映射到对应的值。
->post($url, $data, $options = [])
方法
发送 POST 请求。$data 是请求体:传数组则按表单编码,传字符串则按原始内容发送。

响应结构:每个方法返回的响应对象上的公共属性如下:

->statusCode
int
SDK 向 Crawlbase 发起请求的 HTTP 状态码。
->body
string
页面内容(当使用 format=json / scraper= 时为 JSON 字符串)。
->headers
object
响应头作为对象返回。Crawlbase 特有的状态字段在此暴露:
  • ->headers->pc_status:Crawlbase 对目标站点的判定结果(重试决策应基于此字段)。
  • ->headers->original_status:目标站点返回给 Crawlbase 的 HTTP 状态码。
  • ->headers->storage_url / ->headers->rid:当调用中携带 'store' => true 时会被设置。