This is the code i'm using, I pass a fake tracking number for now, I close the chat window, and then attempt to close the cookies window. But for some reason I just cannot click the X button, any help would be greatly appreciated.
Everything here works besides the last line.. You should be able to copy/paste into a .py file and test for yourself, given you have the correct packages installed.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import NoSuchElementException
import time
import os
import pandas as pd
import pyautogui
import undetected_chromedriver as uc
from seleniumbase import Driver
from selenium.webdriver.common.action_chains import ActionChains
# Add the driver options
driver = Driver(uc=True)
with driver:
# Go to the target website
driver.get("https://google.com")
driver.maximize_window()
#driver.set_window_size(1920, 820)
time.sleep(2)
driver.get("https://www.ups.com/track?track=yes&trackNums=1Z12345E1512345676&loc=en_US&requester=ST/")
time.sleep(3)
# Create another loop to run based on which element is found.
# Find UPS Element
U_Ele = driver.find_element(By.XPATH, "//span[contains(text(), 'UPS')]")
print(f"UPS Element found")
#Switch to UPS iframe
iframe = driver.find_element(By.XPATH, "//iframe[@id='inqChatStage']")
driver.switch_to.frame(iframe)
WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="top-bar"]/div/div[1]/div[1]/topbar-element/div/div/div/div'))).click()
time.sleep(2)
driver.find_element(By.XPATH, '//button[@class="close_btn"]').click()
The problem is that you switched context into the IFRAME but never returned from that context. Selenium was looking for the cookie panel close button inside the IFRAME. To take the context back to the full page, you need to use driver.switch_to.default_content()
.
Additional suggestions:
time.sleep()
. They make your script slower and aren't flexible like WebDriverWait
.WebDriverWait
consistently. You should use a wait on every element interaction/.find_element()
call. If you are going to click on the element then use EC.element_to_be_clickable()
. If you are going to interact with an element in other ways (get .text
, etc., use EC.visibility_of_element_located()
. Review the docs for more wait types and other info.WebDriverWait
and a bunch of other imports you aren't using. Keeping the imports list down to only what's necessary reduces code and confusion as you are coding.By.ID()
and By.CSS_SELECTOR()
to XPaths. IDs are the simplest and least likely to change on the page. CSS selectors are faster and a simpler syntax than XPaths.Taking all this into account, I simplified your code down to the working code below,
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
url = 'https://www.ups.com/track?track=yes&trackNums=1Z12345E1512345676&loc=en_US&requester=ST/'
driver = webdriver.Chrome()
driver.maximize_window()
driver.get(url)
wait = WebDriverWait(driver, 5)
# switch to chat IFRAME and close chat
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "inqChatStage")))
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div[aria-label='End Chat']"))).click()
driver.switch_to.default_content()
# close cookies panel
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.implicit_consent span.ups-icon-x"))).click()
driver.quit()