Use case:
Sending out automated WhatsApp messages using pythonanywhere. Step by step logic below:
non-coders write on a gsheet the phone numbers to which we should
send out the messages
the gsheet data is read (using gspread in pythonanywhere)
open WhatsApp URL to send out the messages in bulk
I have a code using selenium running on my machine that opens the web whatsapp url, finds the needed elements on the website, and sends the messages to the gsheets phone numbers - find below a snippet from that part of the code that I am using on my machine:
global driver
driver.get('https://web.whatsapp.com/')
waiter.until(EC.title_is("WhatsApp"))
waitCounter = 0
while 1:
try:
waiter.until(EC.presence_of_element_located((By.XPATH, "//canvas[#aria-label='Scan me!']")))
waitCounter+=1
if waitCounter%1000 == 0:
print("Waiting for user to log in...", 'WARNING')
except:
print("Logged in to WhatsApp")
break
for entry in data:
driver.find_element_by_xpath(PHONE_NUMER_INPUT).send_keys(str(entry['PhoneNumber']))
time.sleep(2)
driver.find_element_by_xpath(PHONE_NUMER_INPUT).send_keys(Keys.ENTER)
time.sleep(2)
driver.find_element_by_class_name('p3_M1').send_keys(str(entry['Message']))
time.sleep(2)
driver.find_element_by_class_name('_4sWnG').click()
time.sleep(2)
Doubt:
To make step nr 3. working on python anywhere I would have to use a headless browser. However, to initiate whatsapp web we always need to do the QR code scan, so I am not being able to do it that way. Find below the current (useless) part of my code with the headless selenium code - (NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id='side']/div[1]/div/label/div/div[2]"}). I am quite stuck here. Any tip or idea to overcome this is more than welcome and happy to discuss any possible solutions using other libraries that you guys might find appropriate.
Thanks in advance.
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--disable-gpu")
driver = webdriver.Chrome(options=chrome_options)
def send_whatsapp_message():
global driver
driver.get('https://web.whatsapp.com/')
print("Done updating, check the spreadsheet now")
#redirect('https://web.whatsapp.com/', code=302)
for entry in data:
driver.find_element_by_xpath("//*[#id='side']/div[1]/div/label/div/div[2]").send_keys(str(entry['PhoneNumber']))
time.sleep(2)
driver.find_element_by_xpath("//*[#id='side']/div[1]/div/label/div/div[2]").send_keys(Keys.ENTER)
time.sleep(2)
driver.find_element_by_class_name('p3_M1').send_keys(str(entry['Message']))
time.sleep(2)
driver.find_element_by_class_name('_4sWnG').click()
time.sleep(2)
print("Successfully send message to {0}, name: {1}".format(str(entry['PhoneNumber']), str(entry['Name'])), 'INFO')
Related
hi i try to write a bot that automates once a day. Logged into my LinkedIn chat with a person who sends me posts and every message i wiil have post and bot need to to respond my email and write send my you cv something similar to this.
def start():
driver.get("https://www.linkedin.com")
time.sleep(3)
username = driver.find_element(By.ID, 'session_key')
username.send_keys(MyUsername)
time.sleep(0.7)
password = driver.find_element(By.ID, "session_password")
password.send_keys(MyPassword)
time.sleep(0.3)
button_sign = driver.find_element(By.XPATH, '//*[#type="submit"]')
button_sign.click()
time.sleep(3)
# scroll_down_random()
button_messaging = driver.find_element(By.XPATH, '//*[#id="global-nav"]/div/nav/ul/li[4]/a')
button_messaging.click()
time.sleep(2)
search_chat = driver.find_element(By.XPATH, '//*[#id="search-conversations"]')
search_chat.send_keys(name_of_chat)
search_chat.send_keys(Keys.ENTER)
time.sleep(2)
submit_application = driver.find_element(By.ID,'//*[#id="ember65"]')
submit_application.click()
but I am stuck on two things one After I search I can't select the first chat and I Run in a loop between messages in posts.
after
submit_application = driver.find_element(By.ID,'//*[#id="ember65"]')
submit_application.click()
need to click the first person after I search. and how I can sty always connected if I upload it to the cloud without having to connect every time
I think the ID you are searching for is incomplete, I get an ID like
"overlay-conversation-card-ember133"
This might be different for different devices so I believe you should use XPATH here rather than the ID.
Hope this helps. 👍🏻
EDIT:
It seems selenium .click() does not always register, use .submit() although this doesn't work for all browsers incase of that use .send_keys(Keys.ENTER)
I have a requirement of automating the mail sending process with the data from DHL. Currently what we are doing is:
We have a DHL account, someone has to manually login to the account , download the CSV dump which contains the order tracking details then upload it to the server, port the data from those and process it.
So I thought of automating the whole process so that it requires minimal manual intervention.
1) Is there anyway we can automate the download process from DHL?
Note: I'm using Python
I'd start by looking for something more convenient to access with code...
searching google for "dhl order tracking api" gives:
https://developer.dhl/api-catalog
as its first result, which looks useful and exposes quite a bit of functionality.
you then need to figure out how to make a "RESTful" request, which has answers here like Making a request to a RESTful API using python, and there are lots of tutorials on the internet if you search for things like "python tutorial rest client" which points to articles like this
You can use Selenium for Python. Selenium is a package that automates a browser session. you can simulate mouse clicks and other actions using Selenium.
To Install:
pip install selenium
You will also have to install the webdriver for the browser you prefer to use.
https://www.seleniumhq.org/projects/webdriver/
Make sure that the browser version that you are using is up to date.
Selenium Documentation: https://selenium-python.readthedocs.io/
Since you are dealing with passwords and sensitive data, I am not including the code.
Login and Download
You can automate download process using selenium. Below is the sample code to automate any login process and download items from a webpage. As the requirements are not specific I'm taking general use-case and explaining how to automate the login and download process using python.
# Libraries - selenium for scraping and time for delay
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time
chromeOptions = webdriver.ChromeOptions()
prefs = {"download.default_directory" : "Path to the directory to store downloaded files"}
chromeOptions.add_experimental_option("prefs",prefs)
chromedriver = r"Path to the directory where chrome driver is stored"
browser = webdriver.Chrome(executable_path=chromedriver, chrome_options=chromeOptions)
# To maximize the browser window
browser.maximize_window()
# web link for login page
browser.get('login page link')
time.sleep(3) # wait for the page to load
# Enter your user name and password here.
username = "YOUR USER NAME"
password = "YOUR PASSWORD"
# username send
# you can find xpath to the element in developer option of the chrome
# referance answer "[https://stackoverflow.com/questions/3030487/is-there-a-way-to-get-the-xpath-in-google-chrome][1]"
a = browser.find_element_by_xpath("xpath to username text box") # find the xpath for username text box and replace inside the quotes
a.send_keys(username) # pass your username
# password send
b = browser.find_element_by_xpath("xpath to password text box") # find the xpath for password text box and replace inside the quotes
b.send_keys(password) # pass your password
# submit button clicked
browser.find_element_by_xpath("xpath to submit button").click() # find the xpath for submit or login button and replace inside the quotes
time.sleep(2) # wait for login to complete
print('Login Successful') # if there is no error you will see "Login Successful" message
# Navigate to the menu or any section using it's xpath and you can click using click() function
browser.find_element_by_xpath("x-path of the section/menu").click()
time.sleep(1)
# download file
browser.find_element_by_xpath("xpath of the download file button").click()
time.sleep(1)
# close browser window after successful completion of the process.
browser.close()
This way you can automate the login and the downloading process.
Mail automation
For Mail automation use smtplib module, explore this documentation "https://docs.python.org/3/library/smtplib.html"
Process automation (Scheduling)
To automate the whole process on an everyday basis create a cron job for both tasks. Please refer python-crontab module. Documentation: https://pypi.org/project/python-crontab/enter link description here
By using selenium, smtplib, and python-crontab you can automate your complete process with minimal or no manual intervention.
Has anyone faced the problem that automation routine for instagram written in python with selenium chromedriver has become difficult to run recently because instagram keeps asking for the code it sends in sms or email?
When you do your normal browser login it asks for the code in sms only once. But when you do it with selenium it asks for it every time.
Here is the code
options = webdriver.ChromeOptions()
#options.add_argument('headless')
#options.add_argument('--headless')
options.add_argument('--disable-logging')
options.add_argument('--log-level=3')
driver = webdriver.Chrome(chrome_options=options)
#driver = webdriver.Chrome()
print('Driver started successfully!')
driver.get("https://instagram.com/")
time.sleep(6)
pg=driver.find_element_by_tag_name("html")
lng=pg.get_attribute("lang")
#print(lng)
if lng=='en':
global lin
global foll
global foll_tx
global subscr_tx
lin="Log in"
foll="followers"
foll_tx="Follow"
subscr_tx="following"
get_enter_bt
= driver.find_elements_by_link_text(self.lin)
lin_found=False
while not lin_found:
if len(get_enter_bt)==0:
print('Login not found ((( Refreshing...')
driver.refresh()
time.sleep(6)
get_enter_bt = driver.find_elements_by_link_text(self.lin)
else:
lin_found=True
print('Login button found!')
time.sleep(3)
get_enter_bt[0].click()
time.sleep(3)
#login
login = driver.find_element_by_name("username")
login.send_keys(username)
login = driver.find_element_by_name("password")
login.send_keys(password)
login.send_keys(Keys.RETURN)
time.sleep(9)
get_close_mobapp=driver.find_elements_by_css_selector("button._dbnr9")
if len(get_close_mobapp)!=0:
get_close_mobapp[0].click()
notif_switch=driver.find_elements_by_css_selector("button.aOOlW.HoLwm")
print('notif butt %s' % len(notif_switch))
if len(notif_switch)>0:
notif_switch[0].click()
print(1)
#detect suspicious login
susp_login_msg=driver.find_element_by_xpath("//*[#id=\"react-root\"]/section/div/div/div[1]/div/p")#<p class="O4QwN">Подозрительная попытка входа</p>
print('susm login msg %s' % (susp_login_msg!=None))
if susp_login_msg:
if susp_login_msg.text=='Подозрительная попытка входа':
try:
mobile_button = driver.find_element_by_xpath("//*[#id=\"react-root\"]/section/div/div/div[3]/form/div/div[2]/label")
mobile_button.click()
except:
mobile_button = driver.find_element_by_xpath("//*[#id=\"react-root\"]/section/div/div/div[3]/form/div/div[1]/label")
mobile_button.click()
snd_code_btn=driver.find_element_by_xpath("//*[#id=\"react-root\"]/section/div/div/div[3]/form/span/button")
snd_code_btn.click()
print('Instagram detected an unusual login attempt')
print('A security code was sent to your mobile '+mobile_button.text)
security_code = input('Type the security code here: ')
#security_code_field = driver.find_element_by_xpath(("//input[#id='security_code']"))
security_code_field.send_keys(security_code)
‐----‐‐‐----
This code works fine, but how to stop instagram from asking for the code in sms every time? Does it detect that I run selenium and runs a kind of antibot activity?
I was running the script on schedule to perform series of likes for my subscribers for example which is time consuming you know and automation was my remedy)))
I am trying to get video url from links on this page. Video link could be seen on https://in.news.yahoo.com/video/jaguar-fighter-aircraft-crashes-near-084300217.html . (Open in Chrome)
For that I wrote chrome web driver related code as below :
from bs4 import BeautifulSoup
from selenium import webdriver
from pyvirtualdisplay import Display
chromedriver = '/usr/local/bin/chromedriver'
os.environ['webdriver.chrome.driver'] = chromedriver
display = Display(visible=0, size=(800,600))
display.start()
driver = webdriver.Chrome(chromedriver)
driver.get('https://in.news.yahoo.com/video/jaguar-fighter-aircraft-crashes-near-084300217.html')
try:
element = WebDriverWait(driver, 20).until(lambda driver: driver.find_elements_by_class_name('yvp-main'))
self.yahoo_video_trend = []
for s in driver.find_elements_by_class_name('yvp-main'):
print "Processing link - ", item['link']
trend = item
print item['description']
trend['video_link'] = s.find_element_by_tag_name('video').get_attribute('src')
print
print s.find_element_by_tag_name('video').get_attribute('src')
self.yahoo_video_trend.append(trend)
except:
return
This works fine on my local system but when I run on my azure server it does not give any result at s.find_element_by_tag_name('video').get_attribute('src')
I have installed chrome on my azureserver.
Update :
Please see, requests and Beautifulsoup I already tried, but as yahoo loads html content dynamically from json, I could not get it using them.
And yeah azure server is simple linux system with command line access. Not any application.
I tried to reproduce your issue using you code. However, I found there was no tag named video in that page('https://in.news.yahoo.com/video/jaguar-fighter-aircraft-crashes-near-084300217.html')(using IE and Chrome to test).
I used the developer Tool to check the HTML code, like this picture:
It seems that this page used the flash player to play video,not HTML5 video control.
For this reason, I suggest that you can check your code whether used the rightly tag name.
Any concerns, please feel free to let me know.
We tried to reproduce the error on our side. I was not able to get chrome driver to work, but I did try the firefox driver and it worked fine. It was able to load the page and get the link via the URL.
Can you change your code to print the exception and send it to us, to see where the script is failing?
Change your code:
except:
return
try
do
except Exception,e: print str(e)
Send us the exception, so we can take a look.
I had a test script that was working, and it stopped working 2 weeks ago. The test is to login to Hotmail, click on new mail, fill in email address, subject, and text in the body, and send the email. Currently I can't enter text into the body of the mail. I tried with ID, CSS, and Xpath. I also tried using the select frame but to no avail. I have attached the Python code and would appreciate help...
The aim of the script is to capture the traffic via Wireshark specifically for Hotmail send mail, with the current Hotmail protocol.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
import unittest, time, re
class HotmailloginpythonWebdriver(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "https://login.live.com/"
self.verificationErrors = []
def test_hotmailloginpython_webdriver(self):
driver = self.driver
driver.get(self.base_url + "/login.srf?wa=wsignin1.0&rpsnv=11&ct=1321965448&rver=6.1.6206.0&wp=MBI&wreply=http:%2F%2Fmail.live.com%2Fdefault.aspx&lc=1033&id=64855&mkt=en-us&cbcxt=mai&snsc=1")
driver.find_element_by_id("i0116").clear()
driver.find_element_by_id("i0116").send_keys("address#hotmail.com")
driver.find_element_by_id("i0118").clear()
driver.find_element_by_id("i0118").send_keys("password")
driver.find_element_by_id("idSIButton9").click()
driver.find_element_by_id("h_inboxCount").click()
driver.find_element_by_id("NewMessage").click()
driver.find_element_by_id("AutoCompleteTo$InputBox").clear()
driver.find_element_by_id("AutoCompleteTo$InputBox").send_keys("address#hotmail.com")
driver.find_element_by_id("fSubject").clear()
driver.find_element_by_id("fSubject").send_keys("testsubject")
driver.find_element_by_css_selector("body..RichText").clear()
driver.find_element_by_css_selector("body..RichText").send_keys("gggggggggggg")
driver.find_element_by_id("SendMessage").click()
driver.find_element_by_id("c_signout").click()
def is_element_present(self, how, what):
try:
self.driver.find_element(by=how, value=what)
except NoSuchElementException, e:
return False
return True
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()
It is very much possible that Microsoft is blocking the automated service(like Selenium) which tries to access the Hotmail or live.com page. According to the Terms of Service( TOS) at Microsoft you can use automates service to login etc. Here is what TOS (Point Number#2) says:
You must not use the service to harm others or the service. For example, you must not use the service to harm, threaten, or harass another person, organization, or Microsoft. You must not: damage, disable, overburden, or impair the service (or any network connected to the service); resell or redistribute the service or any part of it; use any unauthorized means to modify, reroute, or gain access to the service or attempt to carry out these activities; or use any automated process or service (such as a bot, a spider, periodic caching of information stored by Microsoft, or metasearching) to access or use the service.
Full text is available here: http://windows.microsoft.com/en-US/windows-live/microsoft-service-agreement.
I had similar experience myself once testing something with Twitter UI. Maybe you can look for a third party service that can help you login via SMTP or POP3 etc. to measure network traffic instead of using frontend UI.
I suspect this has something to do with cookies. Maybe you removed the cookies from your browser?
Try debugging the script until the password typing or until
driver.find_element_by_id("idSIButton9").click()
to see if it works fine. Perhaps MS changed their UI so it would be nice to debug your app from that point to see if you have to modify your script to update object id's.
Regards.
Try to use Xpath not id. In xpath you can use following-sibling.It will work.
System.setProperty("webdriver.chrome.driver",
"F:\\batch230\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
//open hotmail site
driver.get("http://www.hotmail.com/");
Thread.sleep(5000);
driver.manage().window().maximize();
Thread.sleep(5000);
//do login
driver.switchTo().activeElement().sendKeys("mail id");
driver.findElement(By.id("idSIButton9")).click();
Thread.sleep(5000);
driver.switchTo().activeElement().sendKeys("password");
driver.findElement(By.id("idSIButton9")).click();
Thread.sleep(5000);
//compose mail
driver.findElement(By.xpath("//*[contains(#title,'new message')]")).click();
Thread.sleep(5000);
driver.findElement(By.xpath("(//*[#role='textbox'])[1]"))
.sendKeys("er.anil900#gmail.com",Keys.TAB,"selenium"
,Keys.TAB,"Hi",Keys.ENTER,"How are you");
Thread.sleep(5000);
//send mail
driver.findElement(By.xpath("(//*[#title='Send'])[1]")).click();
Thread.sleep(10000);
//do logout
WebElement e = driver.findElement(By.xpath("(//*[#role='menuitem'])[11]"));
Actions a = new Actions(driver);
a.click(e).build().perform();
Thread.sleep(5000);
WebElement e1 = driver.findElement(By.xpath("//*[text()='Sign out']"));
a.click(e1).build().perform();
Thread.sleep(10000);
driver.close();