无法切换到iframe后,它就无法与iframe进行交互Python / Selenium-wire

时间:2020-08-15 07:07:00

标签: python xpath iframe seleniumwire

我正在尝试与具有以下结构的页面上的按钮进行交互。感兴趣的按钮位于iframe主体中的div内,该主体位于主体内部。我已经阅读了有关如何切换到iframe的所有StackOverflow问题-如下所示,我对此没有任何疑问。我有一个问题是,无论该建议如何,我都无法与切换到的iframe进行交互。目的是单击特定iframe内的按钮。

编辑:该问题似乎与硒线库有关。这是完整的代码。

from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
import time

url = 'https://sahkovertailu.fi/'
options = {
    'suppress_connection_errors': False,
    'connection_timeout': None# Show full tracebacks for any connection errors
}
chrome_options = Options()
chrome_options.add_argument("--start-maximized")
chrome_options.add_argument('--auto-open-devtools-for-tabs')
chrome_options.add_argument('--log-level=2')

driver = webdriver.Chrome(ChromeDriverManager().install(), seleniumwire_options=options, chrome_options=chrome_options)

if driver.requests is not None:
    del driver.requests
driver.get(url)

iframe = driver.find_element_by_xpath("//iframe[contains(@src, 'privacy')]")
driver.switch_to.frame(iframe)
iframeUniqueId = iframe.get_attribute('cd_frame_id_')
print(iframeUniqueId)
time.sleep(2)
button = driver.find_element_by_xpath("//button[contains(., 'OK')]")
button.click()

这是页面布局的示例

<!doctype html>
<html ng-app="someApp" xmlns="http://www.w3.org/1999/html">
    <head>
        <script>a lot of scripts</script>
    </head>
    <body class="unwantedBody">
        <iframe> some iframes</iframe>
        <div> different divs </div>
        <main> 
            some content
            <iframe> multiple iframes on different nested levels </iframe>
        </main>
        <div> more divs </div>
        <script> more scripts </script>
        <div id='interesting div'>
            <iframe src="uniqueString">
                <!doctype html>
                #document
                <html>
                    <body>
                        <div>
                            <button id='bestButton'>
                                'Nice title'
                            </button>
                        </div>
                    </body>
                </html>
            </iframe>
        </div>
    </body>
</html>

使用Jupyter Notebook,我已经能够找到iframe并切换到它。该问题与尝试与iFrame交互速度过快无关,因为我可以控制速度。我已经尝试过使用“预期”条件,并等到可以将iframe切换到该条件,但这与我的问题无关。

driver.switch_to.default_content # Making sure no other frame is selected
iframe = driver.find_element_by_xpath("//iframe[contains(@src, 'uniqueString')]")
driver.switch_to.frame(iframe)
print(iframe.get_attribute('id'))

上面的代码打印出“有趣的div”,因此它成功找到了iframe所在的div,并且显然选择了div?当我切换到iframe时,网页会发生变化,并且为iframe提供了唯一的GUID:

<iframe src="uniqueString" cd_frame_id_ = "uniqueGuidThatAlwaysChanges"> ... </iframe>

我可以使用来访问唯一ID

iframe.get_attribute('cd_frame_id_')

然后我尝试像这样解析iframe:

bestButton = driver.find_element_by_xpath("//button[@id = 'bestButton']")
bestButton.click()

出现错误:

消息:元素不可交互

如果我替换上面的驱动程序。使用iframe.find_element_by_xpath ...我得到以下错误:

消息:否这样的元素:无法找到元素: {“ method”:“ xpath”,“ selector”:“ // button [@ id =” bestButton“]”}

我还尝试使用上述switch_to.frame(iframe)切换到iframe中的主体 后,因此在此示例中,驱动程序已位于iframe中:

document = driver.find_element_by_xpath('//html/body')
info = document.get_attribute('class')
print(info)

这将打印出来

不需要的身体

以某种方式,驱动程序没有切换到我指定的iFrame,而是仍然停留在主HTML上。在chrome上加载网页时,我可以使用此XPath ///找到我想要的按钮// button [contains(@ id ='bestButton')],但在Selenium中它不起作用,因为它由#document中的iframe。

我想念什么?如果有帮助,我感兴趣的iFrame实际上是一个有关Cookie同意的模式窗口,我试图摆脱与网站交互的方式。

2 个答案:

答案 0 :(得分:1)

@qoob,您没有指定该按钮在网站上的确切位置,并且Google并未将芬兰语翻译成英语。 因此,我假设您是在谈论首页本身,因为iframe的DOM结构看起来像您在问题中所问的那样熟悉。如果下图中的按钮是实际的兴趣点,则下面的代码有效。

enter image description here

from selenium import webdriver
import time

driver = webdriver.Chrome(r"C:\chromedriver.exe")
driver.maximize_window()
driver.get("https://sahkovertailu.fi/")
driver.switch_to.frame(driver.find_element_by_xpath("//iframe[@id='sp_message_iframe_204788']"))
time.sleep(2) # remove after testing
driver.find_element_by_xpath("//div[@class='message type-modal']//descendant::button[2]").click()

有关如何使用XPath轴的参考,请参考:https://www.lambdatest.com/blog/complete-guide-for-using-xpath-in-selenium-with-examples/#testid2.8.1

请注意,webdriver_manager到目前为止存在一些问题,因此强烈建议使用chromedriver / firefox二进制文件。(https://github.com/SergeyPirogov/webdriver_manager/issues/119

让我知道是否可行!

答案 1 :(得分:0)

Akshays的答案将我引向正确的方向-问题可能是使用ChromeDriver(或至少当前版本为84.0.4147)时硒线库中的错误。如果用户对常规硒库有疑问,Akshays的答案是正确的。可以通过使用Firefox驱动程序(当前版本的geckodriver v0.27.0)解决selenium-wire的问题:

from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options as chromeOptions
from selenium.webdriver.firefox.options import Options as firefoxOptions
from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.firefox import GeckoDriverManager

if browser == 'chrome':
    chrome_options = chromeOptions()
    chrome_options.add_argument("--start-maximized")
    chrome_options.add_argument('--auto-open-devtools-for-tabs')
    chrome_options.add_argument('--log-level=2')
    driver = webdriver.Chrome(ChromeDriverManager().install(), seleniumwire_options=options, chrome_options=chrome_options)
elif browser == 'firefox':
    firefox_options = firefoxOptions()
    firefox_options.headless = True
    driver = webdriver.Firefox(executable_path=GeckoDriverManager().install(), seleniumwire_options=options, options=firefox_options)
    driver.maximize_window()

编辑:实际上,Akshay的评论甚至更好-通过删除--auto-open-devtools-for-tabs参数,即使使用硒线Webdriver上的chrome驱动程序,切换到iframe也可以。 / p>

Firefox并非没有问题,例如,使用WebdriverWait不能使用自定义的等待时间等(如https://stackoverflow.com/a/27238388/13952179所述,似乎只能使用45秒)。