在 iframe 中使用 Selenium:NoSuchElementException

Using Selenium in iframe: NoSuchElementException

我正在 运行 一个 streamlit 应用程序,我在其中尝试 运行 selenium(单击搜索框并)在 iframe 组件内,但我不断收到错误“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 运行 app5.py" 时,它生成了两个独立的浏览器,最近打开了一个空浏览器,所以 selenium代码在空页面上执行,而不是在 streamlit localhost:8501 页面上。怎么才能不生成空浏览器,只打开localhost:8501页面,让streamlit页面的selenium代码运行s?

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

input.input_search 元素不在该页面的任何 iframe 中。
那里有 4 个 iframe,但是搜索输入不在其中任何一个内。
因此,您不应为了访问搜索输入元素而切换到 iframe。

这里你需要考虑几件事。

  • 所需的 <input> 不在任何 <iframe> 中,所以你不需要切换到任何框架。

  • on any clickable element instead of you need to induce WebDriverWait for the and you can use the following :

  • 代码块:

    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)
    
  • 浏览器快照:

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

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

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

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

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

  1. 你运行 streamlit run app.py 命令。
  2. Streamlit 在 chrome 浏览器中打开此代码。
  3. selenium 代码启动 运行ning 并打开 selenium 代码的 new 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 - 如果您只想查看从芝加哥到西雅图的方向,只需更改 url.

代码:

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)

输出: