mcpField
S
scraperapi-ruby-sdk

scraperapi-ruby-sdk

github.com/scraperapi开发1099 次安装12 周前更新
代码仓库

关于 scraperapi-ruby-sdk

scraperapi-ruby-sdk 是面向 Ruby 开发者的 ScraperAPI SDK 使用指南,涵盖同步抓取、请求参数和错误处理。它还说明了批量请求使用异步端点及通过结构化数据端点获取 JSON 的方法。

主要功能

  1. 01使用 Ruby 客户端抓取 URL
  2. 02配置渲染、代理与地理定位
  3. 03通过会话复用代理 IP
  4. 04提交异步批量任务
  5. 05请求结构化数据端点

适用场景

  1. 01获取网页 HTML 内容
  2. 02抓取 JavaScript 渲染的页面
  3. 03处理同一域名的分页流程
  4. 04批量抓取 20 个以上 URL

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/scraperapi/scraperapi-skills --skill scraperapi-ruby-sdk

安装后在 Claude Code 中输入/scraperapi-ruby-sdk确认已加载。

详细介绍

ScraperAPI — Ruby SDK 最佳实践

要求: Ruby >= 2.0,gem install scraperapi(或在 Gemfile 中使用 gem 'scraperapi'),SCRAPERAPI_API_KEY 环境变量。

设置

require "scraper_api"

client = ScraperAPI::Client.new(ENV["SCRAPERAPI_API_KEY"])

切勿将 API 密钥硬编码。每次都从环境变量中读取。

基本用法

# Simple GET — returns raw HTML string via .raw_body
html = client.get("https://example.com/").raw_body
puts html

# With a single parameter
html = client.get("https://example.com/", render: true).raw_body

# With multiple parameters
html = client.get(
  "https://example.com/",
  render: true,
  country_code: "us"
).raw_body

参数以关键字参数的形式传入 URL 后。.raw_body 会从响应对象中提取 HTML 字符串。

决策指南

情况方法
单个 URL,同步请求client.get(url, **params).raw_body
页面通过 JavaScript 加载内容传入 render: true
网站会拦截数据中心代理传入 premium: true
最强反机器人保护传入 ultra_premium: true
同一域名上的多步骤/分页流程使用 session_number:
20 个以上的 URL 或批处理作业通过 Net::HTTP 或 Faraday 使用异步端点
受支持的平台(Amazon、Google 等)直接使用结构化数据端点

参数参考

渲染
# Render JavaScript before returning HTML
# Use when: page is a React/Vue/Angular SPA, or initial scrape returns empty/partial content
# Cost: +10 credits
html = client.get("https://spa-site.com/", render: true).raw_body

# Wait for a specific DOM element (requires render: true)
html = client.get(
  "https://spa-site.com/",
  render: true,
  wait_for_selector: ".product-list"
).raw_body

默认不要添加 render: true——先尝试不使用它。它会增加费用和延迟。

代理和地理定位
# Route through a country-specific proxy — no extra credit cost
html = client.get("https://example.com/", country_code: "gb").raw_body

# Premium residential/mobile IPs — for sites that block datacenter proxies
# Cost: 10 credits (25 with render: true)
html = client.get("https://hard-site.com/", premium: true).raw_body

# Ultra-premium — for the toughest anti-bot protections
# Cost: 30 credits (75 with render: true)
# Note: incompatible with keep_headers — custom headers are discarded
html = client.get("https://hardest-site.com/", ultra_premium: true).raw_body

premium 和 ultra_premium 互斥——切勿同时传入。 升级顺序:标准(1 个积分)→ 渲染(10 个积分)→ premium(10 个积分)→ ultra_premium(30 个积分)。

会话(粘性代理)
# Reuse the same proxy IP across requests — useful for pagination and multi-step flows
# Sessions expire 15 minutes after last use; any integer is a valid session ID
html1 = client.get("https://example.com/page1", session_number: 42).raw_body
html2 = client.get("https://example.com/page2", session_number: 42).raw_body
标头和设备类型
# Forward custom headers to the target site
# Note: keep_headers is ignored when ultra_premium: true
html = client.get(
  "https://example.com/",
  keep_headers: true
  # Pass additional headers via the underlying request object as needed
).raw_body

# Emulate a mobile or desktop browser user-agent
html = client.get("https://example.com/", device_type: "mobile").raw_body
自动解析
# Return structured JSON instead of HTML for supported sites
# Use for Amazon, Google, and other supported platforms when you want clean data
json_result = client.get("https://amazon.com/dp/B09V3KXJPB", autoparse: true).raw_body

升级阶梯

始终从成本最低的选项开始,仅在遭到拦截时升级。

def scrape_with_escalation(client, url)
  tiers = [
    {},
    { render: true },
    { premium: true },
    { premium: true, render: true },
    { ultra_premium: true },
  ]

  tiers.each do |params|
    result = client.get(url, **params).raw_body
    return result if result&.include?("<html")
  end

  nil
end

异步作业(用于批处理)

此 SDK 为同步模式——每次 client.get 都会阻塞,直到收到响应(最长 70 秒)。 对于 20 个以上的 URL,请通过 REST 端点提交异步作业。

require "net/http"
require "json"

API_KEY = ENV["SCRAPERAPI_API_KEY"]

def submit_job(url, api_params = {})
  uri = URI("https://async.scraperapi.com/jobs")
  payload = { apiKey: API_KEY, url: url, apiParams: api_params }
  response = Net::HTTP.post(uri, payload.to_json, "Content-Type" => "application/json")
  JSON.parse(response.body) # { "id" => "...", "statusUrl" => "..." }
end

def poll_job(job, max_wait: 120, interval: 5)
  deadline = Time.now + max_wait
  while Time.now < deadline
    uri = URI(job["statusUrl"])
    data = JSON.parse(Net::HTTP.get(uri))
    return data.dig("response", "body") if data["status"] == "finished"
    raise "Job #{job['id']} failed" if data["status"] == "failed"
    sleep interval
  end
  raise "Job #{job['id']} timed out"
end

# Submit all URLs, then collect results
urls = ["https://example.com/page1", "https://example.com/page2"]
jobs = urls.map { |u| submit_job(u) }
results = jobs.map { |j| poll_job(j) }

结构化数据端点

对于受支持的平台,请使用结构化端点获取干净的 JSON,无需解析 HTML。

require "net/http"
require "json"

def structured_get(vertical, params = {})
  query = URI.encode_www_form({ api_key: API_KEY }.merge(params))
  uri = URI("https://api.scraperapi.com/structured/#{vertical}?#{query}")
  response = Net::HTTP.get_response(uri)
  raise "Error #{response.code}" unless response.is_a?(Net::HTTPSuccess)
  JSON.parse(response.body)
end

# Google SERP
results = structured_get("google/search", { query: "ruby web scraping" })

# Amazon product details
product = structured_get("amazon/product", { asin: "B09V3KXJPB" })

# eBay search
listings = structured_get("ebay/search", { query: "mechanical keyboard" })

错误处理

HTTP 错误会使 SDK 抛出异常。请检查状态码以确定正确的处理方式。

def safe_scrape(client, url, params = {})
  client.get(url, **params).raw_body
rescue => e
  status = e.respond_to?(:response) ? e.response&.code&.to_i : nil
  case status
  when 401 then raise "Invalid API key — check SCRAPERAPI_API_KEY"
  when 403 then raise "Blocked or out of credits — try premium: true or ultra_premium: true"
  when 429 then raise "Rate limit hit — reduce concurrency or switch to async"
  when 500, 503 then raise "Transient error — retry with exponential backoff"
  else raise
  end
end

状态码参考:200 表示成功,401 表示密钥无效,403 表示遭到拦截/没有积分,404 表示未找到目标, 429 表示速率限制,500/503 表示暂时性错误(不收费,可安全重试)。

积分费用参考

请求类型积分
标准1
render: true10
premium: true10
premium: true, render: true25
ultra_premium: true30
ultra_premium: true, render: true75

文档

评论

支持 Markdown