Python loops, need some advice - python

i trying to create a small program usign python and i need some help about python loops.
this small program will automates a fairly boring repetitive task.
I use module : selenium, time and pyautogui
here is the piece of code that i want to repeat until it no longer finds a certain element on the web page :
btnOptions = driver.find_element(By.XPATH, "/html/body/div[1]/div/div[1]/div/div[5]/div/div/div[3]/div/div/div[1]/div[1]/div/div/div[4]/div[2]/div/div[2]/div[3]/div[1]/div/div/div/div/div/div/div/div/div/div/div[8]/div/div[2]/div/div[3]/div/div")
btnOptions.click()
time.sleep(1)
pyautogui.press("down", presses=10)
pyautogui.press("enter")
time.sleep(1)
btn_move = driver.find_element(By.XPATH, "/html/body/div[1]/div/div[1]/div/div[6]/div/div/div[1]/div/div[2]/div/div/div/div/div/div/div[3]/div/div/div/div[1]")
btn_move.click()
as long as the btn_option is found, the program must continue otherwise it must stop.
I can't find a solution, if anyone can help me it would be very appreciated.
thanks a lot
i tried several loops but every time i get an error of course, I'm just new to coding in python :/

I've done a similar task. You may try this:
while True:
try:
btnOptions = driver.find_element(By.XPATH, "/html/body/div[1]/div/div[1]/div/div[5]/div/div/div[3]/div/div/div[1]/div[1]/div/div/div[4]/div[2]/div/div[2]/div[3]/div[1]/div/div/div/div/div/div/div/div/div/div/div[8]/div/div[2]/div/div[3]/div/div")
btnOptions.click()
time.sleep(1)
pyautogui.press("down", presses=10)
pyautogui.press("enter")
time.sleep(1)
btn_move = driver.find_element(By.XPATH, "/html/body/div[1]/div/div[1]/div/div[6]/div/div/div[1]/div/div[2]/div/div/div/div/div/div/div[3]/div/div/div/div[1]")
btn_move.click()
except NoSuchElementException:
break

Related

dHow to execute multiple lines of code, Python, Selenium

I am building a stock trading bot for fun and buying/selling on a stock trading simulator. I have all the webscraping done, all the send_keys done. I just want to be able to execute multiple lines of code as one simple command instead of having to repeat code over and over, making the program really long. For example, if I want to buy a stock, I have to execute all this code for it to complete the buy order:
driver.find_element_by_xpath('/html/body/div[4]/div[3]/div[1]/div[1]/div/div[1]/input').click()
driver.find_element_by_xpath('/html/body/div[4]/input').send_keys(('GOOGL') , Keys.RETURN)
time.sleep(1)
driver.find_element_by_xpath('/html/body/div[4]/div[3]/div[1]/table/tbody/tr/td[2]/a/span').click()
time.sleep(1)
driver.find_element_by_xpath('/html/body/div[7]/div/div/div[3]/div/button').click()
time.sleep(1)
driver.find_element_by_xpath('//*[#id="shares"]').click()
driver.find_element_by_xpath('//*[#id="shares"]').clear()
driver.find_element_by_xpath('//*[#id="shares"]').send_keys('0.01')
driver.find_element_by_xpath('/html/body/div[7]/div/div/div[1]/form/div[3]/div/button[3]').click()
Im pretty new at this and I know this wont work but, can I do something like:
Buy = driver.find_element_by_xpath('/html/body/div[4]/div/div[1]/input').click()
driver.find_element_by_xpath('/html/body/div[4]/input').send_keys(('GOOGL') , Keys.RETURN)
time.sleep(1)
driver.find_element_by_xpath('/html/body/div[4]/table/tbody/tr/td[2]/a/span').click()
time.sleep(1)
driver.find_element_by_xpath('/html/body/div[7]/div/div/div[3]/div/button').click()
time.sleep(1)
driver.find_element_by_xpath('//*[#id="shares"]').click()
driver.find_element_by_xpath('//*[#id="shares"]').clear()
driver.find_element_by_xpath('//*[#id="shares"]').send_keys('0.01')
driver.find_element_by_xpath('/html/body/div[7]/div/div[1]/form/div[3]/div/button[3]').click()
Then I can just add the 'Buy' (or whatever) variable in my If statement instead of that whole list of code.
if xxxxxxxxx
execute "Buy"
You mean like a function?
def buy():
driver.find_element_by_xpath('/html/body/div[4]/div[3]/div[1]/div[1]/div/div[1]/input').click()
driver.find_element_by_xpath('/html/body/div[4]/input').send_keys(('GOOGL') , Keys.RETURN)
time.sleep(1)
driver.find_element_by_xpath('/html/body/div[4]/div[3]/div[1]/table/tbody/tr/td[2]/a/span').click()
time.sleep(1)
driver.find_element_by_xpath('/html/body/div[7]/div/div/div[3]/div/button').click()
time.sleep(1)
driver.find_element_by_xpath('//*[#id="shares"]').click()
driver.find_element_by_xpath('//*[#id="shares"]').clear()
driver.find_element_by_xpath('//*[#id="shares"]').send_keys('0.01')
driver.find_element_by_xpath('/html/body/div[7]/div/div/div[1]/form/div[3]/div/button[3]').click()
Now you can run your code just with buy().
if condition:
buy()
def x(): was the correct solution.

send_keys of selenium in pyhon does not work

I am using python3, and want to send messages in Instagram using python, package selenium.
the code works great before. Today most of the time the send_keys() does not work.
I increase the sleep() time to be sure that it is not the internet speed problem. still, it does not work. Any idea? or any alternative ways to send text in a box (I am using python)?
this is the code:
webdriver.get('https://www.instagram.com/explore/tags/'+ hashtag_list[tag] + '/')
sleep(5)
check='//*[#id="react-root"]/section/main/article/div[2]/div/div[%d]/div[%d]/a/div' %(i,x)
sleep(10)
#'//*[#id=\"react-root\"]/section/main/article/div[1]/div/div/div[1]/div[%s]/a/div' % (x)
first_thumbnail = webdriver.find_element_by_xpath(check)
first_thumbnail.click()
sleep(10)
webdriver.find_element_by_xpath('/html/body/div[3]/div[2]/div/article/div[2]/section[1]/span[2]/button/span').click()
sleep(10)
comment_box = webdriver.find_element_by_xpath('/html/body/div[3]/div[2]/div/article/div[2]/section[3]/div/form/textarea')
sleep(20)
comment_box.send_keys("Hi") # this line does not work
sleep(10)
webdriver.find_element_by_xpath('/html/body/div[3]/div[2]/div/article/div[2]/section[3]/div/form/button').click()
sleep(10)
except:
print("Oops!")
sleep(10)
continue
Have you checked to make sure comment_box is actually a valid webelement by printing it? Just to make sure the selector is correct?
Because it should normally work, but perhaps Instagram is somehow doing something to block it.

After drag-and-drop operations, Selenium (Python) sometimes refuses to budge

After some dragging and dropping of elements into one another, the my program sometimes hangs. So I have a timeout set for it that runs the first block of code when the timer is reached. It does print the first line, but Selenium refuses to budge as driver.close() does not run after the print statement, and the rest of the code is rendered unreachable. The whole program hangs and cannot proceed. Is this a bug with Selenium or something I wrote?
print("This took too long. Will run a different function.")
driver.close()
driver.switch_to_window(driver.window_handles[0])
sleep(2)
# REST OF CODE
Could it possibly be the drag-and-drop code?
if elementsToMove:
a1 = random.choice(elementsToMove)
a2 = random.choice(elementsToMove)
while a1 == a2:
a2 = random.choice(elementsToMove)
actions = webdriver.ActionChains(driver)
actions.drag_and_drop(a1, a2)
actions.perform()
Years later, I will answer my own question.
I cringe reading my old code. I should have used sample, not choice twice.
I'm pretty sure it was a geckodriver issue. I don't know what fixed it, but it did get fixed.

Stop when error

In python, I am using selenium to scrape a webpage. There is a button that I need to repeatedly click until there is no button anymore. So far, I have code like:
count = 20
while count:
driver.find_elements_by_class_name('buttontext')[0].click()
count-=1
The problem is that I don't actually know how many times I need to do this - count = 20 is incorrect. What I actually need is for it to keep going until the command encounters an error (IndexError: list index out of range), and then stop. How can I do this?
Follow the EAFP approach - make an endless loop and break it once there is no element found:
from selenium.common.exceptions import NoSuchElementException
while True:
try:
button = driver.find_element_by_class_name("buttontext")
button.click()
except NoSuchElementException:
break
You should use the try statement to handle exceptions. It will run your code until it finds an exception. Your code should look something like that:
try:
while True:
click_function()
except Exception: #as Exception being your error
got_an_error() #or just a pass
I would follow the Selenium docs' recommendation and use .findElements().
findElement should not be used to look for non-present elements, use
findElements(By) and assert zero length response instead.
buttons = driver.find_elements_by_class_name("buttontext")
while buttons:
buttons[0].click()
// might need a slight pause here depending on what your click triggers
buttons = driver.find_elements_by_class_name("buttontext")
Do you need this?
while True:
try:
driver.find_elements_by_class_name('buttontext')[0].click()
except IndexError:
break
try will try to run some code, and except can capture the error that you select.
And if you didn't select an error, except will capture all errors. For more info.

Learning to use Assert and Asserttrue in Python for selenium web driver

Im trying to make a python webdriver to load a webpage and then assert true and run a print command if a text or object is there, and if not I want it to just continue running my loop. Im a noob to python and have been learning from Learn python the Hard Way, and reading documentation. Ive spent the last day or so trying to get my code finding text or elements, but it doesnt feed back info...Here is my code so far minus the top part about going to the webpage, I am just stuff on this count loop assert logic.
count = 1000.00
while count < 1000.03:
driver.find_element_by_id("select").clear()
driver.find_element_by_id("select").send_keys(str(count))
time.sleep(1)
driver.find_element_by_id("BP").click()
driver.find_element_by_id("BP").click()
count += 0.01 ## increases count to test
highervalue = driver.find_element_by_link_text("Select Error")
assertTrue(driver.link_contains_match_for("")) ##could also be, ##text_containt_match_for("ex") or driver.assertTrue(element in WEBPAGE)??
print 'Someone is %.7r' %count
else:
print 'I have %.7r' %count
time.sleep(1)
then the loop starts over again. The issue i am having is I want to find "Select Error" on the webpage in some kind of form, link, or text, and then if it is there print me a msg, and if not, to just continue my loop.
Is it better to use assert/asserttrue, or something like
def is_element_present(self, how, what):
try: self.driver.find_element(by=how, value=what)
except NoSuchElementException, e: return False
return True
or
Some other examples I have searched about that could be used:
self.assertTrue(self.is_element_present(By.ID, "FOO"))
self.assertTrue(self.is_element_present(By.TEXT, "BAR"))
self.assertTrue(self.is_text_present("FOO"))
self.assertTrue(self.driver.is_text_present("FOO"))
Can someone let me know how I would write the part when I find something in the webpage and it gives me feedback if found?
Selenium contains methods known as waits to assist with this specific situation. I would read up on the documentation of explicit waits. Also, there is another Stack Overflow question which may be useful to look at.
In addition, and slightly off topic, it is atypical to use Asserts in the way you have in the code shown. In general, you should not think of using Asserts to check for conditions, but rather a condition that must be true for the test to pass, otherwise the test stops and there is no reason to continue on.
Cheers.
Assuming that your "Select Error" message is actually a link_text, you could try using a 'try/except' statement.
try:
WebDriverWait(driver, 3).until(
expected_conditions.text_to_be_present_in_element((By.LINK_TEXT, "Select Error"), "Select Error")
)
print "Link Found..."
except NoSuchElementException:
pass
This code tries to find the "Select Error" link text for 3 seconds, catches the NoSuchElementException error, and then continues with your code.

Categories

Resources