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

