使用R语言抓取Google Maps遇到的三类技术问题求助
解决方案:Google Maps门店数据抓取的三个问题修复
问题1:评分缺失导致数据无法匹配
不要单独提取名称和评分列表,先定位每个门店的独立父容器,再在每个容器内分别抓取名称和评分。这样无评分的门店会自动返回NA,保证数据一一对应。
Google Maps搜索结果的每个门店条目父容器通常是.Nv2PK(可根据实际页面结构微调),代码调整如下:
# 提取每个门店的父节点 outlets <- html_obj %>% html_elements(".Nv2PK") # 批量提取每个门店的名称和评分 outlet_data <- lapply(outlets, function(node) { name <- node %>% html_element(".hfpxzc") %>% html_attr("aria-label") rating <- node %>% html_element(".ZkP5Je") %>% html_attr("aria-label") data.frame(name = name, rating = rating, stringsAsFactors = FALSE) }) %>% bind_rows()
问题2:地址提取失败
Google Maps的地址通常在门店父容器内的.W4Efsd元素组中,一般是第二行文本。在上述批量提取逻辑中添加地址提取即可:
outlet_data <- lapply(outlets, function(node) { name <- node %>% html_element(".hfpxzc") %>% html_attr("aria-label") rating <- node %>% html_element(".ZkP5Je") %>% html_attr("aria-label") # 提取地址:取.W4Efsd下的第二个文本节点 address <- node %>% html_element(".W4Efsd:nth-child(2)") %>% html_text() data.frame(name = name, rating = rating, address = address, stringsAsFactors = FALSE) }) %>% bind_rows()
如果页面结构有变化,也可以用html_elements(".W4Efsd")获取所有文本行,再取对应位置的元素(比如索引2)。
问题3:侧边栏滚动加载
用RSelenium执行JavaScript滚动比模拟按键更稳定,直接定位侧边栏元素并滚动到底部,还可以循环滚动直到加载完所有内容:
# 定位侧边栏元素(Google Maps搜索结果侧边栏常用选择器) sidebar <- myclient$findElement(using = "css selector", value = ".m6QErb.DxyBCb.kA9KIf.dS8AEf") # 循环滚动直到无新内容加载 prev_height <- 0 while(TRUE) { current_height <- myclient$executeScript("return arguments[0].scrollHeight;", list(sidebar))[[1]] if(current_height == prev_height) break myclient$executeScript("arguments[0].scrollTop = arguments[0].scrollHeight;", list(sidebar)) Sys.sleep(2) # 等待页面加载 prev_height <- current_height }
完整修改后代码
pacman::p_load(rvest, xml2, RSelenium, dplyr) rmDr <- rsDriver(browser = "firefox", port=4443L)$client myclient <- rmDr myclient$navigate("https://www.google.com/maps/search/attea/@1.3586881,103.8165833,12z/data=!3m1!4b1") # 滚动加载所有门店 sidebar <- myclient$findElement(using = "css selector", value = ".m6QErb.DxyBCb.kA9KIf.dS8AEf") prev_height <- 0 while(TRUE) { current_height <- myclient$executeScript("return arguments[0].scrollHeight;", list(sidebar))[[1]] if(current_height == prev_height) break myclient$executeScript("arguments[0].scrollTop = arguments[0].scrollHeight;", list(sidebar)) Sys.sleep(2) prev_height <- current_height } # 提取页面HTML并解析 html_obj <- myclient$getPageSource(header = TRUE)[[1]] %>% read_html() # 批量提取门店数据 outlets <- html_obj %>% html_elements(".Nv2PK") outlet_data <- lapply(outlets, function(node) { name <- node %>% html_element(".hfpxzc") %>% html_attr("aria-label") rating <- node %>% html_element(".ZkP5Je") %>% html_attr("aria-label") address <- node %>% html_element(".W4Efsd:nth-child(2)") %>% html_text() data.frame(name = name, rating = rating, address = address, stringsAsFactors = FALSE) }) %>% bind_rows() print(outlet_data) myclient$close() rmDr$server$stop()
内容的提问来源于stack exchange,提问作者Skyzf
相关产品推荐
相关产品推荐

