在Ruby中调用Google Places API获取下一页结果遇重复问题
问题排查:Google Places Text Search 传入next_page_token返回重复结果
核心问题分析
你的代码里有两个关键错误导致分页无效:
错误的next_page_token获取方式
你用@results.last&.dig('next_page_token')尝试获取下一页token,但@results存储的是所有商家的结果数组——单个商家数据里根本没有next_page_token字段,这个字段只存在于每次请求返回的完整响应对象(也就是fetch_page返回的JSON结构)里。分页逻辑的状态丢失
你只把响应里的results数组合并到@results,没有保留当前响应的完整信息,导致后续循环时无法拿到正确的下一页token,最终发起的是不带page_token的重复请求,自然返回第一页结果。
修复后的代码
1. 修正分页循环逻辑
def extract current_page_token = nil loop do page = fetch_page(current_page_token) break if page.nil? || page['results'].empty? @results += page['results'] # 直接从当前page对象里拿下一页token current_page_token = page['next_page_token'] break if current_page_token.nil? # Google要求next_page_token生成后需等待至少1秒才能使用,1秒足够,无需10秒 sleep(1) end @results = @results.map do |result| result_details = fetch_place_details(result['place_id']) result.merge(result_details) end upsert_businesses(clean_data(@results)) end
2. 修复Place Details API的参数问题
你之前复用了@params(包含query参数)调用Details API,这是冗余且不符合API要求的,应该单独构造请求参数:
def fetch_place_details(place_id) params = { place_id: place_id, fields: 'name,formatted_phone_number,formatted_address,website,place_id,types', key: API_KEY } response = RestClient.get(DETAILS_ENDPOINT, params: params) return {} unless response.code == 200 details = JSON.parse(response.body)['result'] details || {} end
3. 增强API错误处理(可选)
除了HTTP状态码,还要检查Google API返回的业务状态,避免无效请求:
def fetch_page(page_token) params = @params.dup params[:page_token] = page_token if page_token.present? response = RestClient.get(SEARCH_ENDPOINT, params: params) return nil unless response.code == 200 data = JSON.parse(response.body) if data['status'] != 'OK' && data['status'] != 'ZERO_RESULTS' puts "Places API Error: #{data['status']} - #{data['error_message']}" return nil end data end
额外注意事项
- Google的
next_page_token有有效期(通常几分钟),且只能使用一次,不要重复使用同一个token。 - 控制请求频率,避免触发
OVER_QUERY_LIMIT,官方限制是10次/秒,1秒延迟足够覆盖分页请求的间隔。
内容的提问来源于stack exchange,提问作者Ben Cheng
相关产品推荐
相关产品推荐

