WhatsApp Web automation with Selenium not working - python

I found this python script on github that sends automatic WhatsApp Web messages through Selenium.
#https://www.github.com/iamnosa
#Let's import the Selenium package
from selenium import webdriver
#Let's use Firefox as our browser
web = webdriver.Firefox()
web.get('http://web.whatsapp.com')
input()
#Replace Mr Kelvin with the name of your friend to spam
elem = web.find_element_by_xpath('//span[contains(text(),"Mr Kelvin")]')
elem.click()
elem1 = web.find_elements_by_class_name('input')
while True:
elem1[1].send_keys('hahahahahahaha')
web.find_element_by_class_name('send-container').click()
Even though it was meant for spamming, I was trying to adapt it for a good purpose, but the script as it stands doesn't seem to work. Instead of sending a message through WhatsApp Web, it simply loads a QR authentication screen and then it does nothing after I authenticate with my cellphone.
Any clue as to why this is happening? I'm running the lastest version of Selenium WebDriver on Firefox and geckodriver has already been extracted to /usr/bin/.

I realise this post is older, but it still seems to be frequently looked at.
The keystroke explanation of #vhad01 makes sense but did not work for me.
A simple dirty workaround that worked for me:
Replace input() with
import time
time.sleep(25)
while 25 is the amount of seconds it will be waited until the code will be further executed. (15 should also be sufficient to scan the QR code,...).

The way I implement the scanning of the QR code is by detecting if the search bar is present or not on the page.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
chatlist_search = ".jN-F5.copyable-text.selectable-text"
web.get("https://web.whatsapp.com")
WebDriverWait(web, 60).until(EC.visibility_of_element_located((By.CSS_SELECTOR, chatlist_search)))
This would wait until the chat search-bar is rendered on the page, or it will timeout in 60 seconds.

This line :
input()
is waiting for a keystroke to continue.
Simply press any key after scanning.

I was writing a selenium script to schedule my msgs and I came across your question. Yes, problem is that input() line.
Instead of using input():
Use time.sleep(), no doubt it will work but better approach it to use implicit_wait(15)
Time.sleep() makes you wait even after scanning. The script totally stops till the given seconds.
In implicit_wait() the if element appear before specified time than script will start executing otherwise script will throw NoSuchElementException.
I used a more different method to whatsapp_login() and QR scanning. To see that my repo link: https://github.com/shauryauppal/PyWhatsapp
You would like this approach too.

A better way is to scan the QR code hit return in the command line and the proceed further on your code.
browser = webdriver.Firefox()
browser.get('https://web.whatsapp.com/')
print('Please Scan the QR Code and press enter')
input()
This is all you need and is also not very vague logic to apply to this problem.

Related

How to use selenium to navigate web pages with multiple drop downs and check boxes

I am trying to automate a process to download data from a website. The code works if I run it step by step but if I run it all at once it fails. Giving the error
ElementNotInteractableException: Message: element not interactable
I have got around this using time.sleep(x amount of time) but it still seems to fail intermittently. I am having trouble implementing implicit waits. Any help would be appreciated. Code below.
import selenium
browser = webdriver.Chrome(executable_path=r'path\to\chromedriver.exe')
browser.get("https://map.sarig.sa.gov.au/")
browser.maximize_window()
browser.switch_to.frame(browser.find_element_by_id('MapViewer'))
browser.find_element_by_xpath('//*[#id="TourWidget"]/div[1]/span').click()
browser.find_element_by_xpath('//*[#id="menuAllMapLayers"]/div[2]/p').click()
browser.find_element_by_xpath('//*[#id="238"]/li[1]/div/div/span[1]').click()
time.sleep(3)
browser.find_element_by_xpath('//*[#id="238"]/li[1]/div/div/span[1]').click()
browser.find_element_by_xpath('//*[#id="238"]/li[3]/div/div/label/span').click()
browser.find_element_by_xpath('//*[#id="239"]/li[1]/div/div/span[1]').click()
browser.find_element_by_xpath('//*[#id="239"]/li[3]/div/div/label/span').click()
browser.find_element_by_xpath('//*[#id="menuActiveLayers"]').click()
browser.find_element_by_xpath('//*[#id="groupOptions238"]/span').click()
time.sleep(3)
browser.find_element_by_xpath('//*[#id="238"]/li[2]/div/div[3]/div[2]/span').click()
browser.find_element_by_xpath('//*[#id="groupOptions239"]/span').click()
time.sleep(3)
browser.find_element_by_xpath('//*[#id="239"]/li[2]/div/div[3]/div[2]/span').click()
Use ActionChains and get access to pause(3) instead of using sleep(3) but it could also help to use Waits and checking if your elements actually are "visible" rather than "present" (see expected_conditions)
It's a lot of dropdowns so maybe there are not visible all the time, but you can run these checks after doing a move_to_element() so it would actually be present.

How do I make this python automation code using Pyautogui faster and safer?

This is a code that I use to register my courses for semester. I want this code to run fastest as possible so that I can select my preferred courses faster than other students who select them manually, the seats and section of desired classes fill-up fast. My concern is that if my code runs faster and the browser cant keep up with it then it will cause issue. For example I will be running on google chrome browser. And what should I change to make this code faster without risking Thanks in advance.
import pyautogui
import time
import webbrowser
pyautogui.FAILSAFE = False
time.sleep(1)
pyautogui.hotkey('alt', 'tab')
##Subject choose
time.sleep(0.5)
pyautogui.hotkey('ctrl', 'f')
pyautogui.write('PHY182.1')
pyautogui.press('enter')
pyautogui.press('esc')
pyautogui.hotkey('shift', 'tab')
pyautogui.press('space')
I did something similar I while ago, not exactly your case but I believe it would help. If you want it to be as fast as possible while making sure that the browser if keeping up with you, you should make your script recognize that the page you are going to be on has fully loaded, for this I would use selenium, so when the page is fully loaded it does the thing really fast, but not before. I think that if you did it like that it would work.
You have to setup selenium first, it's a bit long so I won't explain here, I'll just give you an example of it being used.
Selenium example:
driver.maximize_window()
driver.get(url) # goes to url and waits till it's loaded #
einput = driver.find_element_by_id("identifierId") # find the element you want through it's name #
einput.send_keys(email) # what you want to write #
einput.send_keys(Keys.RETURN) # enter #
I used this code for a script I made that logged people into google really fast in incognito. But I believe you could adapt it to your case. It's not perfect though because some pages 'never finish loading' but give it a try.

ChromeDriver sometimes does and sometimes doesn't close

I tried to implement Selenium to scrape the pages from the list. While trying to scrape the list, sometimes, the execution just stops. It seems that sometimes the execution doesn't go past driver.close() and it happens completely at random. Below is the code I use to scrape multiple pages.
I would appreciate if anyone suggested a way to ensure that the driver closes after scraping the data.
from selenium import webdriver
addresses = ['address1', 'address2',...]
results = []
for address in addresses:
driver = get_chromedriver() # returns webdriver instance
driver.get(f"https://www.example.com/{address}")
values = scrape_some_data()
driver.close()
driver.quit()
results.append(values)
# do something with the list of values
A few things I have noticed which might, or might not, be helpful in solving your issues:
Unless you really need to, it might be better to call driver = get_chromedriver() outside the loop, and run the driver.quit() after the loop is complete, that will speed up your execution significantly as your browser will not need to re-open. However if you are accessing multiple instances of the same website then you might need to depend on your method.
driver.quit() should be sufficient for your use without the need for driver.close() here.
If you want to use multiple instances definitely, it might be better to use threading. I've heard of a few cases where issues can occur if a loop is used while destroying/recreating the driver over and over.
Try changing your code as below.
You declare webdriver instance once and use driver.get to open a browser url.
Also, I suggest to append all values before you quit webdriver.
from selenium import webdriver
driver = get_chromedriver() # returns webdriver instance
addresses = ['address1', 'address2',...]
results = []
for address in addresses:
driver.get(f"https://www.example.com/{address}")
values = scrape_some_data()
results.append(values)
driver.close()
# do something with the list of values
Difference between driver.close() and driver.quit():
close() method closes the current window.
quit() method quits the driver and closes every associated window.
So, if you want one window to be closed, use close(), all windows - quit()
One more thing I suggest: add explicit waits for all your data to be loaded before webdriver is closed.
To use explicit waits import:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
And use like:
wait.until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "css_selector"))) # for a list of elements
Take this as an example: How to find and compare text with the style property using Selenium/Python?
If all above suggestions will not work, try closing webdriver in finally block.

Python switch focus back to terminal from web browser with driver selenium

I am using selenium webdriver to open a webpage and fill out the form.
anyways In the middle of the code i need to provide input data in the terminal
but the focus still stays in the webbrowser, so i need to move mouse manulally back to the terminal.
is there anyway to switch focus back to terminal from the webbrowser?
sample code :
import time
from selenium import webdriver
driver = webdriver.Chrome() # Optional argument, if not specified will search path.
driver.get('https://www.seleniumeasy.com/test/basic-first-form-demo.html')
search_box = driver.find_element_by_id('user-message')
search_box.send_keys('John Rambo')
time.sleep(5) # Let the user actually see something!
test=input('please provide a number 0-9: \n') # I'd like the focus to switch back to the terminal
driver.quit()
Through Selenium - no. It's a library that communicates exclusively to a browser, through the WebDriver protocol. It can only send request to the browser, which may (or may not) execute them.
As such, it cannot communicate with anything outside it - the OS, and its app switching routines including.
For that you need some other library, that can either issue OS requests (switch app), or simulates keyboard/mouse inputs. But these are OS dependant, e.g. different ones for Windows, Mac or Linux.

Where is the problem about selenium with python?

When I run the code it takes about 5-6 sec to execute, after than nothings happens. I get no error, but the code is simply not working. Please, help me fast I've got a project to do in a month.
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
opts = Options()
opts.set_headless()
assert opts.headless
browser = Firefox(options=opts)
browser.get("https://duckduckgo.com")
Sorry about not knowing enough about stackoverflow. I think I wrote everything to the code entry.
Your code is perfectly working for me.
opts.set_headless()
browser = Firefox(options=opts)
This operation will create an option which hide the browser, then you set this option to you recently created Firefox tab.
Once you open the duckduckgo url,
It takes a few seconds to you program to open Firefox, but... you reach the end of your program and you browser is HIDING
Check with top command and you'll see Firefox still running.
Try to execute the same code but without the opts.set_headless() line.
Good Luck !
Try not use the "headless option":
from selenium.webdriver import Firefox
browser = Firefox()
browser.get("https://duckduckgo.com")

Categories

Resources