0

I am trying to scrape data from a news website and anytime a news article is clicked on, an ad shows up. I try to switch the control to the iframe to close the ad but it keeps on throwing "NoSuchElement" exception.

Below is the iframe that I want to switch to. The id is unique to this iframe.

<iframe title="Advertisement" id="ad_iframe" name="ad_iframe" scrolling="no" src="about:blank" frameborder="0" width="556px" height="222px" style="border: 0px; vertical-align: bottom; width: 556px; height: 222px;"></iframe>

My code is as follows:

try:
    WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it(driver.find_element_by_xpath('//iframe[@id="ad_iframe"]')))
    driver.find_element_by_xpath('//div[@id="dismiss-button"]').click()
            
except NoSuchElementException:
    headline = driver.find_element_by_xpath("//section[@class='col-md-8 content']/h1")
    date = driver.find_element_by_xpath("//p[@class='small']")

The close button element is there in the iframe, and looks like:

<div class="ns-g3arv-e-19 button-common close-button" id="dismiss-button" x-ns-g3arv-e="19" x-overflow-forbidden="xy" aria-label="Close ad" role="button" tabindex="0"><div class="ns-g3arv-e-20" x-ns-g3arv-e="20" x-overflow-forbidden="xy"><span class="ns-g3arv-e-21" dir="auto" x-ns-g3arv-e="21" x-score="1">Close</span></div></div>

I am unable to find what is going wrong here? Why does selenium not 'switch' to the selected iframe?

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Add a wait for the second element. – Arundeep Chohan Feb 04 '22 at 05:19
  • that iframe's src is a little odd. (src="about:blank") It might be updated at a different time. Selenium may not know it's actually "available" until later. Might be worth checking to see if a sleep helps before getting the iframe element. – pcalkins Feb 04 '22 at 19:57

1 Answers1

0

frame_to_be_available_and_switch_to_it()

frame_to_be_available_and_switch_to_it(locator) is the expectation for checking whether the given frame is available to switch to. If the frame is available it switches the given driver to the specified frame. It takes a locator as an argument.

As the element is within an <iframe> so you have to:

  • Induce WebDriverWait for the desired frame to be available and switch to it.

  • Induce WebDriverWait for the desired element to be clickable.

  • You can use either of the following Locator Strategies:

    • Using CSS_SELECTOR:

      WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe#ad_iframe[name='ad_iframe']")))
      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div[aria-label='Close ad'] span"))).click()
      
    • Using XPATH:

      WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@id='ad_iframe' and @name='ad_iframe']")))
      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@aria-label='Close ad']//span[text()='Close']"))).click()
      
  • Note : You have to add the following imports :

     from selenium.webdriver.support.ui import WebDriverWait
     from selenium.webdriver.common.by import By
     from selenium.webdriver.support import expected_conditions as EC
    

Reference

You can find a couple of relevant discussions in:

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352