Reputation: 113
I'm trying to get Selenium to click a link but it is giving an error saying "click intercepted".
The code did work once and loaded the right web page but I haven't gotten it to work since. Selenium does find the link to click but it doesn't want to use it and returns an error.
Error Code:
Enter Anime:One Piece
Search All - MyAnimeList.net
Traceback (most recent call last):
File "C:\Users\amete\Documents\Python\Code\Web test.py", line 29, in <module>
link = driver.find_element_by_xpath("/html/body/div[2]/div[2]/div[3]/div[2]/div[2]/div[1]/div/article[1]/div[1]/div[2]/a[1]").click()
File "C:\Users\amete\AppData\Local\Programs\Python\Python39\lib\site-packages\selenium\webdriver\remote\webelement.py", line 80, in click
self._execute(Command.CLICK_ELEMENT)
File "C:\Users\amete\AppData\Local\Programs\Python\Python39\lib\site-packages\selenium\webdriver\remote\webelement.py", line 633, in _execute
return self._parent.execute(command, params)
File "C:\Users\amete\AppData\Local\Programs\Python\Python39\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "C:\Users\amete\AppData\Local\Programs\Python\Python39\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <a href="https://myanimelist.net/anime/21/One_Piece" class="hoverinfo_trigger fw-b fl-l" id="#revAreaAnimeHover21" rel="#revInfo21" style="position: relative;">...</a> is not clickable at point (103, 339). Other element would receive the click: <div height="576" class="qc-cmp-cleanslate css-1kaql54">...</div>
(Session info: chrome=91.0.4472.114)
My code:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
Anime = input("Enter Anime:")
PATH = r"C:\Users\amete\Documents\chromedriver.exe"
driver = webdriver.Chrome(PATH)
driver.get("https://myanimelist.net/search/all?q=one%20piece&cat=all")
print(driver.title)
# Since Selenium does not want to allow me to use the main page to search
# I got a link that I already searched with and then cleared it.This then allowed me to type whatever I wanted.
search = driver.find_element_by_xpath('/html/body/div[2]/div[2]/div[3]/div[2]/div[1]/form/div/div[1]/input[1]')
# Clears the field
search.send_keys(Keys.CONTROL, 'a')
search.send_keys(Keys.DELETE)
# The field is now cleared and the program can type whatever it wants
search.send_keys(Anime)
search.send_keys(Keys.RETURN)
link = driver.find_element_by_xpath("/html/body/div[2]/div[2]/div[3]/div[2]/div[2]/div[1]/div/article[1]/div[1]/div[2]/a[1]").click()
time.sleep(5)
Upvotes: 2
Views: 2627
Reputation: 4212
You need:
1 Wait for the field to become visible
2 Make a stable locator:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
# Anime = input("Enter Anime:")
driver = webdriver.Chrome(executable_path='/snap/bin/chromium.chromedriver')
driver.get("https://myanimelist.net/search/all?q=one%20piece&cat=all")
print(driver.title)
wait = WebDriverWait(driver, 20)
# Accepting cookies
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#gdpr-modal-bottom button'))).click()
# waiting for Search field
search = driver.find_element_by_xpath('//input[@name="q"]')
wait.until(EC.element_to_be_clickable((By.XPATH, '//input[@name="q"]')))
# Clears the field
search.send_keys(Keys.CONTROL, 'a')
search.send_keys(Keys.DELETE)
# The field is now cleared and the program can type whatever it wants
search.send_keys("anime")
search.send_keys(Keys.RETURN)
wait.until(EC.element_to_be_clickable((By.XPATH, '//h2[@id="anime"]//ancestor::div[@class="content-left"]//article[1]/div[contains(@class, "list")][1]/div[contains(@class, "information")]/a[1]')))
link = driver.find_element_by_xpath('//h2[@id="anime"]//ancestor::div[@class="content-left"]//article[1]/div[contains(@class, "list")][1]/div[contains(@class, "information")]/a[1]').click()
time.sleep(5)
The code clicks the first element after search was performed.
If you need other element to be clicked, change the part of XPath to: div[contains(@class, 'list')][2]
, div[contains(@class, 'list')][3]
and so on. You may try to shorten this XPath (it's probably possible) or find another one.
I suggest to look at css selectors. finding it for your case would probably be easier. Note, there is a cookie prompt, clicking is in not necessary in your case, but may be required if you try getting elements from the page bottom.
Update
I updated the code to include the click on 'Accept cookies' button.
Upvotes: 5
Reputation: 33361
You need to add wait / delay before that line.
The most simple and brutal is to put some kind of sleep, like time.sleep(3)
there, but the best practice is to use explicit wait, like this:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 20)
import time
Anime = input("Enter Anime:")
PATH = r"C:\Users\amete\Documents\chromedriver.exe"
driver = webdriver.Chrome(PATH)
driver.get("https://myanimelist.net/search/all?q=one%20piece&cat=all")
print(driver.title)
# Since Selenium does not want to allow me to use the main page to search
# I got a link that I already searched with and then cleared it.This then allowed me to type whatever I wanted.
search = driver.find_element_by_xpath('/html/body/div[2]/div[2]/div[3]/div[2]/div[1]/form/div/div[1]/input[1]')
# Clears the field
search.send_keys(Keys.CONTROL, 'a')
search.send_keys(Keys.DELETE)
# The field is now cleared and the program can type whatever it wants
search.send_keys(Anime)
search.send_keys(Keys.RETURN)
wait.until(EC.visibility_of_element_located((By.XPATH, "/html/body/div[2]/div[2]/div[3]/div[2]/div[2]/div[1]/div/article[1]/div[1]/div[2]/a[1]"))).click()
time.sleep(5)
Also, your locators are very bad. They should be much shorter and smart.
Upvotes: 2