【问题标题】:Can't fetch titles from some box-like containers无法从一些类似盒子的容器中获取标题
【发布时间】:2018-12-29 03:03:14
【问题描述】:

我在pythonselenium 中编写了一个脚本,用于单击网页地图上的一些可用点。单击一个点时,会弹出一个包含相关信息的小框。

Link to that site

我想解析每个框的标题。当我执行我的脚本时,它会在单击一个点时引发错误。怎样才能成功?

这是脚本:

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 = "replace with above link"

driver = webdriver.Chrome()
driver.get(link)
wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,"#mapDiv_zoom_slider .esriSimpleSliderIncrementButton"))).click()
for item in wait.until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR,"#NWQMC_VM_directory_June2016_3915_0_layer circle"))):
    item.click()

我遇到的错误:

line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: unknown error: Element <circle fill="rgb(237, 81, 81)" fill-opacity="1" stroke="rgb(153, 153, 153)" stroke-opacity="1" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="4" cx="720" cy="430" r="4" transform="matrix(1.00000000,0.00000000,0.00000000,1.00000000,0.00000000,0.00000000)" fill-rule="evenodd" stroke-dasharray="none" dojoGfxStrokeStyle="solid"></circle> is not clickable at point (720, 430). Other element would receive the click: <circle fill="rgb(20, 158, 206)" fill-opacity="1" stroke="rgb(153, 153, 153)" stroke-opacity="1" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="4" cx="720" cy="430" r="4" transform="matrix(1.00000000,0.00000000,0.00000000,1.00000000,0.00000000,0.00000000)" fill-rule="evenodd" stroke-dasharray="none" dojoGfxStrokeStyle="solid"></circle>
  (Session info: chrome=67.0.3396.99)
  (Driver info: chromedriver=2.36.540470 (e522d04694c7ebea4ba8821272dbef4f9b818c91),platform=Windows NT 6.1.7601 SP1 x86)

这是弹出框的方式:

【问题讨论】:

    标签: python python-3.x selenium selenium-webdriver web-scraping


    【解决方案1】:

    @Andrei Suvorkov 非常接近 (+1)

    尝试下面的代码以获得所需的输出:

    from selenium.webdriver.common.action_chains import ActionChains
    
    driver = webdriver.Chrome()
    driver.get(link)
    wait = WebDriverWait(driver, 5)
    driver.maximize_window()
    
    items = wait.until(EC.presence_of_all_elements_located((By.XPATH, "//*[name()='svg']//*[name()='circle']")))
    for item in items:
        ActionChains(driver).move_to_element(item).click(item).perform()
        popup = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "contentPane")))
        print(popup.text)
        wait.until(EC.visibility_of_element_located((By.XPATH, "//div[contains(@class, 'close')]"))).click()
    

    【讨论】:

    • 太棒了!我不知道这个WebDriverWait(popup, 5)。我以为它只适用于司机
    • @AndreiSuvorkov ,哦...实际上那个代码是多余的))但是,如果你想在 ExplicitWait 中使用相对 XPath,你应该像 element = wait(driver, 5).until(EC.visibility_of_element_located((By.XPATH, "//node")))another_element = wait(element, 5).until(EC.visibility_of_element_located((By.XPATH, ".//another_node"))) 那样做>
    • 我没有关闭我的电脑只是因为我注意到你在线@sir Andersson。只要你有空,就几乎没有失败的机会。非常感谢。它做得非常好。
    【解决方案2】:

    要回答您的特定问题,您不能像往常一样与 svg 元素进行交互。为此,您必须像我在示例中提供的那样使用xPath。你也不能像往常一样点击这些元素,但你可以使用ActionChains

    wait = WebDriverWait(driver, 5)
    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,"#mapDiv_zoom_slider .esriSimpleSliderIncrementButton"))).click()
    time.sleep(3)
    items = driver.find_elements_by_xpath("//*[name()='svg']//*[name()='circle']")
    i = 0
    for item in items:
        try:
            time.sleep(1)
            ActionChains(driver).move_to_element(item).click(item).perform()
        except Exception:
            print("Can't click")
    

    此代码有效,每个元素都将被单击,直到地图被放大。在其中一个元素处地图放大,之后它就不起作用了。为什么?我还没有找到,但您可以自己找到或提出其他问题,我们会尽力为您提供帮助。

    注意:您必须添加一些导入:

    from selenium.webdriver.common.action_chains import ActionChains
    import time
    

    编辑:我发现了问题,您必须在点击后关闭每个弹出窗口,然后它才能工作。工作代码如下:

    wait = WebDriverWait(driver, 5)
    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#mapDiv_zoom_slider .esriSimpleSliderIncrementButton"))).click()
    time.sleep(3) # wait until all elements will be ready
    items = driver.find_elements_by_xpath("//*[name()='svg']//*[name()='circle']")
    for item in items:
        time.sleep(0.5) # small pause before each iteration
        ActionChains(driver).move_to_element(item).click(item).perform()
        wait.until(EC.element_to_be_clickable((By.XPATH, "//div[@title = 'Close']"))).click()
    

    我没有找到避免time.sleep() 的方法,可能在这种特殊情况下是不可能的。

    【讨论】:

    • 这是我在尝试使用您建议的脚本时遇到的部分错误; line 397, in _find_element return driver.find_element(*by) TypeError: find_element() argument after * must be an iterable, not WebElement
    • 我已经编辑了我的答案,请看一下代码sn-p
    • 解决了特定元素的问题,我在答案中添加了代码sn-p
    • 非常感谢您的解决方案。它部分工作(尚未解决)。点击 5/7 次后,它会抛出 timeout exception 指向最后一行的错误..
    • 我刚刚在我的本地机器上又测试了一次——效果很好。尝试将time.sleep(0.5) 增加到time.sleep(1)。我觉得脚本太快了
    猜你喜欢
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    • 2019-01-05
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    相关资源
    最近更新 更多