在 iframe 中使用 Selenium:NoSuchElementException

Posted

技术标签:

【中文标题】在 iframe 中使用 Selenium:NoSuchElementException【英文标题】:Using Selenium in iframe: NoSuchElementException 【发布时间】:2022-01-14 12:28:03 【问题描述】:

我正在运行一个流线型应用程序,我尝试在 iframe 组件中运行 selenium(单击搜索框和),但我不断收到错误“NoSuchElementException”。

它成功地在 streamlit 应用上打开 iframe,但它不执行 iframe 内的 selenium 代码。当我在没有 iframe 的情况下对其进行测试时,selenium 代码本身运行良好,但我无法让它在 iframe 内工作。

这是我的代码:

import streamlit as st
from dateutil.parser import parse
import streamlit.components.v1 as components
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

st.title("Auto Search App")

driver = webdriver.Chrome()
wait = WebDriverWait(driver, 20)

# url = 'https://wego.here.com/'
# driver.get(url)

components.iframe("https://wego.here.com/", height = 500)

## Give time for iframe to load ##
time.sleep(3)
## You have to switch to the iframe like so: ##
driver.switch_to.frame(driver.find_element_by_tag_name("iframe"))

search_input = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "input.input_search")))
search_input.click()
search_input.send_keys('Seattle')
search_input.send_keys(Keys.ENTER)

wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "button.btn"))).send_keys(Keys.ENTER)

internal_search_input = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "input#itinerary_item_input_0")))
internal_search_input.click()
internal_search_input.send_keys('Chicago')
internal_search_input.send_keys(Keys.ENTER)

这是带有错误消息的流光页面:


编辑:根据答案,我认为不必切换到 iframe 即可访问搜索输入元素。我猜这个问题是因为当我在 cmd 上运行“streamlit run app5.py”时,它会生成两个单独的浏览器,最近打开了一个空浏览器,因此 selenium 代码在一个空页面上执行,而不是在streamlit localhost:8501 页面。如何不生成空浏览器,只打开localhost:8501页面,让selenium代码运行在streamlit页面上?

EDIT2:我添加了更多的 selenium 执行代码供您参考。我在这里使用 selenium 的原因是在 iframe 上进行一些自动化操作,以便它在最后填充导航页面。我可以通过使用driver.get(url) 在单独的 chrome 上完成它,但不能使用 iframe 在 streamlit 上完成。这是我想在 iframe 中看到的最终结果:

【问题讨论】:

【参考方案1】:

从您的代码中,我了解到您正在尝试运行 selenium 代码来设置打开的 Streamlit 页面内 iframe 中的输入值。

这是不可能的。当您运行此代码时,我将尝试使用事件顺序进行解释。

使用您当前的代码会发生以下情况:

    您运行streamlit run app.py 命令。 Streamlit 在 chrome 浏览器中打开此代码。 selenium 代码开始运行,因为您不使用 driver.get(url),它在空页面上运行,导致 NoSuchElementException。

如果您使用 driver.get(url) 并将 URL 设置为 Streamlit 应用程序 url='http://localhost:8501/',那么它也不会起作用,因为会发生这种情况:

    您运行streamlit run app.py 命令。 Streamlit 在 chrome 浏览器中打开此代码。 selenium 代码开始运行并打开 selenium 代码的 chrome 选项卡,您无法让 selenium 获取已打开的选项卡(会话)。

我建议不要为此使用 selenium,而是使用 Streamlit 创建一个 text_input 并使用输入的地理位置生成 iframe。

代码:

import streamlit as st
import streamlit.components.v1 as components
from geopy.geocoders import Nominatim

bt = st.text_input("Enter Location")

if bt:
    geolocator = Nominatim(user_agent="my_app")
    location = geolocator.geocode("Seattle")
    components.iframe(f"https://wego.here.com/?map=location.latitude,location.longitude,18,normal&x=ep", height = 500)

输出:


编辑 1 - 如果您只想查看从芝加哥到西雅图的方向,只需更改网址即可。

代码:

import streamlit as st
import streamlit.components.v1 as components
from geopy.geocoders import Nominatim

components.iframe("https://wego.here.com/directions/mix/Chicago/Seattlel", height = 500)

输出:

【讨论】:

感谢您的反馈,但我不只是想获得西雅图的地图,而是想使用 selenium 获得从芝加哥到西雅图的导航地图。我想知道是否有办法在不使用 selenium 的情况下使用 url 来获取从芝加哥到西雅图的导航地图。我在最后编辑了我的帖子和我的代码供您参考。 @user9532692 我根据您的要求编辑了我的答案,您只需使用 url 即可获得所需的内容,而无需 selenium。 你是如何/从哪里得到那个网址的?这是我最初想到的,但我找不到将城市名称作为输入值的网址获取路线。这就是我尝试使用 selenium 的原因,但这是最干净、最简单的方法! @user9532692 我刚刚使用了网站,我插入了说明并查看了 url 的变化。这不是最稳定的解决方案,但它比在 Streamlit 应用程序中使用 selenium 更好。也可以尝试搜索具有您可以使用的 api 的不同地图服务,而不是直接使用 url :) 您能否详细说明一下您如何看待 url 的变化。您是否在浏览器上打开 DevTools 以查看此类更改?因为当我插入路线时,我在浏览器上看不到一个干净的网址。【参考方案2】:

input.input_search 元素不在该页面上的任何 iframe 中。 那里有 4 个 iframe,但搜索输入不在其中。 所以你不应该切换到 iframe 来访问搜索输入元素。

【讨论】:

【参考方案3】:

您需要在这里考虑几件事。

所需的 <input> 不在任何 <iframe> 中,因此您无需切换到任何帧。

在任何可点击元素上的click(),而不是presence_of_element_located(),您需要为element_to_be_clickable()诱导WebDriverWait,您可以使用以下@987654325 @:

代码块:

driver.get("https://wego.here.com/")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input.input_search"))).send_keys("Seattle" + Keys.RETURN)

浏览器快照:

【讨论】:

我还可以通过使用 wego.here.com url 打开浏览器来执行 selenium,就像您使用 driver.get("wego.here.com/") 所做的那样.但是,我想在streamlit应用程序的iframe中运行selenium。我想我不必切换到iframe来访问搜索输入元素。但我想这个问题与它打开两个浏览器选项卡有关最后打开一个空的,让selenium运行在一个空页面上。如何只打开localhost:8501页面而不是空页面,让selenium代码运行在streamlit页面上?

以上是关于在 iframe 中使用 Selenium:NoSuchElementException的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 java 在 Selenium WebDriver 中处理 iframe

使用 Java 和 Selenium WebDriver 在表单和 iframe 中查找元素

Selenium基本使用表单切换

python+selenium如何定位多层iframe中元素

Selenium中web三大切换之iframe窗口及Alert(弹窗)切换

selenium 框架切换iframe报错NoSuchFrameException的解决方法