2

I'm trying to click on an element on this page:

url = 'https://finance.yahoo.com/quote/GOOG?ltr=1'
driver = webdriver.Firefox()
driver.get(url)
driver.find_element_by_link_text('Financials')

At this point I would like to click on 'Cash Flow', 'Balance Sheet', or 'Quarterly'. I know these buttons have been loaded because I can extract them using BeautifulSoup from the page source. But when I try to do it using Selenium:

driver.find_element_by_link_text('Cash Flow')
driver.find_element_by_link_text('Balance Sheet')
driver.find_element_by_link_text('Quarterly')

All return 'Unable to locate element' except for 'Quarterly' which returns an element but its the one sitting above the graph and not the one above the table which is what I'm interested in.

I think this is due to being in the wrong iframe, and I have located all iframes:

driver.find_elements_by_tag_name('iframe')

which returns 9 elements. But I'm having trouble figuring which iframe the elements I want to click on belong to. I also went through the iframes sequentially and still couldn't find the elements I'm interested in.

Chris_Rands
  • 38,994
  • 14
  • 83
  • 119
AppleCider
  • 23
  • 5

3 Answers3

1

I just checked in the website, they (the elements you are looking for) are NOT in any iframe tag.

Following code worked for me (changed to xpath, no need to switch):

driver.find_element_by_xpath("//span[contains(text(),'Cash Flow')]").click()
driver.find_element_by_xpath("//span[contains(text(),'Balance Sheet')]").click()
driver.find_element_by_xpath("//span[contains(text(),'Quarterly')]").click()

Note: It might be the reason that for "Financials", parent tag is a which represent a link, but for other elements (Cash Flow, Balance sheet), parent tag is div which is not a link tag. so find_element_by_link_text might not have been worked.


Switching between iframes:

You have to switch to the frame in which the element is present before we try to identify it.

Lets assume, your element is inside 3 iframes as follows:

<iframe name="frame1">
  <iframe name="frame2">
     <iframe name="frame3">
        <span>CashFlow</span> <! Span element is inside of 3 iframes>
    </iframe>
    <span>balance sheet> <! Span element is inside of 2 iframes>
  </iframe>
</iframe>

Now, if you want to identify CashFlow which is inside the three iFrames:

    driver.switch_to_frame(driver.find_element_by_name("frame1")) // here, you can provide WebElement representing the iFrame or the index.
    driver.switch_to_frame(driver.find_element_by_name("frame2"))
    driver.switch_to_frame(driver.find_element_by_name("frame3"))
    driver.find_element_by_link_text("CachFlow")

    # switch to default frame before you again try find some other element which is not in the same frame (frame3)

   driver.switch_to_default_content()

   # then navigate to the frame that you want to indentify the element:
   driver.switch_to_frame(driver.find_element_by_name("frame1")) 
   driver.switch_to_frame(driver.find_element_by_name("frame2"))
   driver.find_element_by_link_text("balance sheet")

  # switch to default content again
  driver.switch_to_default_content()

Note: I used Frame References instead of indexes as you mentioned there are 9 iFrames. so, using indexes would be confusing. If you can't identify frameElement, then only go for indices.

Reference:

  1. http://selenium-python.readthedocs.io/api.html#selenium.webdriver.remote.webdriver.WebDriver.switch_to_frame
Naveen Kumar R B
  • 6,248
  • 5
  • 32
  • 65
  • Very nice answer! So to clarify, how would you be able to identify, on a complex web page, how the frames are nested? I've been using Firefox's Inspector though its not obvious to me how that allows me to find how the iframes are contained within each other. – AppleCider Nov 24 '16 at 01:25
  • you have to go through the entire hierarchy towards html tag, from the element you want to find, and check whether any of its parent elements are iframe tags. , in above html, you consider that the required element is in iframe tag. If the syntax is ****, then we consider iframe is closed in the same line and does not have any elements. – Naveen Kumar R B Nov 24 '16 at 05:43
  • Thanks for the response, I understand what you've explained but rather I was hoping that there are some web tools that allows an easy way to find how the iframes are nested without traversing all of the code? Especially if the source is very complicated, or are you suggesting that I'd just have to work through it by eye and find the appropriate iframe? – AppleCider Nov 25 '16 at 03:36
  • 1
    Use Firebug and FirePath Addons in your firefox browser. Navigate to FirePath Tab in Firebug and inspect the element. On the Left side of the expression text field, A drop down list populates the default frame(Top WIndow) and other child frames. From there you can identify that your element belong to which frame.But not the structure either flatten or hierarichal. – Mouli Nov 25 '16 at 06:38
  • From my knowledge, I am not aware of any such tools who can directly point out the hierarchy of iframe(s) in which the element is resides. I suggest to ask a new question in stackoverflow.com, so, you may find best answers. @Mouli has mentioned already one option. – Naveen Kumar R B Nov 25 '16 at 11:37
0

you need switch to correct iframe - all of them has different IDs (or some other tags) in java it looks like this (for some random iframe id)

driver.switchTo().frame(driver.findElementById("defaultdestFB2-1"))
dimkin
  • 108
  • 1
  • 11
0

Yes this helped resolve the issue. Thank you very much. There were 2 frames on this webpage (0) and (1). I added the line "driver.switch_to.frame(1)". Below is a copy of the code I used and it has fixed the issue I encountered...

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

#create capabilities
capabilities = DesiredCapabilities.INTERNETEXPLORER

#delete platform and version keys
capabilities.pop("platform", None)
capabilities.pop("version", None)

#start an instance of IE
driver = webdriver.Ie(executable_path="C:\\LocalDev\\IEDriverServer.exe", capabilities=capabilities)

#open Accela login page
driver.get("https://pwms-avdev.co.arapahoe.co.us/security/hostSignon.do?signOff=true")

driver.switch_to.frame(1)

#enter Agency
agency = driver.find_element_by_id("servProvCode")
agency.send_keys('arapahoe')
JohnnieK
  • 23
  • 4