无法点击地图上的标志

Posted

技术标签:

【中文标题】无法点击地图上的标志【英文标题】:Unable to click on signs on a map 【发布时间】:2019-02-07 14:22:28 【问题描述】:

我用 Python 编写了一个与 selenium 相关的脚本,用于单击地图中的每个可用标志。但是,当我执行我的脚本时,它会在到达wait.until(EC.staleness_of(item)) 这一行时引发timeout exception 错误。

在点击该行之前,脚本应该点击过一次,但它不能?如何循环点击该地图中的所有标志?

This is the site link.

这是我目前的代码(也许,我正在尝试使用错误的选择器):

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

link = "https://www.findapetwash.com/"

driver = webdriver.Chrome()
driver.get(link)
wait = WebDriverWait(driver, 15)
for item in wait.until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "#map .gm-style"))):
    item.click()
    wait.until(EC.staleness_of(item))
driver.quit()

该地图上可见的标志,例如:

发布脚本:我知道这是他们的 API https://www.findapetwash.com/api/locations/getAll/,我可以使用它获取 JSON 内容,但我想坚持 Selenium 方式。谢谢。

【问题讨论】:

我不认为你可以,这些标志不是 html 的一部分。作为一种解决方法,您可以打开右侧的列表并单击其中的项目,但如果这不仅仅是为了练习,我认为 API 是您的最佳解决方案。 【参考方案1】:

如果由于某些原因无法使用 API,您可以使用 Selenium 逐个单击。也可以提取每个标志的信息,而无需使用 Selenium 点击它们。

这里代码一一点击:

signs = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "li.marker.marker--list")))
for sign in signs:
     driver.execute_script("arguments[0].click();", sign)
     #do something

不用等待也可以尝试,可能会成功。

【讨论】:

【参考方案2】:

我知道你写过你不想使用 API,但是使用 Selenium 从地图标记中获取位置似乎有点矫枉过正,相反,为什么不使用请求调用他们的 Web 服务并解析返回json?

这是一个工作脚本:

import requests
import json

api_url='https://www.findapetwash.com/api/locations/getAll/'

class Location:
    def __init__(self, json):
        self.id=json['id']
        self.user_id=json['user_id']
        self.name=json['name']
        self.address=json['address']
        self.zipcode=json['zipcode']
        self.lat=json['lat']
        self.lng=json['lng']
        self.price_range=json['price_range']
        self.photo='https://www.findapetwash.com' + json['photo']

def get_locations():
    locations = []
    response = requests.get(api_url)
    if response.ok:
        result_json = json.loads(response.text)
        for location_json in result_json['locations']:
            locations.append(Location(location_json))

        return locations
    else:
        print('Error loading locations')
        return False

if __name__ == '__main__':
    locations = get_locations()
    for l in locations:
        print(l.name)

如果您仍然想采用 Selenium 方式,而不是等到所有元素都加载完毕,您可以暂停脚本几秒钟甚至一分钟以确保所有内容都已加载,这应该可以解决超时异常:

import time 

driver.get(link)
# Wait 20 seconds
time.sleep(20)

有关其他可能的解决方法,请参阅此处接受的答案:Make Selenium wait 10 seconds

【讨论】:

OP 明确表示他们宁愿不使用 API 并坚持使用 Selenium 编辑:现在看来已得到解决 我知道,但是代码伤害了我的眼睛,所以我写了一个更安全的解决方案。不过我加了一句,谢谢。 使用 API 绝对是更优雅的方式,同意

以上是关于无法点击地图上的标志的主要内容,如果未能解决你的问题,请参考以下文章

如何百度地图上面添加公司的标识?

如何在网页上自动化谷歌地图图像?

怎样在百度地图导航路线上添加经过地点

如何将百度上的地图上转化成为arcgis地图

当用户点击地图上的(商业)地点时如何获取点击事件

地图悬停和点击谷歌地图