Goal: Record all these specific actions: onKeyboardEvent and onMouseEvent performed by one user on a particular website. This recording includes logging, for example, the button name, class name of that button and so on of a website only when the user clicked on that respective button. I want to create this logger with python.
Example of the expected result:
This is an illustrative example to understand what I need:
Event name: Mouse Left click
Button Name: Login
Class name of the button: login-button
...
Event name: Mouse Left click
Button name: Next
Class name of the button: next-button
Experience in python: Beginner
Python interpreter: 3.7
Question: How can I record or log the button name or class name of that button when a User clicked on it on a particular website that it opened?.
I checked Selenium and Python in order to achieve my goal. What I understood so far, selenium hat listener class and Selenium is which opens the browser and starts the event listening under that particular browser. However, in my case the user is who opens a particular website on Chrome, Firefox or Internet explorer and I need a program in python to record what the user is doing in that website.
The code attached below did not record or log anything. Besides, it did not connect to the respective browser that the user open but it listens only the session started by Selenium. Could anyone tell me if I am using the right approach or if I should use another to reach my goal?.
Thank you very much for your help and please forgive me if I used incorrectly any concept.
Python code:
import time
from selenium import webdriver
from selenium.webdriver.support.events import EventFiringWebDriver, AbstractEventListener
class MyListener(AbstractEventListener):
def before_click(self, element, driver):
driver.get_attribute("tag")
print ("Event : before element click()")
def after_click(self, element, driver):
print("clicked on %s" %element)
driver = webdriver.Chrome('Webdrivers\Chrome_80\\chromedriver.exe')
driver = EventFiringWebDriver(driver, MyListener())
driver.get("https://google.com")
elem = driver.find_element_by_name("q")
time.sleep(20)
driver.close()
Selenium is a python framework for testing purposes, you could see more information if you are interested in https://selenium-python.readthedocs.io/
What you need (maybe) is like a pyHook approach: https://pypi.org/project/pyHook/ It uses the mouse and keyboard events.
There is another module named pyscreenshot, it could help you for monitoring what is being clicked https://pypi.org/project/pyscreenshot/
Regards!
Related
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"]
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.
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.
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']")
Sript click a link like <a href="/loginform.do">
and it's open a new pop up window with login/password fields (OK/Cancel buttons).
And webdriver for some reason determine this pop up as alert not window...
if try
for handle in browser.window_handles:
print(handle)
it's return exception: UnexpectedAlertPresentException: Alert Text: Message: Modal dialog present
if try
alert=browser.switch_to_alert()
alert.send_keys('userlogin')
it's working (userlogin inserted into first field).
And then if trying to move cursor to next field (password) by TAB key
alert.send_keys(Keys.TAB)
it's replace text at the first field to bullet symbol instead of tabbing to next field...
Not only TAB, even ENTER working in the same way
alert.send_keys(Keys.ENTER)
it's paste the same bullet symbol instead of sending request to a server
And
alert.accept()
doing nothing (no sending request to a server)
What can be done here?
It's an alert, so find_element_by_... methods are not applicable.
TAB by send_keys is not working (no tabbing).
Is the only solution to click by coordinates (using pyautogui module as an option)?
Or is it possible to do more with webdriver?
BTW using IE (IEDriverServer)
And some searching for close questions
31152912 close question, but answer is about find_element_by_name (no such attribute for 'Alert' object)
31152912, 29516740, 27322871 answers about using 'http://username:password#', unfortunatelly it's not working
So an example with login form of .htaccess password protection (advancedhtml.co.uk/password.html)
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
browser=webdriver.Ie('c:\\...\\IEDriverServer.exe')
page='http://www.advancedhtml.co.uk/password/'
browser.get(page)
alert=browser.switch_to_alert()
#alert=browser.switch_to.alert() # this should work, but it doesn't: TypeError: 'Alert' object is not callable
alert.send_keys('user')
alert.send_keys(Keys.TAB) # no tabbing, bullet symbol instead...
#alert.send_keys('password')
So this kind of login page is HTTP Basic Access Authentication. And looks the best way to handle such authentication is to sent post request (Requests package)
Need to pass browser session from Selenium to Requests
(29563335)
The code may look like this:
from selenium import webdriver
import requests
startURL='http://some_url'
browser=webdriver.Ie('c:\\path\\IEDriverServer.exe')
browser.get(startURL)
# an example of finding login link and get the url
loginLink=browser.find_element_by_xpath("//*[contains(text(), 'Log In')]")
loginURL=loginLink.get_attribute('href')
# load cookies from Selenium to Requests (so we could authenticate in current session)
cookies=browser.get_cookies()
s=requests.Session()
for cookie in cookies:
s.cookies.set(cookie['name'], cookie['value'])
# and send the post request
auth=('login', 'password')
r=s.post(url=loginURL, auth=auth)
browser.refresh() # refresh page to see the result
And for .htaccess password protection (example: advancedhtml.co.uk/password.html) it may be handled with additional click at coordinates
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import pyautogui
page='http://www.advancedhtml.co.uk/password/'
browser=webdriver.Ie('c:\\path\\IEDriverServer.exe')
browser.get(page)
alert=browser.switch_to_alert()
alert.send_keys('demo')
#alert.send_keys(Keys.TAB) # tabbing is not working
pyautogui.moveTo(620, 550) # so move mouse cursor to second field
pyautogui.click()
pyautogui.typewrite('password')
alert.accept()
#Litvin, Your approach is correct but you needed to know one more thing in this.
When you do:- obj = driver.switch_to.alert
You can send the keys in one more way as below, which I understood after walking through the Python selenium source code (here).
obj.send_keys(keysToSend="username\ue004password")
Here \ue004 is the value for TAB.