简体   繁体   中英

Python Selenium Webdriver: Can I switch to an unfriendly iframe?

I'm getting an error when I try to switch_to_frame() or switch_to.frame() (btw, which of those is correct?) to an unfriendly iFrame. Should that be supported?

def click_all(driver):
    for img in imgs:
        img.click()
    iframes = driver.find_elements_by_tag_name('iframe')
    for ifr in iframes:
        try:
            driver.switch_to.frame(ifr)
        except:
            e = sys.exc_info()
            print "Error: %s" % str(e) # Gives a vague error: '(<class 'selenium.common.exceptions.WebDriverException'>, WebDriverException(), <traceback object at 0x1102a9680>)'
            return
        click_all(driver)

Thanks for any help!

The stack trace is:

Traceback (most recent call last):
File "/Users/merrigan/working/DockLion/qe-cordell/test/bases/util.py", 
line 45, in click_all
driver.switch_to_window(ifr)
File "/Library/Python/2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 657, in switch_to_window
self._switch_to.window(window_name)
File "/Library/Python/2.7/site-packages/selenium/webdriver/remote/switch_to.py", line 113, in window
self._driver.execute(Command.SWITCH_TO_WINDOW, data)
File "/Library/Python/2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 308, in execute
self.error_handler.check_response(response)
File "/Library/Python/2.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 194, in 
check_response
raise exception_class(message, screen, stacktrace)
WebDriverException: Message: unknown error: 'name' must be a string
(Session info: chrome=65.0.3325.181)
(Driver info: chromedriver=2.33.506106 
(8a06c39c4582fbfbab6966dbb1c38a9173bfb1a2),platform=Mac OS X 10.12.6 x86_64)

(Does this mean it only works if the iFrame has a name attribute?)

Yes, you can pass a WebElement to the switch_to.frame function and it will work.

ex.

 driver.switch_to.frame(driver.find_element_by_id('id'))

The issue you are having above is caused by this line that is not present in your code above:

self._switch_to.window(window_name)

Which requires a window name or handle , thus causing your error in the Traceback provided.

If you are still having issues, please provide the relevant HTML , so we can help you switch to this frame.


switch_to_frame is now deprecated, please use switch_to for any switching functions.

The documentation on switching between windows and frames is HERE , which refers to switch_to_frame , but the description is still relevant for use purposes.


SIDENOTE

Please update your Chromedriver to at least 2.36 since you are running on Chrome build 65 , which is not supported by your current version of Chromedriver 2.33 : https://sites.google.com/a/chromium.org/chromedriver/downloads

By keeping these up to date, or on a recommended pair, you will run into less problems as described on the chromedriver download landing page.

While working with frames you need to consider a couple of things as follows :

  • An webpage can have multiple frames.
  • All the frames may not have distinct id , name , class etc attributes.
  • Loading sequence of the frames can differ with respect to the WebElements with which you interact within the Top-Level Browsing Context
  • Some ifames can have the attribute style set to display: none;

Keeping in view the above mentioned usecases you have to figure out the intended <iframe> to which you want to switch. So instead of creating a list through :

iframes = driver.find_elements_by_tag_name('iframe')

Try to locate the exact frame where the intended WebElements are located with which you want to interact through either of the following methods :

driver.switch_to.frame("iframe_name") # By Frame Name
driver.switch_to.frame("iframe_id") # By Frame ID
driver.switch_to.frame(frame_index) # By Frame Index

You can find a detailed discussion in How can I select a html element no matter what frame it is in in selenium?

The API Docs clearly mentions switch_to_frame() method is Deprecated :

switch_to_frame(frame_reference)
Deprecated use driver.switch_to.frame

Use switch_to.frame() instead as follows :

driver.switch_to.frame(frame_reference)

Returns : SwitchTo an object containing all options to switch focus into

Note : For effective frame switching you need to induce WebDriverWait with expected_conditions clause as frame_to_be_available_and_switch_to_it() . You can find a detailed discussion under the subheading A Better Approach to Switch Frames

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM