登录

SDK 的设计形态

Ruby gem 是对 API Reference 中所记录的同一 HTTP API 的轻量封装。在原始 HTTP 调用中作为查询字符串附加的每个 Crawling API 参数,都可以作为关键字参数在 gem 中调用,名称、默认值和行为一一对应。gem 不会增加任何参数,也不会隐藏任何参数。

相比直接使用 Net::HTTP / Faraday,使用 gem 的好处:

  • URL 编码、参数校验和响应解析开箱即用,应用代码可以专注于业务逻辑。
  • 地道的 Ruby 接口:关键字参数、snake_case 参数命名、传输失败时抛出异常、朴素的 Ruby 响应对象。
  • 每个 Crawlbase API 对应一个客户端类,所有类共享相同的构造器 / 调用形态。
  • 合理的默认值(90 秒超时、自动解析 format=json 响应、UTF-8 编码的响应体)—— 与大多数团队首次集成时手动配置的结果一致。

源码位于 github.com/crawlbase/crawlbase-ruby。欢迎提交 Issues 和 PR。

安装

最新版本发布在 RubyGems 上。已在 Ruby 2.7、3.0、3.1、3.2、3.3 + JRuby 上测试通过。

gem install crawlbase

# Or in your Gemfile
gem 'crawlbase'

身份认证

每个 Crawlbase API 都使用相同的 token 认证模型。同一个账号下有两种 token:

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

在生产环境中,使用 Rails credentials(Rails.application.credentials.crawlbase_token)或环境变量。gem 本身不会读取它们,这是有意为之,便于您完全掌控凭据的来源。模式如下:

require 'crawlbase'

# Pick the right token at instantiation; the gem doesn't switch
# tokens per-call, so keep two clients if you alternate.
api = Crawlbase::API.new(token: ENV.fetch('CRAWLBASE_TOKEN'))
js = Crawlbase::API.new(token: ENV.fetch('CRAWLBASE_JS_TOKEN'))

api.get('https://github.com/anthropic')
js.get('https://feed.example.com', page_wait: 2000)

完整的 token 模型与控制台位置见 Authentication 页面。

快速开始

从 require 到爬取 HTML,只需三行:

require 'crawlbase'

api = Crawlbase::API.new(token: 'YOUR_TOKEN')
res = api.get('https://github.com/anthropic')

puts res.body if res.status_code == 200

在决定是否重试时,基于 .status_code(gem 到 Crawlbase 的 HTTP 状态)和 .pc_status(Crawlbase 的判定结果,详见下方 Errors)进行分支判断。传入 format: 'json' 可获得 JSON 包装的响应,而非原始页面内容。

所有 API 集于一个 gem

每个 Crawlbase API 都有对应的类。相同的构造器、相同的 get / post 方法。

require 'crawlbase'

token = { token: 'YOUR_TOKEN' }

crawl = Crawlbase::API.new(**token) # general-purpose page fetch
scraper = Crawlbase::ScraperAPI.new(**token) # parsed JSON for supported sites
leads = Crawlbase::LeadsAPI.new(**token) # domain-scoped email extraction (legacy)
shots = Crawlbase::ScreenshotsAPI.new(**token) # screenshots of any URL
storage = Crawlbase::StorageAPI.new(**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、懒加载的 feed,以及初始 HTML 为空的页面,请使用 JavaScript token 实例化,并传入 page_waitajax_waitscrollcss_click_selector 的任意组合。建议的思考顺序:先固定等待,再等待网络空闲,然后滚动以触发懒加载,最后点击任何门控的 UI 元素。

api = Crawlbase::API.new(token: 'YOUR_JS_TOKEN')
res = api.get('https://spa.example.com',
 page_wait: 2000,
 ajax_wait: true,
 scroll: true)

使用内置 scraper

在受支持的网站上完全跳过解析器。传入 scraper: 'NAME',响应体就会变成一个 JSON 字符串,包含对应 scraper 页面所记录的结构化字段。

require 'crawlbase'
require 'json'

api = Crawlbase::ScraperAPI.new(token: 'YOUR_TOKEN')
res = api.get('https://www.amazon.com/dp/1098145356',
 scraper: 'amazon-product-details')
data = JSON.parse(res.body)
puts data['name'], data['price']

地理路由

传入 country: 'ISO' 即可通过该国家的出口节点路由爬取请求。当目标网站根据 IP 提供本地化内容时使用。

api = Crawlbase::API.new(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 重试。

require 'crawlbase'

api = Crawlbase::API.new(token: 'YOUR_TOKEN')

def crawl(api, url, attempts: 5)
 attempts.times do |i|
 res = api.get(url)
 return res if res.status_code == 200 && res.pc_status.to_i == 200
 raise "client error: %d" % res.status_code if (400..499).include?(res.status_code)
 sleep(rand * (2**i)) # exponential backoff with jitter
 end
 raise "Failed: %s" % url
end

异步爬取 + webhook

即发即弃模式。gem 调用立即返回一个 rid;页面就绪后 Crawlbase 会以 POST 方式将结果发送到您的回调 URL。适合批处理任务和响应较慢的目标。

api = Crawlbase::API.new(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 Rails / Sinatra webhook receives a POST with:
# { rid, url, original_status, pc_status, body }

对于超大规模(数百万 URL),请使用 Enterprise Crawler,它位于这套异步管道的前端。

粘性会话

某些流程需要在多次调用中复用同一个住宅 IP。传入带稳定标识符的 cookies_session,Crawlbase 会在约 30 分钟内复用同一个出口节点。

api = Crawlbase::API.new(token: 'YOUR_JS_TOKEN')

session = "checkout-#{user_id}"
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)

错误处理与重试

平台在每个响应中都会返回两个状态码:gem 自身的 .status_code(请求到 Crawlbase 本身的 HTTP 状态)和 .pc_status(Crawlbase 对目标站点的判定结果,完整列表见 Crawling API errors table)。在决定是否重试时,请始终基于 .pc_status 进行判断:目标站点可能返回 200 但响应体为空,此时 .status_code200,而 .pc_status520

res = api.get(url)
pc = res.pc_status.to_i

case pc
when 200
 use(res.body)
when 520, 525
 # 520 = empty body, 525 = anti-bot couldn't be solved.
 # Switch to JS token and retry.
 retry_with_js_token(url)
when 521, 522, 523
 # Target unreachable or timed out. Retry with backoff.
 schedule_retry(url)
else
 Rails.logger.error('crawl failed', url: url, pc_status: pc)
end

针对平台的所有重试都是免费的,只有成功响应(pc_status: 200)才会计入您的配额。

性能与最佳实践

  • 每个 token 复用一个客户端。 构造器开销很小,但每个实例都会打开自己的连接。在应用启动时构建一次(Rails initializer 是自然的位置),然后在所有请求间共享。
  • 使用能跑通的最便宜的 token。 不要为了「以防万一」而默认使用 JavaScript token,Normal token 的请求更快、占用并发更少。仅当 Normal 响应为空或被反爬拦截时再升级到 JS。
  • 优先使用 ajax_wait 而不是 page_wait 固定延迟会在每次请求上消耗并发额度,即使是很快的请求也不例外。
  • 批处理任务:使用异步 + webhook,或推送到 Enterprise Crawler。 Sidekiq worker 同步调用 gem 会很快打满您的并发上限;异步 + webhook 在请求被排队的瞬间就释放了占用槽位。
  • 关注响应头中的 remaining 它会返回您剩余的并发槽数,主动退避,在触及上限之前提前调整,而不是被动应对 429。

方法参考

所有客户端类共享相同的接口。构造器接受关键字参数;方法名与底层 HTTP 方法对应。

Crawlbase::API.new(token:, timeout:)
构造器
使用您的 token 初始化客户端。可选参数:timeout,以秒为单位(默认 90)。
#get(url, **options)
方法
发送 GET 请求。options 将任何 Crawling API 参数映射为对应的值。返回响应对象。
#post(url, data, **options)
方法
发送一个 POST 请求。data 是 body:传入哈希为 form-encoded,传入字符串为原始数据。

响应结构 —— 响应对象上的方法:

.status_code
Integer
gem 向 Crawlbase 发起请求的 HTTP 状态码。
.pc_status
Integer
Crawlbase 对目标站点的判定结果。可基于此值决定是否重试。
.original_status
Integer
目标站点返回给 Crawlbase 的 HTTP 状态码。
.url
String
经目标站点重定向后的最终 URL。
.body
String
页面内容(当使用 format=json / scraper= 时为 JSON 字符串)。
.headers
Hash
来自目标站点的响应 headers。
.rid
String
请求 ID(当 async: truestore: true 时)。