I am trying to write a Python script with Selenium to see if I can automate the registration process for a sample event I created. Here is the event page: https://www.tickettailor.com/events/testing4/621753
I am able to access the page and click on "Join the guestlist" button:
from selenium import webdriver
driver = webdriver.Chrome('path_to_chromedriver')
driver.get('https://www.tickettailor.com/events/testing4/621753')
button = driver.find_element_by_link_text('Join the guestlist')
button.click()
After this, I need to select '1' from the dropdown menu of Category1 ticket and let # of tickets in Category2 remain as 0. Afterward, I need to enter the name and email to confirm my order.
However, I am not able to find the element to select the dropdown menu at all. I have tried driver.find_element_by_id,name,xpath,class_name,css_selector, but none of them have worked. I have also tried it with the select option as in:
select = Select(driver.find_element_by_id("quantity_2335182"))(quantity_2335182 is the id of the select tag in the inspect element in Chrome) and then select.select_by_value('1'). It keeps giving errors such as:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="quantity_2335182"]"}
(Session info: chrome=96.0.4664.93)
I would prefer if I don't have to specify the specific id as in "quantity_2335182" and can select the dropdown based on a general class name, tag, or css_selector. Also, I only want to select the first of the two dropdown menus (Only editing Category1 and not Category2).
wait=WebDriverWait(driver, 60)
driver.get('https://www.tickettailor.com/events/testing4/621753')
wait.until(EC.element_to_be_clickable((By.LINK_TEXT,"Join the guestlist"))).click()
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe#overlay_window")))
row1=Select(wait.until(EC.presence_of_element_located((By.XPATH,"(//select)[1]"))))
row1.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#submit"))).click()
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#name"))).send_keys("a")
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#email"))).send_keys("a")
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#email_confirm"))).send_keys("a")
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#submit"))).click()
## do captcha
key=wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,".h-captcha"))).get_attribute("data-sitekey")
print(key)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#submit"))).click()
Imports:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.select import Select
To automate this just click the link text, switch to the iframe overlay window , use the select import and select by index and then click the next button.
You are unable to interact with the dropdown because that popup is within Iframe. So First you have to switch to iframe and then you can interact with elements.
Here, Please see it's within iframe:
Your code steps would be :
Click on that Join the guestlist Button
Switch to Iframe. i.e driver.switch_to_frame("overlay_window")
Interact with your element or dropdown as per your requirement
Once you are done with all your operation with popup, Switch to default content i.e driver.switch_to.default_content()
Related
I am trying to select a value from a dropdown menu using the Selenium Select method but I am unable to correctly locate the right element as illustrated in other Stackoverflow posts as my element lacks an ID as in other Stackoverflow posts. I have tried using the Xpath, Class_Name and CSS_Selector as an alternative but I keep getting an error "Unable to locate element".
This is the HTML:
<select class="lf-simpelselect lf-bottom-margin" data-bind="options: activiteitenOptions, value: activiteit, optionsText: 'Naam', optionsValue: 'Id', visible: toonActiviteiten()" style=""><option value="0bdae2c9-6ebc-4396-b3bb-0e587f9bbe86">Latin Jam</option><option value="c18aef82-be4d-4881-ae96-28aa72161c17">Kiddo Swing 6-8 jr</option><option value="8cbe6618-68cd-47f1-8a79-29db71498292">Ballet </option><option value="8d03eb2f-02ea-434d-8520-30b2f02e18f1">Pilates</option><option value="30358ec5-9751-4b13-8514-4db7b541c540">Gold 40+</option><option value="b811c4be-703b-4193-8f60-57bdb574a60a">Feminine</option><option value="2c6b4f41-6953-4347-99b9-70c33f48da07">City Jam</option><option value="696ba3a2-a453-4550-9cbe-7a00d46dfb14">Dojo</option><option value="fc8b9e43-401f-4e38-8d0b-8afba5f1226b">Power Jam</option><option value="7192a0d5-65b1-43a0-80d6-987b90cf505c">Dans Mix 9 - 12 jr</option><option value="820cf6c6-c9a6-4759-939e-988c646a69f7">Barre Workout</option><option value="e9bfd01d-b183-483a-b809-b2d9dd62354d">Latin House 18+</option><option value="505e1c62-9e68-4569-a7ef-b6566ff1b56d">Afro</option><option value="e4899faa-969e-4953-af1f-bc7eba080bec">Hip Hop</option><option value="796f9e98-f54c-486c-bc62-e6a2e74a5f45">Contemporary Flow </option><option value="88845fb5-e1ab-418d-ba3c-ed1131821835">Modern</option><option value="cb7fa275-b034-4f04-8265-ef747fe73179">Dancehall</option></select>
The code of my try at using the Select() to change the value is as follows:
url = "https://prd.mylogifit.com/logifitweb/genericwidgetbyid.html?a=Touchee&widgetId=73f1f696-5063-4fb7-9a8d-c588ef149eb4"
browser = webdriver.Chrome(executable_path='./chromedriver')
browser.get(url)
# Select lesson type (afro)
lesson_droplist = Select(browser.find_element(By.CLASS_NAME, 'lf-simpelselect lf-bottom-margin'))
lesson_droplist.select_by_value("Afro")
How do I use the Select method to change the drop-down value from Hip-Hop to Afro?
To select the <option> with text as Pilates as the desired element is a dynamic element, you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
Using CSS_SELECTOR:
driver.get("https://prd.mylogifit.com/logifitweb/genericwidgetbyid.html?a=Touchee&widgetId=73f1f696-5063-4fb7-9a8d-c588ef149eb4")
Select(WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "select.lf-simpelselect.lf-bottom-margin[data-bind*='activiteitenOptions']")))).select_by_visible_text('Pilates')
Using XPATH:
driver.get("https://prd.mylogifit.com/logifitweb/genericwidgetbyid.html?a=Touchee&widgetId=73f1f696-5063-4fb7-9a8d-c588ef149eb4")
Select(WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//select[#class='lf-simpelselect lf-bottom-margin' and contains(#data-bind, 'activiteitenOptions')]")))).select_by_visible_text('Pilates')
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
from selenium.webdriver.support.ui import Select
Browser snapshot:
References
You can find a couple of relevant discussions in:
How to select an option from the dropdown menu using Selenium and Python
from selenium.webdriver.support.ui import Select
lesson_droplist = Select(driver.find_element(By.CLASS_NAME, "lf-simpelselect"))
lesson_droplist.select_by_visible_text("Afro")
You should select by visible text not value
If you want to select by value then
lesson_droplist= Select(driver.find_element(By.CLASS_NAME, "lf-simpelselect"))
lesson_droplist.select_by_value("505e1c62-9e68-4569-a7ef-b6566ff1b56d") #Afro's value
The Class name has more than one matches, that is why you are getting that error, try the below XPath:
from selenium.webdriver.support.select import Select
dropdown = Select(driver.find_element(By.XPATH, "(.//select[#class='lf-simpelselect lf-bottom-margin'])[2]"))
dropdown.select_by_visible_text("Afro")
You can use XPath with some solution for waiting. There are two option time library or WebDriverWait.
You can try this one for time libray:
import time
time.sleep(3)
dropdown = Select(browser.find_element(By.XPATH, "(.//select[#class='lf-simpelselect lf-bottom-margin'])[2]"))
dropdown.select_by_visible_text("Afro")
time.sleep(3)
text = browser.find_element(By.XPATH, "//div[#data-bind='text: lesOmschrijving()']").text
print(text)
You can try this for WebDriverWait(but its just wait for this XPath and you might be need another waiting for getting another text):
wait.until(EC.presence_of_element_located((By.XPATH, "(.//select[#class='lf-simpelselect lf-bottom-margin'])[2]")))
Generally, you need an wait to make sure the relevant elements are loaded in the browser.
This question already has answers here:
Click on ember.js enabled element using Selenium
(5 answers)
Closed 1 year ago.
At this stage, all the script aims to do is to locate the search bar in a digital library, send the name of the resource I am looking for, click on it and get the current url. The first bit (sending keys to search bar) works fine. But I have noticed that the second try/finally block only executes when I right click and inspect any element on the page. If I don't, I get the following error message :
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="ember767"]"}
My code:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
PATH = "/Applications/chromedriver"
ser = Service(PATH)
driver = webdriver.Chrome(service=ser)
driver.maximize_window()
driver.implicitly_wait(20)
driver.get("https://browzine.com/libraries/1374/subjects")
print("Enter targeted Journal name:")
targeted_journal = input()
wait = WebDriverWait(driver, 10)
try:
button = driver.find_element(By.ID, "ember648")
driver.implicitly_wait(10)
ActionChains(driver).move_to_element(button).click(button).perform()
button.send_keys(targeted_journal)
button.send_keys(Keys.RETURN)
finally:
pass
# step 2 : click targeted journal and get current url
try:
driver.implicitly_wait(20)
click_journal = driver.find_element(By.ID, "ember767")
ActionChains(driver).move_to_element(click_journal).click(click_journal).perform()
targeted_url = driver.current_url
finally:
pass
print(targeted_url)
driver.quit()
Update - answer found
The ID initially collected for the targeted element was a dynamic one. It was only as such when the developer tools window was open. Therefore the script was only able to detect that particular ID when "Inspect element" was clicked as it was the only case in which the targeted element was assigned this particular ID ("ember767" in my case).
To avoid this issue, an Xpath was used to locate the element instead. See Mayank Shukla's answer below.
In some cases, element's ID or other attributes changes or attribute's value appears on mouse hover. So it's preferred to use xpath for locating such elements
In this scenario, I think the element's id is changing after you are hovering the mouse. Try using xpath and let me know if that works. Because might be after browser refresh this is happening i.e. element's id is changing.
The problem: trying to click on a drop-down within an iframe using Chrome driver and Selenium with Python.
Hi all. A user kindly helped me with a newbie query yesterday. I was unable to click on a link within a url and this was because I had to switch into an iframe. This part of the code now works and I navigate to a drop-down menu for which I wish to make a selection.
I've tried accessing this element through amending my code but receive the traceback that it is unable to locate the element. I am trying to change the value of the drop-down to 'Aldershot' using Select, finding the element by name and visible text. Any advice greatly appreciated.
#setup
from selenium import webdriver
from selenium.webdriver.support.select import Select
#utilise chrome driver to open specified webpage
driver = webdriver.Chrome("/Users/philthomas/Desktop/web/chromedriver")
driver.maximize_window()
driver.get("http:enfa.co.uk")
#switch to specific iframe and click on 'clubs' button on left hand menu
driver.switch_to.frame(2);
ClubsLink=WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,
"//span[contains(text(),'Clubs')]")))
ClubsLink.click()
#find drop-down menu and choose 'Aldershot'
select_box = Select(driver.find_element_by_name("team"))
select_box.select_by_visible_text("Aldershot")
Traceback:
HTML:
The reason you are getting error because the select dropdown present inside an iframe.
You need to switch to iframe first inorder to select the element.
Induce WebDriverWait and frame_to_be_available_and_switch_to_it()
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.support.select import Select
#utilise chrome driver to open specified webpage
driver = webdriver.Chrome("/Users/philthomas/Desktop/web/chromedriver")
driver.maximize_window()
driver.get("http:enfa.co.uk")
#switch to specific iframe and click on 'clubs' button on left hand menu
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.NAME,"left")))
ClubsLink=WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,
"//span[contains(text(),'Clubs')]")))
ClubsLink.click()
#return from iframe
driver.switch_to.default_content()
#Switch to another iframe
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.NAME,"main")))
#find drop-down menu and choose 'Aldershot'
teamselect=WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.NAME,"team")))
select_box = Select(teamselect)
select_box.select_by_visible_text("Aldershot")
Browser snapshot:
Thanks already to the users who have helped me on this piece of work. I am navigating to the url enfa.co.uk. I use ChromeDriver with Selenium in Python and navigate (via iframe) to click on the 'Clubs' link from the left hand menu, then switch iframes to select a drop-down value 'Select Club = Shrewsbury Town' and then click on a specific season '1950/51'.
This takes me to a table for which I am trying to click on a value under the column 'Res'. This would take me to further data (I have to login to access this data, but either way, a user clicking on this link would take them to the subscribe page which also has the desired result).
I have checked that I am in within the expected table by calculating the number of rows/columns and this matches my expectations (97/9). However when I try and click on the element required (in this example, the Res is 0-0 which should correspond to row 7 / column 7) I receive a traceback stating that the element is not interactable. Similarly if I try and print this element it shows as blank. Any thoughts? Thanks in advance.
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.support.select import Select
#utilise chrome driver to open specified webpage
driver = webdriver.Chrome("/Users/philthomas/Desktop/web/chromedriver")
driver.maximize_window()
driver.get("http:enfa.co.uk")
#switch to specific iframe and click on 'clubs' button on left hand menu
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.NAME,"left")))
ClubsLink = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,"//span[contains(text(),' Clubs')]")))
ClubsLink.click()
#return from iframe
driver.switch_to.default_content()
#Switch to main iframe
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.NAME,"main")))
#find drop-down menu and choose 'Team'
teamselect=WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.NAME,"team")))
select_box = Select(teamselect)
select_box.select_by_visible_text("Shrewsbury Town")
#ChooseSeason
season=WebDriverWait(driver,10)until(EC.presence_of_element_located((By.XPATH,"//a[contains(text(),'1950/51')]")))
season.click()
#count number of rows & columns in table to check:
rows=len(driver.find_elements_by_xpath("/html/body/form/div[7]/table/tbody/tr"))
cols=len(driver.find_elements_by_xpath("/html/body/form/div[7]/table/tbody/tr[7]/td"))
print('No of rows in table:', rows)
print('No of columns in table:', cols)
#click on specific Res - in this case, 0-0 Aug 19th v Scunthorpe
match=WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,"/html/body/form/div[7]/table/tbody/tr[7]/td[7]/a")))
match.click()
print('Check:', value)
HTML of required element:
Traceback error:
The element is present in the html before it's visible, so EC.presence_of_element_located is true but the element is still hidden and can't be clicked. Use EC.visibility_of_element_located instead
match = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "/html/body/form/div[7]/table/tbody/tr[7]/td[7]/a")))
Please find updated solution. Explicit wait method needs to be change while clicking on the elements.
Also I have updated code to switch to default content before switching to main frame
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.support.select import Select
#utilise chrome driver to open specified webpage
driver = webdriver.Chrome(executable_path=r"C:\New folder\chromedriver.exe")
driver.maximize_window()
driver.get("http:enfa.co.uk")
#switch to specific iframe and click on 'clubs' button on left hand menu
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.NAME,"left")))
ClubsLink=WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,"//span[contains(text(),'Clubs')]")))
ClubsLink.click()
driver.switch_to.default_content()
#Switch to main iframe
WebDriverWait(driver,15).until(EC.frame_to_be_available_and_switch_to_it((By.NAME,"main")))
#find drop-down menu and choose 'Team'
teamselect=WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.NAME,"team")))
select_box = Select(teamselect)
select_box.select_by_visible_text("Shrewsbury Town")
season=WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,"//a[contains(text(),'1950/51')]")))
season.click()
#count number of rows & columns in table to check:
rows=len(driver.find_elements_by_xpath("/html/body/form/div[7]/table/tbody/tr"))
cols=len(driver.find_elements_by_xpath("/html/body/form/div[7]/table/tbody/tr[7]/td"))
print('No of rows in table:', rows)
print('No of columns in table:', cols)
#click on specific Res - in this case, 0-0 Aug 19th v Scunthorpe
match=WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"//a[contains(text(),'Scunthorpe & Lindsey Utd')]")))
match.click()
I can't find a solution how this element cannot be found by using a selenium xpath. Other button on other websites always working just fine. Usually what I would normally do is, just open up a page and inspect the element and I would right click it and copy the xpath. Done.
But this website, www.gsc.com.my (a malaysian cinema booking site). Seems not able to find the button. Is it protected by another security layer?
Lets see the code below,
from selenium import webdriver
chromedriver_path = './chromedriver.exe'
driver = webdriver.Chrome(chromedriver_path)
driver.get('https://www.gsc.com.my')
driver.find_element_by_xpath("""//*[#id="btnNext"]""").click()
The error Message:
no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id="btnNext"]"}
Button is located inside an iframe, so you need to switch to that frame before clicking the button:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait as wait
from selenium.webdriver.support import expected_conditions as EC
driver.switch_to.frame('getQuickFilter_ctrl_ifrBox')
wait(driver, 10).until(EC.element_to_be_clickable((By.ID, "btnNext"))).click()
Because there are two elements with id btnNext, you'll have to specify which of them using an index, 1 for the first, 2 for the second.
driver.find_element_by_xpath("""//*[#id="btnNext"][1]""").click()
You can try with this css selector :
div.container input#btnNext
Note that you will need to switch to iframe first , cause the check button is in a iframe.
For switching to iframe :
driver.switch_to.frame(driver.find_element_by_id("getQuickFilter_ctrl_ifrBox"))
and for clicking on check Button
wait = WebDriverWait(driver, 10)
check_button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.container input#btnNext")))
check_button.click()