python selenium click blocked by popup

Viewed 1220

when I attempt to click a button located behind a popup menu I receive the following error message.

*** selenium.common.exceptions.ElementClickInterceptedException: Message: Element <input id="submitButton" class="search-button icon-search active" type="submit"> is not clickable at point (729.2000122070312,22) because another element <div id="monetate_lightbox_mask" class=""> obscures it

This error message is able to identify the name of what is blocking my click

How can I get this name (as an element) so that I can make modifications such as,

element = <div id="monetate_lightbox_mask" class="">

browser.execute_script("""var element = arguments[0]; element.parentNode.removeChild(element);""", element)

The wait function is not applicable as this popup does not go away. I have tried webdriver.ActionChains, but it doesn't not solve this issue

2 Answers

Another interesting workaround would be to perform that click via javascript - in that case, it would not matter what is in front of it or blocking it:

submit_button = driver.find_element_by_id("submitButton")
driver.execute_script("arguments[0].click();", submit_button)

Also, be aware of the differences between a regular selenium click and click via javascript:

If I understand correctly, you basically don't want to hardcode monetate_lightbox_mask id and parse it out of the exception message. It is possible with something like:

import re

from selenium.common.exceptions import ElementClickInterceptedException


error_pattern = re.compile(r'another element <div id="(.*?)".*? obscures it')
submit_button = driver.find_element_by_id("submitButton")

try:
    submit_button.click()
except ElementClickInterceptedException as e:
    print("Blocking element detected. Removing..")

    blocking_element_id = error_pattern.search(e).group(0)  # TODO: error handling
    blocking_element = driver.find_element_by_id(blocking_element_id)
    browser.execute_script('var element = arguments[0]; element.parentNode.removeChild(element);', blocking_element)

    print("Element removed. Clicking again...")
    submit_button.click()

Here we are applying a regular expression pattern to the error message to extract the id value which introduces this assumption of that blocking element to have an id. We could though improve it to look for all the attributes and then use these attributes to locate a blocking element.

Instead of a regular expression, we could even use something like BeautifulSoup HTML parser to parse that error message and find HTML elements inside:

In [1]: from bs4 import BeautifulSoup

In [2]: data = """
   ...: *** selenium.common.exceptions.ElementClickInterceptedException: Message: Element <input id="submitButton" cla
   ...: ss="search-button icon-search active" type="submit"> is not clickable at point (729.2000122070312,22) because 
   ...: another element <div id="monetate_lightbox_mask" class=""> obscures it
   ...: """

In [3]: soup = BeautifulSoup(data, "html.parser")

In [4]: for element in soup():
   ...:     print(element)
   ...:     
<input class="search-button icon-search active" id="submitButton" type="submit"/>
<div class="" id="monetate_lightbox_mask"> obscures it
</div>

In [5]: blocking_element = soup()[-1]

In [6]: blocking_element.name
Out[6]: 'div'

In [7]: blocking_element.attrs
Out[7]: {'class': [''], 'id': 'monetate_lightbox_mask'}

Another note: if there are multiple blocking popups, you may need to apply this method recursively.

Related