Issue
I'm trying to click on Next ('Siguiente') to go to the next page but I'm noob enough to have spend one day trying what I have found in stackoverflow and different forums with no luck.
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
from selenium.webdriver import ActionChains
from selenium.common import MoveTargetOutOfBoundsException
url='https://www.online.bmsupermercados.es/es/c/ofertas/99999?orderById=5&page=1'
# Set ChromeOptions() and open window
options = webdriver.ChromeOptions()
options.add_argument("--incognito")
options.add_argument("--nogpu")
options.add_argument("--disable-gpu")
options.add_argument("--window-size=1920,1080")
options.add_argument("--no-sandbox")
options.add_argument("--enable-javascript")
options.binary_location = "/usr/bin/chrome/chrome"
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option("useAutomationExtension", False)
options.add_argument("--start-maximized")
driver = webdriver.Chrome(options=options)
driver.get(url)
#Close cookies and Postal Code panels
wait = WebDriverWait(driver, 200)
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Rechazar todo']"))).click()
element = wait.until(EC.visibility_of_all_elements_located((By.XPATH, "//*[name()='use' and @*='#icon-cancel']")))
for i in element:
i.click()
#Scroll down (this last part is required for another action that mouse hover while paging down)
body = driver.find_element(By.TAG_NAME, 'html')
body.click()
body.send_keys(Keys.PAGE_DOWN)
body.send_keys(Keys.PAGE_DOWN)
body.send_keys(Keys.PAGE_DOWN)
And here is where I'm not able to click the Next icon to go to the next page. The following are some of the tries I've done, in some of them it says it's not a button and in others I just receive the TimeoutException:
next_page_link = wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@routerlink='./']//*[name()='svg']/*[local-name()='title' and text()='Siguiente']")))
next_page_link.click()
wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@routerlink='./']//*[name()='svg']/*[local-name()='title' and text()='Siguiente']"))).click()
wait.until(EC.element_to_be_clickable((By.XPATH,"//a//*[contains(text(), 'Siguiente')]"))).click()
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.next-page.d-flex.u-cursor--pointer a[rel=next]'))).click()
wait.until(EC.element_to_be_clickable((By.XPATH, "//a//*[name()='svg']//*[local-name()='Siguiente']"))).click()
wait.until(EC.element_to_be_clickable((By.LINK_TEXT, "//svg[contains(text(),'Siguiente')]"))).click()
wait.until(EC.element_to_be_clickable((By.LINK_TEXT, 'Siguiente'))).click()
wait.until(EC.element_to_be_clickable((By.XPATH, "//a[contains(text(),'Siguiente')]"))).click()
wait.until(EC.element_to_be_clickable((By.XPATH, "//title[@text='Siguiente']"))).click()
# Obtain button by link text and click.
button = body.find_element("link text", "Siguiente")
button.click()
#This is the only one that didn't get the TimeOutException:
wait.until(EC.element_to_be_clickable((By.XPATH, "//a//*[name()='svg']//*[local-name()='use']"))).click()
The error in the last one is:
ElementClickInterceptedException: element click intercepted: Element <use xlink:href="#icon-double-caret"></use> is not clickable at point (935, 492). Other element would receive the click: <div id="paginator-input" class="paginator-input">...</div>
(Session info: chrome=119.0.6045.105)
How can it work? Thank you very much in advance to those of you who take the time to read and say something.
Solution
You don't have to click on svg element in your case.
If you really want to do this, see this answer.
But you can achieve your goal much more easily. You can either get the number of pages, and just fill in the paginator input, or click on the <a> element which is an ancestor to your svg (and which is doing the real action).
See the below code:
actions = ActionChains(driver)
url = 'https://www.online.bmsupermercados.es/es/c/ofertas/99999?orderById=5&page=1'
try:
driver.get(url)
wait = WebDriverWait(driver, 200)
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Rechazar todo']"))).click()
element = wait.until(EC.visibility_of_all_elements_located((By.XPATH, "//*[name()='use' and @*='#icon-cancel']")))
for i in element:
i.click()
# handle pagination
navigate_by_nums = True
if navigate_by_nums:
# navigate by numbers
num = int(
wait.until(EC.visibility_of_element_located(
(By.XPATH, "//input[@id='paginator-input-box']/parent::div/following-sibling::span"))
).text.replace("de", "").strip()
)
for i in range(1, num + 1):
p_input = wait.until(EC.element_to_be_clickable((By.ID, "paginator-input-box")))
actions.move_to_element(p_input) \
.click(p_input) \
.send_keys_to_element(p_input, Keys.CONTROL + "a") \
.send_keys_to_element(p_input, Keys.DELETE) \
.send_keys_to_element(p_input, str(i)) \
.send_keys_to_element(p_input, Keys.ENTER) \
.perform()
wait.until(EC.text_to_be_present_in_element_value((By.ID, "paginator-input-box"), str(i)))
print(f"Moved to page: {i}")
# do some parsing here
# do some parsing here
# do some parsing here
time.sleep(1)
else:
# navigate by next button
i = 1
while True:
next_btn = wait.until(
EC.element_to_be_clickable(
(By.XPATH, "//cmp-tol-main-paginator//cmp-icon[@name='icon-right']/ancestor::a")
)
)
if "u-disabled" in next_btn.get_attribute("class"):
print(f"Finished at page: {i}")
break
else:
actions.move_to_element(next_btn).click(next_btn).perform()
i += 1
print(f"Moved to page: {i}")
wait.until(EC.text_to_be_present_in_element_value((By.ID, "paginator-input-box"), str(i)))
# do some parsing here
# do some parsing here
# do some parsing here
time.sleep(1)
finally:
driver.quit()
There is a 'navigate_by_nums' flag you can change its value to test both approaches. Select the one which suits you best.
Answered By - sashkins
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.