Selenium ChromeDriver not interacting with Chrome Print Dialog - python

I'm new to web scraping, and I have recently tried to create a web scraper that prints out my online Calendar. I have been able to work out how to get to the print prompt with Selenium, but I cannot interact with the actual print window when I try to programmatically click the Print & Cancel buttons.
The print prompt does take a second or two to load, and I already have the print window selected as the current window by Webdriver (accomplished using the below code)
whandles = driver.window_handles
print("About to switch window handle to print window, should be: " + whandles[1])
driver.switch_to.window(whandles[1])
But when I try:
printBtnFinal = WebDriverWait(driver,100).until(EC.element_to_be_clickable((By.CLASS_NAME,'action-button'))).click()
nothing happens, the program times out (I'm assuming because the element never was found).
How can I successfully interact with the Chrome Print Window?
Any help is appreciated.

Problem Explanation
You do not need to switch to Print Modal pop up. Because it is not a new windows/tab neither it is in frame. So switching is the culprit here.
Solution
I would recommend you to use WebDriverWait which is an explicit waits in Selenium library.
to click on Print which is in top right corner use this xpath and code :
wait = WebDriverWait(driver, 20)
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Print']/ancestor::button"))).click()
Once this is clicked you'd see a new pop up with Print and Cancel button.
to click on Print in the pop up, the below code should help you past the issue that you've been facing.
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Print']/ancestor::button[contains(#class,'action')]"))).click()
Imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Update 1 :
driver = webdriver.Chrome(driver_path)
driver.maximize_window()
driver.implicitly_wait(50)
driver.get("https://outlook.live.com/owa/?state=1&redirectTo=aHR0cHM6Ly9vdXRsb29rLmxpdmUuY29tL2NhbGVuZGFyLw&nlp=1")
wait = WebDriverWait(driver, 20)
#User Must place Email:
USER_EMAIL = 'user name should be given here'
USER_PASSWORD = 'password should be here'
emailField = WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[type='email']")))
emailField.clear()
emailField.send_keys(USER_EMAIL)
submitEmail= WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[type='submit']"))).click()
#Dismiss "It looks like this email is used with more than one account from Microsoft" screen
#personalAccount = WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"div[id='msaTile']"))).click()
#Enter Password
passwordField = WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[type='password']")))
passwordField.clear()
passwordField.send_keys(USER_PASSWORD)
submitPassword = WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[type='submit']"))).click()
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.table-row"))).click()
time.sleep(30)
wait.until(EC.element_to_be_clickable((By.ID, "idSubmit_SAOTCC_Continue"))).click()
#Dismiss StaySignedIn
staySignedIn = WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[id='idBtn_Back']"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a[title='Calendar']"))).click()
printBtn1 = WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Print']/ancestor::button"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Print']/ancestor::button[contains(#role,'menuitem')=false]"))).click()

Related

It closes when click runs. (selenium)

It closes when click runs.
and ı wanna just click button.
ı wanna do click that xpath. but its doesnt work. it close without doesnt click. so it open edge. waiting waiting and close. it didint run my click command. and there a error. its "webdriver object has no attribute find_element_by_xpath"
from selenium import webdriver
import time
driver = webdriver.Edge()
driver.get("https://www.instagram.com/")
time.sleep(7)
log_in = driver.find_element_by_xpath("//*[#id='mount_0_0_+h']/div/div/div/div[1]/div/div/div/div[1]/section/main/article/div[2]/div[2]/div/p/a/span")
log_in.click()
driver.close()
I think this is what you want:
# Needed libs
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
#Open the browser
driver = webdriver.Edge()
driver.get("https://www.instagram.com/")
# Wait and click for allow cookies button
allow_cookies_button = date = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, f"//button[text()='Only allow essential cookies']")))
allow_cookies_button.click()
# Wait and click for Sign in button
signup_button = date = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, f"//span[text()='Sign up']")))
signup_button.click()
# This time.sleep is to allow you to see what happened, you can delete it
time.sleep(5)
# Close the browser
driver.close()
Why your code did not work? Because as you console told you "find_element_by_xpath" is not a valid method/attribute for driver.
Advises for automation/Scraping:
Wait for the element you will use (it does not matter if you want to write, click or whatever, make sure the element is on the screen)
Try to use xpaths (Or any selector) that are understandable, you will reuse them in the future. What do you understand better, //span[text()='Sign up'] or //*[#id='mount_0_0_+h']/div/div/div/div[1]/div/div/div/div[1]/section/main/article/div[2]/div[2]/div/p/a/span? Good selectors will save a lot of time in the future

Python Selenium Webdriver Cannot Locate an Element on a Pop Up Page in Instagram

First of all sorry for my junky coding, I am not a coder of any sort.
I created (copied xd) an Instagram bot like a year ago, and it was working absolutely fine until two months ago. My goal with my Instagram bot is to identify new followers and unfollowers and stuff for my main account. I don't do rapid followings and unfollowings. The problem is when I open the following popup on Instagram, selenium cannot find any element that I specify. I've tried using XPATH, CSS Selector, by class name and all those methods. But I cannot even click the close button after I open that popup page, the code cannot find the button. Do you guys have any ideas why or any suggestions?
last_ht, ht = 0, 1
WebDriverWait(self.browser, 10).until(EC.presence_of_element_located((By.XPATH, "//div[#class=_aano]")))
scroll_box = self.browser.find_element_by_xpath("//div[#class=_aano]")
while last_ht != ht:
last_ht = ht
time.sleep(2.5)
ht = self.browser.execute_script(
"arguments[0].scrollTo(0, arguments[0].scrollHeight);"
"return arguments[0].scrollHeight;", scroll_box)
The code above should wait for the Following button on your profile page and then click it (there is nothing wrong until there), and then wait for the popup to load and then scroll, but the WebDriverWait function raises an error, meaning the code cannot find the element, but like I can literally see it. It waits for 10 seconds.
I've tried Chrome and then Firefox, but it was even worse in Mozilla, it couldn't locate the Followings button on the profile page.
Since you haven't shared the applicable part of the DOM, my best guess is that the element you need to interact with is located inside an iframe. To interact with components inside an iframe, you must switch to the iframe first (which means you need to write a locator for the iframe, and then execute the rest of your code.
last_ht, ht = 0, 1
# you must provide the xpath string for the iframe
driver.switch_to.frame(driver.find_element_by_xpath("..."))
WebDriverWait(self.browser, 10).until(EC.presence_of_element_located((By.XPATH, "//div[#class=_aano]")))
scroll_box = self.browser.find_element_by_xpath("//div[#class=_aano]")
while last_ht != ht:
last_ht = ht
time.sleep(2.5)
ht = self.browser.execute_script(
"arguments[0].scrollTo(0, arguments[0].scrollHeight);"
"return arguments[0].scrollHeight;", scroll_box)
# the rest of your code
Once you finish with the components in the iframe, you must switch back to the parent frame.
driver.switch_to.parent_frame()
Or switch to the top window
driver.switch_to.default_content()
Try them in that order. I am sure the first one will work for you.
My goal with my Instagram bot is to identify new followers and unfollowers and stuff for my main account
So you should click "followers" button instead of "following" button, like you said here.
The code above should wait for the Following button on your profile page
So, assume that's what you need, this code will help you scroll down the "followers" popup. I put the whole code here because i don't know if your code clicked the "followers" button or not. Also, the:
last_ht, ht = 0, 1
while last_ht != ht:
last_ht = ht
part will make your scrolling down action run only once, quite weird that they use 3 lines of code for doing nothing. just remove that part and your code will do exact same thing it previously does. So I use a for loop here instead.
Things to change to use the code:
Put your username and password in these two lines:
INS_EMAIL = "youremail#gmail.com"
INS_PASSWORD = "yourpassword"
Fix the link in this line to your ins account link:
self.driver.get("https://www.instagram.com/geeks_for_geeks/")
Change "followers" to "following" depend on your use case:
followers = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((
By.PARTIAL_LINK_TEXT,
'followers')))
I'm using a 100 times for loop but if you want to scroll until it reaches the end of the file, guess I can change that later.
Next time you should post longer code so we can understand if other parts are working or not.
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import os
# ------------ CONSTANTS ------------- #
INS_EMAIL = 'youremail#gmail.com'
INS_PASSWORD = 'yourpassword'
INS_URL = 'https://instagram.com'
class InstaFollower:
def __init__(self):
s = Service(ChromeDriverManager().install())
self.driver = webdriver.Chrome(service=s)
def login(self):
self.driver.get(INS_URL)
time.sleep(3)
username_input_tag = WebDriverWait(self.driver,
10).until(EC.presence_of_element_located((By.XPATH,
"//input[#name='username']")))
username_input_tag.send_keys(INS_EMAIL)
password_input_tag = WebDriverWait(self.driver,
10).until(EC.presence_of_element_located((By.XPATH,
"//input[#name='password']")))
password_input_tag.send_keys(INS_PASSWORD)
password_input_tag.send_keys(Keys.ENTER)
def find_followers(self):
time.sleep(2)
self.driver.get('https://www.instagram.com/geeks_for_geeks/')
# change the link above to your instagram link
time.sleep(3)
followers = WebDriverWait(self.driver,
10).until(EC.presence_of_element_located((By.PARTIAL_LINK_TEXT,
'followers')))
# The line above is optional, you can change followers to following
followers.click()
time.sleep(3)
try:
popup = self.driver.find_element(By.CSS_SELECTOR, '._aano')
except:
print 'FAILED TO FIND POPUP ELEMENT'
else:
print 'Popup element is found'
for run in range(100):
print(f"scrolling down {run}")
self.driver.execute_script('arguments[0].scrollTop = arguments[0].scrollHeight'
, popup)
time.sleep(2)
insta_follower_bot = InstaFollower()
insta_follower_bot.login()
time.sleep(2)
insta_follower_bot.find_followers()
I'm curious to know your result because I'm currently working on the similar project.
Added a lot of time.sleep because the libary's internet is so badddd

Failed to obtain response using Selenium python to automate visiting a website

Basically what I want to do is to automate visiting
this website. If you visit using Chrome, manually picking report type and date, a download link will appear. I tried to automate this process using python + selenium by
following the suggestions in the linked question. But selenium clicking the Get Data button didn't work. I don't know why. Please help.
Please see this link https://stackoverflow.com/a/68598528/12469120 for more context about how to use DatePicker.
Her is my code.
from selenium import webdriver
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
import time
driver = webdriver.Chrome()
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source":
"const newProto = navigator.__proto__;"
"delete newProto.webdriver;"
"navigator.__proto__ = newProto;"
})
driver.get("https://www.nseindia.com/products/content/derivatives/equities/archieve_fo.htm")
time.sleep(5)
datepicker = driver.find_element_by_id("date")
datepicker.click()
selectMonth = driver.find_element_by_xpath('//select[#class="ui-datepicker-month"]')
for option in selectMonth.find_elements_by_tag_name('option'):
if option.text == 'Mar':
option.click()
break
selectYear = driver.find_element_by_xpath('//select[#class="ui-datepicker-year"]')
for option in selectYear.find_elements_by_tag_name('option'):
if option.text == '2018':
option.click()
break
days = driver.find_elements_by_xpath('//a[#class="ui-state-default"]')
days[4].click()
time.sleep(2)
select = Select(driver.find_element_by_id('h_filetype'))
select.select_by_visible_text('Market Activity Report')
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'getdata-button')))
element.click()
time.sleep(20)
Update
The site can detect Selenium driven browsers. A workaround is added in the code. The download link can be obtained.
The issue is that, there is no file available for the specified date.
No file found for specified date. Try another date.
Though, there were some tweak needed, I have made some changes, see below :-
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(30)
driver.get("https://www.nseindia.com/products/content/derivatives/equities/archieve_fo.htm")
wait = WebDriverWait(driver, 20)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[id='date']"))).click()
select_month = Select(wait.until(EC.visibility_of_element_located((By.XPATH, "//select[#class='ui-datepicker-month']"))))
select_month.select_by_visible_text('Mar')
select_year = Select(wait.until(EC.visibility_of_element_located((By.XPATH, "//select[#class='ui-datepicker-year']"))))
select_year.select_by_visible_text('2017')
days = driver.find_elements_by_xpath("//a[#class='ui-state-default']")
days[3].click()
time.sleep(2)
select = Select(wait.until(EC.element_to_be_clickable((By.ID, "h_filetype"))))
select.select_by_value('fomkt')
element = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'getdata-button')))
element.click()
Update 1:
look, this css selector represent the 'file not available' message
div#spanDisplayBox td
it's actually working manually, but hangs with automation (chrome browser). I have faced this issue earlier as well with the same site. However, I have added a method that could help us in following way :
element = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'getdata-button')))
element.click()
try:
if(len(driver.find_elements(By.CSS_SELECTOR, "div#spanDisplayBox td"))) > 0:
print("Response is present")
print(wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div#spanDisplayBox td"))).text)
else:
print("There is no response")
except:
print("something went wrong")
pass
However, when I ran this I got this output :-
There is no response
I would recommend you to check this with Firefox, (cross browser, cross platform and see if that helps).

Not able to click button with Selenium (Python)

I'm trying to click a button using Selenium, but everytime I get the message that it can't find the element. This happens even when I put a time.sleep() in front of it.
time.sleep(5)
#Click on download
downloadButton = driver.find_element_by_css_selector('#downloadButton')
time.sleep(5)
downloadButton.click()
#Click on close
closeButton = driver.find_element_by_xpath('//*[#id="btnZorgAnnuleren"]')
closeButton.click()
The button is inside of a frame (not iframe), but I don't know how to switch to it. Here is the frame source code and page source code: https://www.codepile.net/pile/ZoG0REzQ. Can anyone help me out?
If it's iframe :
the I would suggest you to switch to frame like this (with explicit waits):
wait = WebDriverWait(driver, 10)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "iframe ID")))
Imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
once you have switched you can click like this :
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#downloadButton"))).click()
and click on close :
wait.until(EC.element_to_be_clickable((By.ID, "btnZorgAnnuleren"))).click()
and once you are done, you should switch to default content like this :
driver.switch_to.default_content()

Upload profile picture on Microsoft with selenium, python ()

So, what I'm trying to do is to automate a process which opens the Microsoft login page, enters the login information and then logs in. After that it clicks on the profile and then clicks on change profile picture button.
Now, I'm having trouble with the next part....which is to upload a picture and set it as profile picture.
I searched all over the internet but can't find a solution.
My code till now is -
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from selenium.webdriver import ActionChains
chromedriver = 'C:\\Users\\verma\\Downloads\\chromedriver.exe'
browser = webdriver.Chrome(chromedriver)
action = ActionChains(browser)
#1. Open Microsoft Login Page
browser.get('https://www.microsoft.com/en-in/?wa=wsignin1.0')
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID,"mectrl_headerPicture"))).click()
#2. Login with Username and Password
user = (By.ID,"i0116")
WebDriverWait(browser, 10).until(EC.element_to_be_clickable(user)).send_keys("emailid#outlook.com")
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID,"idSIButton9"))).click()
password = (By.ID,"i0118")
WebDriverWait(browser, 10).until(EC.element_to_be_clickable(password)).send_keys("password")
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID,"idSIButton9"))).click()
#3. Click on Profile and then Click on Change Picture
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID,"mectrl_headerPicture"))).click()
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID,"mectrl_currentAccount_picture_profile_picture"))).click()
#4. Upload Picture
time.sleep(5)
browser.quit()
What I have tried is -
#4. Upload Picture
WebDriverWait(browser, 30).until(EC.element_to_be_clickable((By.ID,"id__62"))).click()
The windows file chooser is not popping up. My guess is that I gave wrong ID for "Choose File" button/link to selenium and that's why it gives TimeoutException since it cant find the element.
But I cant seem find the correct ID. I also want to know how to upload the picture after the File Chooser pops up successfully.
EDIT: Screenshot of the HTML code (Through Inspect)
HTML Code
There are few steps that you need to follow in order to upload a pic :
you need to switch driver focus to new tab
Click on Add a photo.
Upload a pic.
Assert Successful Message.
Code :
#4. Upload Picture
windows_before = browser.current_window_handle
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID,"mectrl_currentAccount_picture_profile_picture"))).click() # this is from #3
windows_after = browser.window_handles
new_window = [x for x in windows_after if x != windows_before][0]
browser.switch_to.window(new_window)
browser.find_element(By.CSS_SELECTOR, "button[id='profile.profile-page.profile-pic-section.edit-picture']").click()
browser.find_element(By.CSS_SELECTOR, "button[id='button[id='profile.edit-picture.upload-button']']").click()
browser.find_element(By.CSS_SELECTOR, "input[type='file']").send_keys("path of the file to be uploaded")
#Assert your msg

Categories

Resources