selenium中缺少iframe元素

2024-04-27 02:24:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图使用python selenium实现一些自动化功能,但遇到了一些奇怪的行为

html的总体布局:

<html>
  <body>
    <div class="parent">
      <iframe style="display: none"> ... </iframe>
      <iframe style="display: none"> ... </iframe>
      <iframe style="display: block">
        #document
        ...
        <div class="someClass"> ... </div>
      </iframe>
      <iframe style="display: none"> ... </iframe>
      <iframe style="display: none"> ... </iframe>
    </div>
  </body>

现在,每个iframe实际上都有相同的内部html,来自网站的代码似乎是随机选择哪个iframe获得display="block"。但是,我找不到任何iFrame

我尝试了一种标准方法:iframe = driver.find_elements_by_xpath("//iframe[contains(@style, 'display:block')]")

如果失败了,我就试图找到任何iframe:driver.find_element_by_tag_name("iframe")

他们都没有找到任何iframe元素。我看到以下错误:

Traceback (most recent call last):
  File "myfile.py", line 60, in <module>
    iframe = driver.find_element_by_xpath("//iframe[contains(@style, 'display: block')]")
  File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 394, in find_element_by_xpath
    return self.find_element(by=By.XPATH, value=xpath)
  File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 978, in find_element
    'value': value})['value']
  File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "C:\Python27\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: The result of the xpath expression "//iframe[contains(@style, 'display: block')]" is: [object HTMLIFrameElement]. It should be an element.
  (Session info: chrome=93.0.4577.63)

关于xpath返回[object HTMLIFrameElement]的原因,以及我在通过xpath搜索时无法访问其他对象的原因,有什么想法吗

编辑

新代码选项1:

iframes = driver.find_elements_by_xpath(".//iframe[contains(@style,'display: block')]")

这仍然抛出与上面完全相同的错误

新代码选项2:

parent = driver.find_element_by_xpath("//div[@class='parent']")
iframes = parent.find_elements_by_tag_name("iframe")
// when I print typeof iframes here, it's a list of dicts
// find the right index. Here, for simplicity, I just set it a default value
index = 4
// ...
driver.switch_to.frame(iframes[index])

我得到以下错误:

Traceback (most recent call last):
  File "myfile.py", line 76, in <module>
    driver.switch_to.frame(iframe)
  File "C:\Python27\lib\site-packages\selenium\webdriver\remote\switch_to.py", line 89, in frame
    self._driver.execute(Command.SWITCH_TO_FRAME, {'id': frame_reference})
  File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "C:\Python27\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: missing 'ELEMENT'
  (Session info: chrome=93.0.4577.82)

当我打印iFrame时:

[{}, {}, {}, {}, {u'ontouchmove': {}, u'ontouchstart': {}}, {}, {}, {}, {}, {}]

作为参考,这是我试图点击的页面。有时,您必须刷新几次才能获得挑战,而使用selenium时,刷新频率要高得多。此外,使用无头模式会导致每次挑战都会发生https://catalog.usmint.gov/coins/coin-programs/morgan-and-peace-silver-dollar-coins/


Tags: inpybystyledriverseleniumdisplayline
3条回答

我所见过的唯一类似的情况是,当我试图从任何类似的广告中获取一个iframe时,它在我试图获取它们的那一刻消失了

我总是用getElementsByTagName("iframe")解决这个问题,所以在加载页面之前,请尝试再等待一点,以确保在运行iframe之前完全初始化了iframe。 在this question上已经讨论了一种实现这一点的方法

另外,这里是python等待模式的官方文档: https://selenium-python.readthedocs.io/waits.html

PS:刚刚测试了您的示例html页面,当使用document.getElementsByTagName("iframe")时,我可以很容易地在我的浏览器上获得它们,如下图所示,因此您很可能遇到了我上面提到的问题之一,因为您的Selenium应该能够看到它们,假设它们是静态的,并且不会消失,并且您的页面已完全加载:

enter image description here

额外细节

在您的例子中,如果您作为属性接收HTMLIFrameElement而不是简单的iframe标记,这意味着您正在处理一个Web界面,您可以从该界面直接访问它们的属性,这意味着您确实在页面上找到了一个iframe。 您可以使用它的属性来访问native APIs,它有一个.src属性,反映它正在加载的URL,在许多情况下,您可以在不同的页面中打开此URL,并直接获取它所呈现的内容(除非URL包含一些CORS块)。 此外,确实存在一些与WaitForPageToLoad相关的硒铬错误,可以使用其他方法修复,如described here,尽管我认为这不是您当前的问题

?您是否尝试过Selenium文档的示例

See cap. "Using an Index"

# switching to second iframe based on index
iframe = driver.find_elements_by_tag_name('iframe')[1]

# switch to selected iframe
driver.switch_to.frame(iframe)

我遇到过这样的情况:帧需要时间渲染,并且最初没有被代码捕获。以下方法对我很有效

iframes = driver.find_elements_by_tag_name('iframe')

for iframe in iframes:
if 'block' in iframe.get_attribute('style'):
    driver.switch_to.frame(iframe)
    break

相关问题 更多 >