Python and Selenium with Whatsapp Web - python

I'm trying to make a bot that allows me to send any message for a lot of ppl.
through web.whatsapp.com i can do that, but my issue here with the class name :
this is Type a message's class, you can see it clearly : _3FRCZ copyable-text selectable-text, so my issue here that i cannot select it, idk why, i tried to select deffrent classes but still same issue.
here is my code:
from selenium import webdriver
driver = webdriver.Firefox()
content = "Hi There"
phone = "+96657831111"
driver = webdriver.Firefox()
driver.get(f"https://web.whatsapp.com/send?phone={phone}&text&source&data&app_absent")
input("Press Enter After Scanning..")
send = driver.find_element_by_class_name("_3FRCZ copyable-text selectable-text")
send.send_keys("Test")
Notes:
for me i dont have to set geckdriver.
my python verion is 3.8
EDIT: I used xpath to do it //div[#class='_3FRCZ copyable-text selectable-text'] and it worked, but with search box not messages box.
i realized that search box and message box has same class.

I fixed it by using CSS Selector, You cannot use xpath or find element by class name, bc there is many elements using the same class name, so here is the best choice:
send = driver.find_element_by_css_selector("div[data-tab='6']")
send.send_keys(msg,Keys.ENTER)

Related

Type in login and password

Just began typing following code:
from selenium import webdriver
browser = webdriver.Chrome('C:\\webdrivers\\chromedriver.exe')
browser.get('https://auth.sketchengine.eu/#login')
button = browser.find_element_by_xpath('//*[#id="r_0"]')[0]
button.send_keys('Lobster')
button = browser.find_element_by_xpath('//*[#id="r_1"]')[0]
button.send_keys('123123123')
to make Python go to Sketch Engine and type in a login and password. I used inspect in Chrome and then copied the Xpaths, but Python is not doing the typing and says 'unable to locate element' for both the Xpaths. What do I change?
I am not a Python person but try this for xpath. I think the issue is that id "r_0" is on the page a few times. If you look at the xpath with "//input" you will only return one.
//input[#id="r_0"]
//input[#id="r_1"]

Selenium can't find 99% of elements, why?

I'm using Selenium with Python and Firefox on Windows 7.
Running through my script, at some point Selenium can't find any elements beside and after I navigated to a certain part of a website.
The website belongs to an E-Mail provider called freemail (https://web.de/). I have set up a test account to complete a training project from chapter 11 of the book "Automate the Boring Stuff with Python".
Python, Selenium and Firefox are all up to date. And before this certain part of the website everything was working fine (including finding tags, class names, id's etc.).
I tried like 10 different ways to click one of the ways to navigate to the inbox of the E-Mail provider but had no luck in making it work.
Here is the HTMLcode with the highlighted element I want Selenium to click.
Here another image of the Website itself with the button highlighted in the upper left corner.
And this is the code for my script:
## This program navigates through the website of an
## e-mail provider and sends a mail automatically.
# Import necessary modules
from selenium import webdriver
# Mail account info
mailLink = 'https://web.de/'
mailAddress = 'testing2772#web.de' # This is just a test account
mailPw = 'ewaa11ewaa11'
# Recipient % content of the e-mail
recipient = 'pradicradr#matra.top'
mailContent = 'Test this awesome string.'
# Set up browser
browser = webdriver.Firefox()
browser.get(mailLink)
# Log into account
browser.find_element_by_class_name('icon-freemail').click()
browser.find_element_by_id('freemailLoginUsername').send_keys(mailAddress)
pwElem = browser.find_element_by_id('freemailLoginPassword')
pwElem.send_keys(mailPw)
pwElem.submit()
# Close notification overlay if it pops up
try:
browser.find_element_by_class_name('layerCloser').click()
except:
pass
## At this point Selenium can't Find 99% of elements including the one I need
## Testing if Selenium finds basic elements
testElem1 = browser.find_element_by_tag_name('html') # works
testElem2 = browser.find_element_by_tag_name('body') # works
testElem3 = browser.find_element_by_tag_name('div') # works
## Click link to inbox (all of these variants won't work somehow)
linkToInbox = browser.find_element_by_class_name('nx-track-sec-click-communication-newmail') # try by class_name
linkToInbox = browser.find_element_by_xpath("/html/body/div[3]/div/div[3]/div[1]/ul/li[3]/a") # try by XPath
linkToInbox = browser.find_element_by_link_text('E-Mail schreiben') # try by link_text
linkToInbox = browser.find_element_by_css_selector('a.nx-track-sec-click-communication-newmail') # try by CSS selector
linkToInbox = browser.find_element_by_css_selector('a.newmail') # try by CSS selector
linkToInbox = browser.find_element_by_css_selector('a.nx-track nx-track-sec-click-communication-newmail newmail') # another try by CSS selector
linkToInbox = browser.find_element_by_css_selector('a[title="E-Mail schreiben"]') # another try by CSS selector
## TODO: Click link to write a new mail
## TODO: Fill in recipient and mail content
## TODO: Send mail and close program
I guess it has something to do with an iframe? But I'm a beginner and I don't know how to handle this :/
Thanks in advance!
EDIT:
I solved the problem by finding another button that linked to the inbox with
browser.find_element_by_xpath("/html/body/atlas-app/atl-navbar/atl-actions-menu/div[1]/div[1]/atl-menu-item[2]/pos-icon-item/span/span").click(). This button is not within an iframe, so no problem here.
However, it is still strange that I can't enter any iframes. Here is another image to make it more clear. Does anybody know how to switch to that iframe?
browser.switch_to.default_content() and then browser.switch_to.frame('home') doesn't do the trick...
SECOND EDIT:
KunduK's answer did it.
The problem was, that the script needs to wait for the iframe to become available and then for the button to become available after that. See his post further down for the exact approach. Thanks everyone!
To click on the E-Mail schreiben link you need to switched to iframe first and then click on link.Use WebDriverWait and frame_to_be_available_and_switch_to_it and then use element_to_be_clickable
WebDriverWait(browser,20).until(EC.frame_to_be_available_and_switch_to_it((By.NAME,'home')))
WebDriverWait(browser,10).until(EC.element_to_be_clickable((By.XPATH,'//div[#id="navigation"]//ul//li[#class="item"]//a[#title="E-Mail schreiben"]'))).click()
You need to use following imports to execute above code.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
I guess it has something to do with an iframe?
Since the elements you are trying to find are in an iframe, you must first switch to the iframe before finding the elements. Your iframe has a name=home attribute, so you should be able to add:
driver.switch_to.frame('home')
... then find the elements.
Once you are done interacting with the iframe and want to switch back to the top level content, use:
driver.switch_to.default_content()
Option 1
linkToInbox = browser.find_element_by_css_selector('a.nx-track.nx-track-sec-click-communication-newmail.newmail') # try by CSS selector
Option 2
use the title property of the anchor link
linkToInbox = browser.find_element_by_css_selector('a[title="E-Mail schreiben"]')
option 3
re-read the docs: https://selenium-python.readthedocs.io/locating-elements.html

sending message on youtube live chat with selenium using python

I was trying to make a script using python and selenium, to spam a massage on youtube live stream for a giveaway, i was able to do most of the task successfully until on line (33), where i was trying to locate the youtube live chat box by(.find_element_by_...?) it was showing all kind of error like,AttributeError: 'WebDriver' object has no attribute or failed to locate element_by_...? 'find_element_by_text,xpath,id.class, etc
from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys
email = ''
password = ''
gmail_link = 'http:\\www.gmail.com'
driver = webdriver.Firefox('D:\Projects\python projects')
driver.get(gmail_link)
time.sleep(4)
#email send_keys
driver.find_element_by_id('identifierId').send_keys(email)
#Email_next button xpath.click
driver.find_element_by_xpath('/html/body/div[1]/div[1]/div[2]/div[2] /div/div/div[2]/div/div[2]/div/div[1]/div/content/span').click()
time.sleep(4)
#password xpath
driver.find_element_by_xpath('/html/body/div[1]/div[1]/div[2]/div[2]/div/div/div[2]/div/div[1]/div/form/content/section/div/content/div[1]/div[1]/div/div/div/div/div[1]/div/div[1]/input').send_keys(password)
time.sleep(2)
#password button xpath.click
driver.find_element_by_xpath('/html/body/div[1]/div[1]/div[2]/div[2] /div/div/div[2]/div/div[2]/div/div[1]/div/content/span').click()
time.sleep(5)
#A random youtube live link
driver.get('https://www.youtube.com/watch?v=VTqTnbe6b1g')
time.sleep(5)
# youtube live chat box
driver.find_element_by_text('Say somthing...').send_keys('#PUBGMOBILE')
time.sleep(3)
# youtube live chat box button
driver.find_element_by_id('//*[#id="button"]').click()
Basically that div is associated with 'input' event so you have to dispatch the 'input' event once you enter the value in the div.
Here is the code which I was able to execute successfully form console (FYI this is JS you can use the same logic in your test and language).
ele = document.querySelector('div#input')
ele.textContent = 'test this sample data'
ele.dispatchEvent(new Event('input',{'bubles':true, 'cancelable':true}))
Line 1 is equals findelemnt by css
Line 2 enter the input
Line 3 fireevent 'input' on the element
WebElement chatEle = driver.find_element(By.CSS_SELECTOR('div#input')
chatEle.sendKeys "sample data"
driver.fireEvent(chatEle,"input")
should do the magic, couldn't test the code above as I don't have eclipse java environment on my machine. Test it and let us know.
Refer to Selenium FireEvent document for more information on the fireevent implementation.
Instead of looking for the element by its text you could use its xpath like you did before. I just looked at the chatbox for a YT livestream and the xpath seems to be called //*[#id="input"]
Edit:
Also, there could be something tricky where you need to click the element first before you can enter text.
don't use the [#id="input"] it was also given for another element too. You will not get the element. Use class name {yt-live-chat-text-input-field-renderer style-scope} this is unique you will get the element by this class name.
Your sending text to a wrong element
driver.find_element_by_text('Say somthing...').send_keys('#PUBGMOBILE')
This is lable not a textbox.

Python selenium unable to find element neither by class name nor xpath

I'm newbie in Selenium. I start to learn Selenium via book. And I struggle with unclear behavior of Selenium. For educational purposes I use this site:
http://magento-demo.lexiconn.com/ - I'm trying to find search button by its class name, (which is: class='button search button') or by it xpath
search_button = self.driver.find_element_by_xpath('/html/body/div/div[2]/header/div/div[4]/form/div[1]/button')
or
search_button = self.driver.find_element_by_class_name('button')
but each time selenium unable to find it. Please help me to understand reason of such behavior. Thank you
I used Selenium IDE and it shows me XPATH: //button[#type='submit']
when I tried to find element by xpath,I have got the same error and it is strange. Please advise.
My code is:
import unittest
from selenium import webdriver
class HomePageTest(unittest.TestCase):
#classmethod
def setUpClass(cls):
#create new Firefox session
cls.driver = webdriver.Firefox()
cls.driver.implicitly_wait(30)
cls.driver.maximize_window()
#navvigate to application home page
cls.driver.get('http://magento-demo.lexiconn.com/')
def test_search__text_field_max_length(self):
#get the search text box
search_field=self.driver.find_element_by_id("search")
#check maxlenght attribute st to 128
self.assertEqual("128",search_field.get_attribute("maxlength"))
def test_search_button_enabled(self):
# get Search button
search_button = self.driver.find_element_by_class_name('button')
# check Search button is enabled
self.assertTrue(search_button.is_enabled())
#classmethod
def tearDown(self):
#close the browser window
self.driver.quit()
if __name__=='__main__':
unittest.main(verbosity=2)
Try this :
search_button = self.driver.find_element_by_xpath('//button[#class="button search-button"]')
Try downloading the selenium IDE plugin, install and start recording. Click on the button you want and view how its target is recorded in the IDE. Programmatically, selenium will accept the same xpaths and other selectors as the IDE. After it's been recorded in the IDE, there is a pull down on the target field that lets you see all the different ways you can select that element, ie xpath vs. by class etc.
http://www.seleniumhq.org/projects/ide/
you might try:
css=button.button.search-button
//button[#type='submit']
//form[#id='search_mini_form']/div/button
I think the issue is that your locator isn't specific enough. There is more than one button on the page and more than one element with class=button on the page. This CSS selector is working for me.
self.driver.find_element_by_css_selector("button[title='Search']")
Try this way using xpath locator
Explanation: Use title attribute of <button> tag.
self.driver.find_element_by_xpath("//button[#title='Search']")
OR
Explanation: Use title and type attribute of <button> tag.
self.driver.find_element_by_xpath("//button[#title='Search'][#type='submit']")

Selenium webdriver - element can be found but is not visible?

I am working on a personal project to make a python script to log in to a site and do few tasks for me, and I've decided to use the Selenium web driver. Currently I am stuck on the log in part.
driver = webdriver.Chrome()
driver.get("https://pucatrade.com")
puca_username = "example#username"
user_fieldID = "login"
user_fieldelement = driver.find_element_by_id(user_fieldID)
user_fieldelement.send_keys(puca_username)
However, it gives me selenium.common.exceptions.ElementNotVisibleException: Message: element not visible on the send_keys call. I know that find_element_by_id finds the element because I've tested with print user_fieldelement.get_attribute('id'), and it prints login. So if find_element_by_id works can find the element, how come send_keys can't?
There are multiple inputs having id="login". You are interested in the one located in the login form on the very right which is inside the div with id="home-login":
form = driver.find_element_by_id("home-login")
# login
user_fieldelement = form.find_element_by_id(user_fieldID)
user_fieldelement.send_keys(puca_username)
# password
passwd_fieldelement = form.find_element_by_id(passwd_fieldID)
user_fieldelement.send_keys(puca_password)
I'm still not sure why some websites has many fields with same name and id... but as I was only interested on the visible ones, I did this little function to get the right field.
def find_visible_element_by_name(name):
# Websites, for some reason, has many fields with the sama name and ID! This gets the first one that is visible.
# http://stackoverflow.com/questions/32462116/selenium-webdriver-element-can-be-found-but-is-not-visible
fields = self.sel.find_elements_by_name(name)
for f in fields:
if f.is_displayed():
return f
return None
self.sel is the Selenium driver object.

Categories