I'm trying to use Selenium w/ Python to click on answers to problems posted at a tutoring site, so I can take tests over the command line.
I enter the following:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver.get('https://www.varsitytutors.com/sat_critical_reading_diagnostic_1-problem-10821')
(an annoying popup comes up at this point -- we can ignore that for now)
Answers on the page are embedded in forms like this:
<div class="question_row">
<form class="button_to" method="post" action="/problem_question_answers/save_answer?answer_id=539461&problem_id=5065&qotd=false&question_id=10821">
<input id="answer_539461" class="test_button" type="submit" value="select" /><input type="hidden" name="authenticity_token" value="LE4B973DghoAF6Ja2qJUPIajNXhPRjy6fCDeELqemIl5vEuvxhHUbkbWeDeLHvBMtEUVIr7okC8Njp4eMIuU3Q==" /></form>
<div class="answer">
<p>English dramatists refused to employ slang in their work.</p>
</div>
<div style="clear:both"></div>
</div>
My goal is to click an answer such as this one in order to get to the next question using Selenium.
I thought it might be as easy as doing this:
answer_buttons=driver.find_elements_by_class_name('test_button')
answer_buttons[1].click()
But I get error messages saying that the element is out of the frame of the driver.
I've also tried submitting the form, which doesn't produce an error message:
answer_forms=driver.find_elements_by_class_name('button_to')
answer_forms[1].submit()
But it redirects to a different url that doesn't load:
http://www.varsitytutors.com/sat_critical_reading_diagnostic_1-problems-results-d9399f1a-4e00-42a0-8867-91b1c8c9057d
Is there any way to do this programmatically, or is the website's code going to prevent this?
Edit:
With some help I was able to click the button once initially. But an identical submit button (by xpath) for the next question remains unclickable. This is the code I'm presently using:
driver.get('https://www.varsitytutors.com/practice-tests')
# click subject
subject=driver.find_element_by_xpath('/html/body/div[3]/div[9]/div/div[2]/div[1]/div[1]')
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,'/html/body/div[3]/div[9]/div/div[2]/div[1]/div[1]')))
subject.click()
# select specialty
specialty=driver.find_element_by_xpath('/html/body/div[3]/div[9]/div/div[2]/div[2]/div[1]/div[2]/a[4]')
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,'/html/body/div[3]/div[9]/div/div[2]/div[2]/div[1]/div[2]/a[4]')))
specialty.click()
# select test
taketest=WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,'/html/body/div[3]/div[8]/div[3]/div[1]/div[1]/a[1]')))
driver.execute_script("arguments[0].click();", taketest)
# click away popup
button=WebDriverWait(driver,5).until(EC.element_to_be_clickable((By.XPATH,"//button[contains(.,'No Thanks')]")))
button.location_once_scrolled_into_view
button.click()
# select first choice
choice=WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH,'/html/body/div[3]/div[7]/div[1]/div[3]/div[1]/form/input[1]')))
driver.execute_script("arguments[0].click();", choice)
I repeat this code again over the next few lines. It has no effect, however; the drive stays on question two and the next few clicks don't work...
choice=WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH,'/html/body/div[3]/div[7]/div[1]/div[3]/div[1]/form/input[1]')))
driver.execute_script("arguments[0].click();", choice)
choice=WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH,'/html/body/div[3]/div[7]/div[1]/div[3]/div[1]/form/input[1]')))
driver.execute_script("arguments[0].click();", choice)
Try the following code.This will handle pop-up and click on the select button.
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 import webdriver
driver=webdriver.Chrome()
driver.get('https://www.varsitytutors.com/sat_critical_reading_diagnostic_1-problem-10821')
driver.maximize_window()
button=WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH,"//button[contains(.,'No Thanks, Start The Test')]")))
button.location_once_scrolled_into_view
button.click()
eleQuestions=WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,'input.test_button')))
driver.execute_script("arguments[0].click();", eleQuestions[2])
button=WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH,"//button[contains(.,'No Thanks')]")))
button.location_once_scrolled_into_view
button.click()
Please note: you can change the indexes from 2 to 6.
Snapshot:
If you would like to select any particular Question as you mentioned then try below code.
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 import webdriver
driver=webdriver.Chrome()
driver.get('https://www.varsitytutors.com/sat_critical_reading_diagnostic_1-problem-10821')
driver.maximize_window()
button=WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH,"//button[contains(.,'No Thanks, Start The Test')]")))
button.location_once_scrolled_into_view
button.click()
eleQuestions=WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH,"//div[./p[text()='English dramatists refused to employ slang in their work.']]/parent::div//input[1]")))
driver.execute_script("arguments[0].click();", eleQuestions)
button=WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH,"//button[contains(.,'No Thanks')]")))
button.location_once_scrolled_into_view
button.click()
Related
I'm trying to click on a checkbox filter on a website with selenium python. This is a part of its HTML code linked to one of the checkbox options.
<div class="shopee-checkbox" bis_skin_checked="1">
<label class="shopee-checkbox__control">
<input type="checkbox" name="" value="Jabodetabek">
<div class="shopee-checkbox__box" bis_skin_checked="1">
<i> </i>
</div>
<span class="shopee-checkbox__label">Jabodetabek</span>
</label>
</div>
I tried following, but it didn't work.
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('https://shopee.co.id/search?keyword=baju%20laki-laki')
time.sleep(5)
driver.find_element(By.XPATH, "//input[#value='JABODETABEK']").click()
I read the answers to similar questions, mostly they suggest using 'id' and 'name' to find the element. However, in this input tag, there are only 'type' and 'value'.
Here is one way to select that checkbox:
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, 25)
[..]
wait.until(EC.element_to_be_clickable((By.XPATH, '//span[text()="Jabodetabek"]'))).click()
print('clicked on Jabodetabek')
Selenium documentation can be found here.
#value for the checkbox in the xpath is incorrect. The selenium web locator techniques are case sensitive. So make sure to use exact values while identifying objects. Changing your xpath to below would fix the issue.
driver.find_element(By.XPATH, "//input[#value='Jabodetabek']").click()
I want know how I can click a button in this page here with selenium the code I try is this
import selenium
from selenium import webdriver
from time import sleep
PATH= "C:\Program Files (x86)\chromedriver.exe"
driver = webdriver.Chrome(PATH)
driver.get("https://yopmail.com/it/")
inputsSI= driver.find_element_by_class_name("md").click()
print(inputsSI)
sleep(100)
driver.close()
the error I get is this:
Message: element not interactable
It's because find_element_* methods will return the first occurrence of the element they find. If you see the HTML page there is another div element before the button that has this "md" class and of course it is not the button you are looking for.
You are looking for this buttun :
<div id="refreshbut">
<button class="md" style="border-radius: 20px;"
title="Controllare la posta #yopmail.com"
onclick="{if(chkl())go()}"><i
class="material-icons-outlined f36"></i></button>
<input type="submit" style="display:none;">
</div>
It is wrapped inside a div with id of "refreshbut".
So all you have to do is first get this div by id. Then search for the element which has the "md" class which is indeed the button you are looking for. (you could also get the button with XPATH. it's up to you)
like:
inputsSI = driver.find_element(By.ID, "refreshbut") \
.find_element(By.CLASS_NAME, "md") \
.click()
Note 1: It's better to use raw-string for your PATH variable.
Note 2: I would put the driver.close() statement inside the finally block so that it always runs
To click on the md button use button.md as a selector then wait for the element to be interactable. I don't know what goes in there so I just added a send keys of a.
wait=WebDriverWait(driver,30)
driver.get("https://yopmail.com/it/")
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#login"))).send_keys('a')
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"button.md"))).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
I'm using Selenium Python to do the same action for different users and the flow is as follows,
1- the webpage show list of user ids
2- I search for 1 user-id (Iteration)
3- I click on the check box next to the user-id
4- I click on done
My issue is with the check box, it is clickable in the first row of iteration but then it becomes unclickable with the next row.
Checkbox Element:
<input type="checkbox" class="ant-checkbox-input" value="" xpath="1">
I have also tried ActionChains but I got the error: stale element reference: element is not attached to the page document
Thank you
the input checkbox might be in disable state or some javascript load is yet to happen before checkbox become availabe.
try this code:
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.XPATH,"//tbody/tr[1]/td[1]/span[1]/label[1]/span[1]/input[1]"))).click()
another problem might be xpath changes depending on user you logged in.
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.XPATH,'//input [#type="checkbox"]'))).click()
above code will work only if you have 1 checkbox.
This code will try to click all the check boxes present on page, if this works we could narrow down XPath.
els=driver.find_elements_by_xpath('//input [#type="checkbox"]')
for el in els:
try:
el.click()
except:
pass
I'm trying to develop a bot that automatically handles the deletion of various posts from a website. I have stumbled across a major problem which does not allow me to proceed any further.
The page I've achieved to open presents various checkboxes with the following input:
<input type="checkbox" name="ids[]" value="305664759" onclick="toggleDeleteButtons()">
What I have to do is check simultaneously each checkbox and then click on delete button. Then a popup will appear, where I have to click another "Delete" button with the following input:
<input id="btnDelAds" class="button" href="javascript:void(0)" onclick="document.manageads.cmd.value='del';if (submit_batch_delete()){document.manageads.submit();}else{closeDialogDelete();}">
And then another popup will appear for confirming, but that's another problem.
In fact, the troubles come when I try to find the checkboxes.
This is the code for handling the first part of the site, and findind the checkboxes:
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.keys import Keys
#HANDLING ACCESS
email = "somemail"
password = "somepass"
driver = webdriver.Firefox()
driver.get("https://www.somesite.it/account/manageads")
login_field = driver.find_element_by_id("login_email")
login_field.clear()
login_field.send_keys(email)
login_field = driver.find_element_by_id("login_passwd")
login_field.clear()
login_field.send_keys(password)
login_field.send_keys(Keys.ENTER)
#HANDLING DELETE OF POSTS
while True:
try:
elem = driver.find_element_by_xpath("//input[#type='checkbox' and contains(#name, 'id')")
print("Found")
except NoSuchElementException:
print("End")
break
elem.click()
(I've censored site url and credentials)
print("Found") clause is obviously not executed. The idea was to check consecutively every checkbox, probably I've done this in the wrong way.
What I get instead is "END" in console.
Any help will be strongly appreciated. Thanks in advance.
To trigger the presence of the popup with text as Delete you have to induce WebDriverWait for the desired element_to_be_clickable() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[name^='ids'][onclick^='toggleDeleteButtons'][type='checkbox']"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[starts-with(#name, 'ids') and starts-with(#onclick, 'toggleDeleteButtons')][#type='checkbox']"))).click()
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
You can find a relevant discussion in How to locate a button with a dynamicID
I'm trying to scrape this with a combination of python 3.5/selenium/phantomjs.
There is a button which loads more offers
<button data-behavior="result-paging" class="button button-text--centered">
Mehr laden
</button>
This exact button is twice inside the HTML-Code and if all offers are listed the first button looks as follows, while the second button stays the same:
<button data-behavior="result-paging" class="button button-text--centered is-hidden">
Mehr laden
</button>
To click the first button I tried:
while True:
try:
time.sleep(4)
btnElements = driver.find_elements_by_xpath("//button[#data-behavior='result-paging']")
for btnElement in btnElements:
btnElement.click()
# btnElement.send_keys("\n")
if i==11:
break
else:
i=i+1
except:
break
and
while True:
try:
time.sleep(4)
elements= driver.find_elements_by_xpath("//button[#data-behavior='result-paging']")
driver.execute_script("arguments[0].click();", elements[0])
if i==11:
break
else:
i=i+1
except:
break
The loop was just there for quick testing purposes since the script would run eternally otherwise. With booth approaches no new content was loaded, so clicks werent working.
Does anybody have an idea how to solve this issus (perform clicks and load other offers)?
Edit:
Apparently this problem is caused by phantomjs, since I could run the same script with chromedriver. Unfortunately I need to run phantomjs. Did anybody experienced this behaviour before?
As per your code block the Locator Strategy which you have used as ...
find_elements_by_xpath("//button[#data-behavior='result-paging']")
... doesn't identifies the visible button with text as Mehr laden uniquely.
Solution
To identify the visible button with text as Mehr laden uniquely you can use eith of the following Locator Strategies :
CSS_SELECTOR :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
# lines of code
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div[data-psa-scope=tarifflist] button.button.button-text--centered"))).click()
XPATH :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
# lines of code
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[#data-psa-scope='tarifflist']//button[#class='button button-text--centered']"))).click()