Ruby 调用谷歌搜索 API:net/http 与 json 标准库实战

Ruby 做脚本和小工具依然顺手,而且这篇的客户端只用标准库 ------net/http 加 json,连 gem 都不用装,ruby serp_client.rb 直接跑。适合给运维脚本、Sidekiq 任务或任意老项目里加一个搜索数据源。

客户端代码

ruby 复制代码
# serp_client.rb
require 'net/http'
require 'json'
require 'uri'

class SerpClient
  API_URL = URI('https://api.serpbase.dev/google/search')

  def initialize(api_key)
    @api_key = api_key
  end

  # 信封:status 为 0 表示成功;失败时 error 带原因、credits_charged 为 0(不扣费)
  def search(q, hl: 'en', gl: 'us', page: 1)
    body = { q: q, hl: hl, gl: gl, page: page }.to_json

    http = Net::HTTP.new(API_URL.host, API_URL.port)
    http.use_ssl = true
    http.open_timeout = 10
    http.read_timeout = 30

    resp = http.post(API_URL.path, body,
      'X-API-Key'    => @api_key,
      'Content-Type' => 'application/json')

    data = JSON.parse(resp.body)
    if data['status'] != 0
      raise SerpApiError.new(data['status'], data['error'])
    end
    data
  end

  class SerpApiError < StandardError
    attr_reader :code
    def initialize(code, message)
      @code = code
      super("SERP API error #{code}: #{message}")
    end
  end
end

# 用法
client = SerpClient.new(ENV['SERPBASE_API_KEY'])
data = client.search('mechanical keyboard review')

data['organic'].each do |r|
  puts format('%3d  %s', r['rank'], r['title'])
  puts "     #{r['link']}"
end

信封结构、参数表(q/hl/gl/page/device)与 organic 字段定义以 SerpBase 官方文档 为准;rank 是本页内的 1 起算位次,titlelink 是每条必有字段,snippetdisplay_url 等为可选------取值前用 r['snippet'] 拿到的是 nil 也别当异常处理。

错误分诊表

信号 含义 动作
SerpApiError 1001 key 缺失/无效 不重试,查配置
SerpApiError 1020 余额不足 告警,人工充值
SerpApiError 1029 触发限流 指数退避重试,最多 3 次
Net::OpenTimeout / Net::ReadTimeout 连接/读取超时 重试一次,再失败记日志
JSON::ParserError 响应非 JSON 记录原始响应前 200 字符

计费口径:search 端点每次成功请求 1 credit;100 次免费试用够在开发环境把这个类调稳,标准包 $0.50/1k 起。

三个 Ruby 特有的坑

  1. Net::HTTPuse_ssl = true :https 地址忘了这行会直接报 use_ssl 错误;URI.parse 不会自动开。把 open/read 超时显式设置,默认值在网络抖动时偏长。
  2. data['status'] 的类型 :JSON 里数字就是 Integer,直接 != 0 判断即可;但如果哪天信封升级成字符串,'0' != 0 会误报------防御性写法是 data['status'].to_i != 0
  3. 别忘了键是字符串 :JSON.parse 默认返回字符串键的 Hash,data[:organic] 永远是 nil,要写 data['organic'];装 symbolize_names: true 参数也行,但团队统一一种风格更重要。

FAQ

为什么不装 httparty 或 faraday? 一个 POST 接口用不上它们;标准库版零依赖,扔进任何项目都不会引起 gem 冲突。等第二个接口出现再抽公共模块不迟。

怎么翻页? search(q, page: 2),page 从 1 起;organic 为空或与上页重复就停。

PAA、相关搜索怎么拿? 返回里是可选模块:data['people_also_ask']data['related_searches'],用 data.fetch('related_searches', []) 兜底遍历;字段结构以实际返回和文档为准,先原样存 JSON 再建模。

serp_client.rb 放进 lib/,配一行环境变量,Rake 任务和 cron 脚本里就都能拿结构化搜索结果了。

相关推荐
Elastic 中国社区官方博客4 小时前
使用 Elasticsearch 和 Jina 进行 AI 视频搜索:精准找到你需要的视频片段秒数
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
Y38153266218 小时前
C# 调用谷歌搜索 API:HttpClient 与 System.Text.Json 实战
搜索引擎·.net
piikee1 天前
论坛帖子百度收录越来越慢?提高收录速度实测案例
搜索引擎·百度收录·必应快收·好用蜘蛛池·蜘蛛1号·收录慢
goujunwe1 天前
GEO 评估方法:如何自测你的内容,会不会被 AI 引用
搜索引擎·网络安全·游戏引擎·全文检索·中文分词
hi_ro_a3 天前
基于正倒排索引的boost搜索引擎
linux·c++·搜索引擎·项目
LaughingZhu3 天前
Product Hunt 每日热榜 | 2026-09-17
人工智能·深度学习·神经网络·搜索引擎·百度
Y3815326623 天前
SEO 周报自动化:从采集数据到一页报告
数据库·搜索引擎
程序员黎剑3 天前
RabbitMQ-消息可靠性-publisher-confirm持久化与手动ack
分布式·rabbitmq·ruby
我也要在julius_bar里藏钱3 天前
【山竹记账后端】1.搭建后端项目
后端·ruby·rails