I am working on a script that shows CAPTCHA and a few other stuff in a pop window. I am writing script for FireFox. Is it possible that I feed the values and on hitting Submit button script could resume the operations? I guess, some kind of infinite loop?
You could wait for the submit button to be clicked by the user:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# load the page
driver.get("https://www.google.com/recaptcha/api2/demo")
# get the submit button
bt_submit = driver.find_element_by_css_selector("[type=submit]")
# wait for the user to click the submit button (check every 1s with a 1000s timeout)
WebDriverWait(driver, timeout=1000, poll_frequency=1) \
.until(EC.staleness_of(bt_submit))
print "submitted"
I believe what you're asking is if it's possible to have your selenium script pause for human interaction that can't be fully automated.
There are several ways to do this:
Easy but hacky feeling:
In your python script, put
import pdb
pdb.set_trace()
At the point you want to pause for the human. This will cause the python app to drop to a debugger. When the human has done their thing, they can type c and hit enter to continue running the selenium script.
Slightly less hacky feeling (and easier for the human).
At the point where you want to put the pause, assuming the user submits something, you can do something like (with an import time at the top):
for _ in xrange(100): # or loop forever, but this will allow it to timeout if the user falls asleep or whatever
if driver.get_current_url.find("captcha") == -1:
break
time.sleep(6) # wait 6 seconds which means the user has 10 minutes before timeout occurs
More elegant approaches are left as an exercise for the reader (I know there's a way you should be able to not have to busy-wait, but I haven't used it in too long)
One way is to check for some content of the next page that loads after entering captcha and wait till they're found.
Other way is to check for current URL until it changes (usually URL changes after entering CAPTCHA) or wait for the next URL with -
while driver.current_url == your_current_url:
wait
Related
I run selenium in python to do web testing, and I have noticed that, when I have added a longer wait in python, my selenium session is logged-out after a certain point of time.
Below Line of code I use to wait in the code
time.sleep(420)
I have tried to do some fake click during the wait period, but still, I have seen the security logout. is there any approach I can solve this issue?
I use python 3.5 and firefox web driver for testing.
What if you try to insert also a wait to Selenium.
In Java it looks like: SeleniumUtils.sleepQuietly(420);
There should also be a method for Python how to tell Selenium to wait (sleep) for certain time.
In your case, you have to say Selenium to wait, after you have called "the function" or click the button that needs to long (6 minutes) to execute.
when you use sleep() function you cannot do anything in that time. that is very useful between two lines of code where you need some time for processing like you are downloading file so, wait 5 seconds after 5 seconds add new parameters and download another file something like that.
you can surely do clicks without having sleep() function. between to click use sleep of 5 to 10 seconds like this your session will not expire it will run until you do driver.quit().
I am launching several requests on different tabs. While one tab loads I will iteratively go to other tabs and see whether they have loaded correctly. The mechanism works great except for one thing: a lot of time is wasted "Waiting for (website)..."
The way in which I go from one tab to the other is launching an exception whenever a key element that I have to find is missing. But, in order to check for this exception (and therefore to proceed on other tabs, as it should do) what happens is that I have to wait for the request to end (so for the message "Waiting for..." to disappear).
Would it be possible not to wait? That is, would it be possible to launch the request via browser.get(..) and then immediately change tab?
Yes you can do that. You need to change the pageLoadStrategy of the driver. Below is an example of firefox
import time
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium import webdriver
cap = DesiredCapabilities.FIREFOX
cap["pageLoadStrategy"] = "none"
print(DesiredCapabilities.FIREFOX)
driver = webdriver.Firefox(capabilities=cap)
driver.get("http://tarunlalwani.com")
#execute code for tab 2
#execute code for tab 3
Nothing will wait now and it is up to you to do all the waiting. You can also use eager instead of none
I am capturing the webpage but i want that the script should wait for sometime before capturing it because i am populating somedata using AJAX right now the script is not waiting and capturing the webpage before the ajax data is getting loaded.
i am using following code.
import blockspring
from selenium import webdriver
import time
import json
def screenshot(request, response):
driver = webdriver.PhantomJS(executable_path='/usr/local/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs')
driver.set_window_size(request.params["width"] or 1024, request.params["height"] or 768) # optional
driver.implicitly_wait(30) # seconds
driver.get(request.params["url"])
driver.save_screenshot('my_screenshot.png')
response.addFileOutput("screenshot", "my_screenshot.png")
response.end()
blockspring.define(screenshot)
The only reliable way to wait until the page is completely loaded, is using explicit waits. When there are AJAX requests they change something in the page. So you need to wait for those changes to occur. You have to determine what element is added (or removed) to the page as the last element, determine what the selector for this element is and wait for it.
This is the example from the documentation (it works the same way with PhantomJS):
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
This code waits up 10 seconds until an error is raised. You can use this time to specify the acceptable time that the site loads or does some things. If it doesn't do them in time and the test case fails, you know either that the site is too slow and must be optimized or that the site has changed and you have to adjust. It can also be a network error and a million other things.
The static way of using sleep is easier to add, but may lead to unexpected results. When the AJAX request took longer than expected, the processing may continue before the page is loaded. If you use a long sleep time, then you give time away with unnecessary waits.
To capture the screen only after your Ajax Data is Loaded..You can set Manual Wait time as per your requirement. Say you want your script to wait for 5 sec. so just include this command in your script where you want it to be paused.
Thread.sleep(5000);
Or
WebDriverWait wait_for_Data = new WebDriverWait(driver, 20);
wait_for_Data.until(ExpectedConditions.elementToBeClickable(By.--("Our Ajax Data Loading Condition")));
Lets say in the worst case the our Ajax data takes 20 seconds to Load.Even though we have 20 sec assigned for our Web-element the execution will go to next step as soon as Ajax Data is Loaded completely avoiding unnecessary wait.
I am using python 2.7 with Selenium webdriver for Firefox and I have a problem I can't solve or find solved on the internet.
My task is to open around 10k web pages (adsl router web interfaces - via ip address) and upload new firmware. I wrote the code but in order to finish it I must learn how to make selenium webdriver not to wait for page load like forever, but to wait for 2 minutes(it is time needed for new firmware to upload) and then proceed to next step.
I thought I let it wait for forever (wait for router to reconnect - much slower but doable by me without help) but the catch is when I click upload button it takes 2 minutes of uploading new firmware, then router reboots to apply changes (takes less then 2 minutes), then tries to connect (around 10 seconds) and even then if it gets some other IP it will never load and my program wait for forever.
So, I want to skip all of that and I want program to proceed to next router after first 2 minutes. Can it be done? I read something about "pageLoadingStrategy" but I couldn't understand how to use it.
Please write me if it is not understandable, because English is not my native language. Below you can see the code sample, after button.submit() it should wait for 2 minutes and proceed and not wait forever:
def firmware_upload():
global ip
br.get("http://"+ip+"/upload.html")
button = br.find_element_by_xpath('//input[#type="file" and #name="filename"]')
button.send_keys("/home/djura/Downloads/KW5815A_update_140417")
button.submit()
print ("Odradjen UPDATE SOFTWARE-a!")
return
see if this works.
try
{
br.manage().timeouts().pageLoadTimeout(2, TimeUnit.MINUTES);
global ip
br.get("http://"+ip+"/upload.html")
button = br.find_element_by_xpath('//input[#type="file" and #name="filename"]')
button.send_keys("/home/djura/Downloads/KW5815A_update_140417")
button.submit()
print ("Odradjen UPDATE SOFTWARE-a!")
return
}
catch(TimeoutException e)
{
print("2min over");
}
The problem is probably because you are using button.submit, which if I'm not mistaken waits for the return of the action. So instead you should find the actual submit button and click on it using click, e.g.
submit_button = br.find_element_by_id('SUBMIT_BTN_ID')
submit_button.click()
P.S. the fact that in your example code your button variable actually refers to an input element is misleading.
I am working on selenium with python for downloading file from a url.
from selenium import webdriver
profile = webdriver.FirefoxProfile()
profile.set_preference('browser.download.folderList', 2) # custom location
profile.set_preference('browser.download.manager.showWhenStarting', False)
profile.set_preference('browser.download.dir', '/tmp')
profile.set_preference('browser.helperApps.neverAsk.saveToDisk', 'text/csv')
browser = webdriver.Firefox(profile)
try:
browser.get("http://www.drugcite.com/?q=ACTIMMUNE")
browser.find_element
browser.find_element_by_id('exportpt').click()
browser.find_element_by_id('exporthlgt').click()
except:
pass
I want to set timeout for this program. Means, If within 60 seconds if this url is not loaded due to net issue, it should retry after each 60 seconds and after 3 tries, it should go ahead.
How can I achieve such in this code?
Thanks
You could use browser.implicitly_wait(60)
WebDriver.implicitly_wait
There is nothing built in to do this. However, I wouldn't have said it would be too hard.
Just use an explicit wait to find a particular element that should be there when the page loads. Set the timeout to be 60 seconds on this explicit wait.
Wrap this in a loop that executes up to three times. To avoid it running three times unnecessarily, put in a break statement when the explicit wait actually runs without any issue.
That means it'll run up to three times, waiting 60 seconds a time, and once it's successful it'll exit the loop. If it isn't successful after all of that, then it'll crash.
Note: I've not actually tried this but it's just a logical solution!