Apparently, turns out that the problem I faced ( as mentioned in the question ) wasn't because the XPath was wrong, it was because of two things, which I'd like to explain further in this answer, by drawing a comparison between
a) The code I initially wrote and posted in the question, (wrong)
exem = driver.find_element_by_tag_name("frameA")
driver.switch_to.frame(exem)
required_field = driver.find_element_by_xpath("html/body/p").text
print(required_field)
versus
b) The modified version of it ( which is now error-free and perfectly working )
driver.implicitly_wait(20)
exem = driver.find_element_by_tag_name("iframe")
driver.switch_to.frame(exem)
required_field = driver.find_element_by_xpath("html/body/p").text
print(required_field)
(or)
driver.implicitly_wait(20)
exem = driver.find_element_by_id("frameA")
driver.switch_to.frame(exem)
required_field = driver.find_element_by_xpath("html/body/p").text
print(required_field)
- As aptly mentioned by @PDHide, frameA in this example is the id of the iframe, and not a tag. Hence, using frameA as the argument to
driver.find_element_by_tag_name()
would be meaningless, and hence, I've replaced it by
driver.find_element_by_tag_name("iframe")
(or) driver.find_element_by_id("frameA")
In simple use cases ( when web pages contain just one iframe ), either of these may be used.
- The actual cause of my initial code failing was inadequate time given to the web page for all of its components to load, i.e. in the absence of a mechanism to pause the operations of the driver for few seconds, the driver would not wait for components such as iframes to load, and would hence not find the iframe in the script of the page, eventually returning no element, leading to the NoSuchElementException.
To avoid this, a mechanism to instruct the driver to wait for few seconds is needed, and that is exactly what the method driver.implicitly_wait()
does. It takes the number of seconds the driver has to wait for as its argument, and instructs the driver to wait accordingly. This is what you see in the first line of my modified code.
Also, @DMart aptly mentions the use of //p
in the XPath, because it does work, without having to use html/body/p
, so the code works with //p
in the XPath too.
Note: Waits may be explicit too, i.e. triggered by/after the execution of a series of conditions or statements.
Find a detailed read on "waits" here - https://selenium-python.readthedocs.io/waits.html
A site explaining some usecases of iframes with Selenium - Python - https://chercher.tech/python/iframe-selenium-python#handle-single-iframe
A similar issue on StackOverflow, Selenium with Java - Selenium WebDriver can't locate element in iframe even when switching to it