如何用Selenium访问OpenStreetBrowser的SVG元素获取限速数据
解决OpenStreetBrowser瓦片点击与限速数据获取问题
问题分析
你遇到的TimeoutException是因为页面地图瓦片并非直接通过SVG元素暴露,而是由Leaflet类地图库渲染的图片瓦片,道路数据是叠加在瓦片上的矢量图层,直接定位SVG的XPath逻辑不准确。
解决方案步骤
1. 调整元素定位逻辑
放弃直接定位SVG,转而定位地图容器内的可交互矢量图层。OpenStreetBrowser基于Leaflet开发,地图容器#map下的.leaflet-overlay-pane .leaflet-interactive是承载道路数据的可点击层,定位该元素更可靠:
# 等待地图可交互图层加载完成 map_layer = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#map .leaflet-overlay-pane .leaflet-interactive")))
2. 模拟点击道路元素
由于道路是矢量元素,直接点击地图上的道路位置比点击瓦片更精准,可使用ActionChains模拟坐标点击:
from selenium.webdriver.common.action_chains import ActionChains # 获取地图容器的位置参数 map_container = driver.find_element(By.ID, "map") map_x = map_container.location['x'] map_y = map_container.location['y'] # 模拟点击地图中心附近的道路(可根据实际场景调整偏移量) ActionChains(driver).move_to_element_with_offset(map_container, 200, 200).click().perform()
3. 提取弹窗内的限速数据
点击道路后会弹出详情窗口,定位详情按钮并提取限速字段:
# 等待详情按钮可点击并触发 wait.until(EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Details')]"))).click() # 提取限速数据 maxspeed = wait.until(EC.presence_of_element_located((By.XPATH, "//div[contains(text(), 'maxspeed')]/following-sibling::div"))).text print(f"道路限速: {maxspeed}")
4. 优化等待策略
增加地图瓦片加载的等待,避免过早执行后续操作:
# 等待所有地图瓦片加载完成 wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#map .leaflet-tile")))
完整修改代码
from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains driver = webdriver.Chrome() driver.maximize_window() driver.get('https://www.openstreetbrowser.org') wait = WebDriverWait(driver, 20) # 导航至Maxspeed分类 wait.until(EC.element_to_be_clickable((By.XPATH, "//a[contains(text(), 'Transportation')]"))).click() wait.until(EC.element_to_be_clickable((By.XPATH, "//a[contains(text(), 'Individual Traffic')]"))).click() wait.until(EC.element_to_be_clickable((By.XPATH, "//a[contains(text(), 'Maxspeed')]"))).click() # 搜索定位目标区域 wait.until(EC.element_to_be_clickable((By.XPATH, "//ul[@class='tabs-list']//li[@title='search']"))).click() search_input = wait.until(EC.element_to_be_clickable((By.XPATH, "//div[@class='tabs-section nominatim-search selected']//input"))) search_input.send_keys('53.40125254855821,-3.0876670857133757') wait.until(EC.element_to_be_clickable((By.XPATH, "//div[@class='tabs-section nominatim-search selected']//ul//li"))).click() # 等待地图资源加载完成 wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#map .leaflet-tile"))) wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#map .leaflet-overlay-pane .leaflet-interactive"))) # 模拟点击道路位置 map_container = driver.find_element(By.ID, "map") ActionChains(driver).move_to_element_with_offset(map_container, 200, 200).click().perform() # 获取并打印限速数据 wait.until(EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Details')]"))).click() maxspeed = wait.until(EC.presence_of_element_located((By.XPATH, "//div[contains(text(), 'maxspeed')]/following-sibling::div"))).text print(f"道路限速: {maxspeed}") driver.quit()
注意事项
- 地图元素的层级可能随网站更新变化,需定期检查CSS选择器有效性
- 若点击位置不准确,可调整
move_to_element_with_offset的偏移量,或直接使用绝对坐标点击 - 如需批量获取数据,可循环遍历地图区域内的多个坐标点
内容的提问来源于stack exchange,提问作者Satya Pamidi
相关产品推荐
相关产品推荐

