You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用R的googleway包获取德国献血点完整列表并去重?

问题描述

使用R语言的googleway包调用google_places函数,以德语搜索词Blutspende in Deutschland获取德国献血点数据。已知API每次返回20条结果,预估德国约有300个献血点,因此编写循环分页获取数据,但最终得到的202条数据中仅54条为唯一值,存在大量重复,需要优化循环以获取无重复的完整结果。

现有代码如下:

library(googleway)
# 初始化列表
datalist = list()

# 首次搜索
key = "YOUR-KEY"

res <- google_places(search_string = "Blutspende in Deutschland",
                     key = key)

# 存储首次20条结果
datalist[[1]] <- data.frame(Name = res$results$name,
                            Place = res$results$formatted_address)

# 设置下一页token
token = res$next_page_token

for(i in 1:10){
  # 等待时间
  Sys.sleep(2)
  
  # 下一页搜索
  res_n <- google_places(search_string = "Blutspende in Deutschland",
                         page_token  = token,
                         key = key)
  
  # 存储下一页结果
  datalist[[i+1]] <- data.frame(Name = res_n$results$name,
                              Place = res_n$results$formatted_address)
  
  # 更新下一页token
  token <- res_n$next_page_token
  
  # 打印状态
  aa = res_n$status
  cat(i, aa, '\n')
}

# 合并为数据框
big_data = do.call(rbind, datalist)

原去重验证代码:

library(tidyverse)
big_data %>% distinct() %>% nrow()

重复原因分析

  1. 唯一标识缺失:原代码仅用名称和地址去重,但不同献血点可能名称/地址相似,或同一献血点的地址格式存在细微差异;谷歌Places API返回的place_id是每个地点的唯一标识符,应以此作为去重依据。
  2. 循环终止条件不合理:固定循环10次,可能导致重复请求已获取过的页面,或提前终止未取完所有结果。
  3. Token生效时间不足:谷歌API的next_page_token需要短暂延迟才能生效,2秒等待时间可能不够,导致请求返回重复结果。
  4. 未实时去重:每次获取新结果后未先去重再合并,导致重复数据不断累积。

优化后的代码

library(googleway)
library(tidyverse)

# 初始化总数据框,包含唯一标识place_id
total_data <- tibble(
  place_id = character(),
  name = character(),
  formatted_address = character()
)

key <- "YOUR-KEY"
search_term <- "Blutspende in Deutschland"

# 首次搜索
res <- google_places(search_string = search_term, key = key)

# 提取首次结果并去重
new_data <- tibble(
  place_id = res$results$place_id,
  name = res$results$name,
  formatted_address = res$results$formatted_address
) %>% distinct(place_id, .keep_all = TRUE)

total_data <- bind_rows(total_data, new_data)

token <- res$next_page_token
page_count <- 1

# 循环获取所有分页,直到没有下一页token或无新结果
while(!is.null(token)) {
  # 延长等待时间,确保token生效
  Sys.sleep(3)
  
  page_count <- page_count + 1
  res_n <- google_places(search_string = search_term, page_token = token, key = key)
  
  # 检查请求状态
  status <- res_n$status
  cat("第", page_count, "页,状态:", status, "\n")
  
  if(status != "OK") {
    # 处理异常状态:请求超限则延长等待,无效token则终止
    if(status == "OVER_QUERY_LIMIT") {
      cat("请求超限,等待10秒后重试...\n")
      Sys.sleep(10)
      next
    } else {
      cat("请求失败,终止循环\n")
      break
    }
  }
  
  # 提取新结果并去重
  new_data <- tibble(
    place_id = res_n$results$place_id,
    name = res_n$results$name,
    formatted_address = res_n$results$formatted_address
  ) %>% distinct(place_id, .keep_all = TRUE)
  
  # 只添加之前未出现过的结果
  new_unique_data <- anti_join(new_data, total_data, by = "place_id")
  
  if(nrow(new_unique_data) == 0) {
    cat("无新结果,终止循环\n")
    break
  }
  
  total_data <- bind_rows(total_data, new_unique_data)
  token <- res_n$next_page_token
}

cat("共获取", nrow(total_data), "个唯一献血点\n")

验证唯一结果数量

# 直接查看总数据行数即为唯一数量
nrow(total_data)

# 再次确认去重(冗余但保险)
total_data %>% distinct(place_id) %>% nrow()

内容的提问来源于stack exchange,提问作者Marco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 09:35:24