动态网站Leaflet地图标记坐标抓取求助(RSelenium实现)
解决Leaflet地图标记坐标抓取问题
问题原因
你定位的.MapIcons__marker_icon___vDTMo只是标记的图标DOM元素,Leaflet的坐标数据并不存储在这个元素的属性中,而是保存在Leaflet的JavaScript地图实例对象里,所以通过getElementAttribute获取data-lat/data-lon会失败。
方法一:直接通过JavaScript提取Leaflet标记坐标
RSelenium支持执行原生JavaScript,我们可以直接调用Leaflet的API获取所有标记的坐标:
library(RSelenium) library(dplyr) # 初始化驱动 remote_driver <- rsDriver(browser = "firefox", chromever = NULL, verbose = FALSE, port = 4445L) remDr <- remote_driver$client remDr$navigate("https://www.hejfish.com/d/1356-strobl-wasser-fliegenstrecke-traun") # 等待地图加载完成,提升稳定性 Sys.sleep(3) # 执行JavaScript获取所有标记坐标 marker_coords <- remDr$executeScript(" // 获取页面中的Leaflet地图实例 const map = Object.values(window.L._layers).find(layer => layer instanceof L.Map); const markerList = []; // 遍历地图所有图层,筛选出标记类型 map.eachLayer(function(layer) { if (layer instanceof L.Marker) { const latlng = layer.getLatLng(); markerList.push({lat: latlng.lat, lon: latlng.lng}); } }); return markerList; ")[[1]] # 转换为数据框 coords_df <- bind_rows(marker_coords) print(coords_df) # 关闭驱动 remDr$close() remote_driver$server$stop()
方法二:解析页面脚本中的初始化数据
很多动态网站会把地图数据放在页面的<script>标签的全局变量里,可提取这部分JSON数据来获取坐标:
library(RSelenium) library(jsonlite) library(dplyr) # 初始化驱动 remote_driver <- rsDriver(browser = "firefox", chromever = NULL, verbose = FALSE, port = 4445L) remDr <- remote_driver$client remDr$navigate("https://www.hejfish.com/d/1356-strobl-wasser-fliegenstrecke-traun") Sys.sleep(3) # 获取所有脚本标签 script_elements <- remDr$findElements(using = "tag name", value = "script") # 遍历脚本查找包含标记数据的内容 coords_df <- NULL for (elem in script_elements) { script_text <- elem$getElementText()[[1]] # 匹配包含标记数据的JSON片段,根据页面实际内容调整正则 if (grepl("waypoints|markers", script_text, ignore.case = TRUE)) { # 提取JSON数组部分 json_str <- regmatches(script_text, regexec("(\\[.*?\\])", script_text))[[1]][2] if (!is.na(json_str)) { coords_df <- fromJSON(json_str) %>% select(lat, lon) # 假设JSON里有lat和lon字段 break } } } print(coords_df) # 关闭驱动 remDr$close() remote_driver$server$stop()
注意事项
- 方法一依赖Leaflet的全局API,需确保页面Leaflet库加载完成,可通过
Sys.sleep()等待加载。 - 方法二的正则表达式需要根据页面实际脚本内容调整,比如若页面初始化数据是
window.data = {markers: [...]},则需修改匹配规则。
内容的提问来源于stack exchange,提问作者M.Teich
相关产品推荐
相关产品推荐

