How to handle Save File dialog box in firefox using selenium with python? - python-2.6

I'm trying to download .csv file using selenium tool in python but after clicked on save file link in web page, the browser is showing me dialog box.I tried "alert" to handle this but it gives me error like, alert is not present....
I'm using python as a scripting language and selenium as a tool.
here is the my code:
fp = webdriver.FirefoxProfile()
fp.set_preference('browser.download.folderList', 2) # custom location
fp.set_preference('browser.download.manager.showWhenStarting', False)
fp.set_preference('browser.download.dir', 'C:\Temp\')
fp.set_preference('browser.helperApps.neverAsk.saveToDisk', 'application/csv,text/csv,text/comma-separated-values, application/octet-stream')
driver = webdriver.Firefox(profile)
driver.window_handles
driver.swich_to_window(driver.window_handles[0])
url=''
driver.get(url)
pass=driver.find_element_by_id('pswd')
pass.send_keys('xyz123')
driver.find_element_by_id('btnLogin').click()
driver.implicitly_wait(30)
driver.find_element_by_link_text('FileName').click()
driver.switch_to_alert().accept()

Finally I am done with Save file dialog box. I have handled it with some firefox profile preference settings. Since I was not unable to find out the exact MIME type I used all possible.
Below is my code to handle the Save file Dialog box :
fp = webdriver.FirefoxProfile()
fp.set_preference('browser.download.folderList', 2)
fp.set_preference('browser.download.manager.showWhenStarting', False)
fp.set_preference('browser.download.dir', r'C:\Temp\')
fp.set_preference('browser.helperApps.neverAsk.openFile', 'text/csv,application/x-msexcel,application/excel,application/x-excel,application/vnd.ms-excel,image/png,image/jpeg,text/html,text/plain,application/msword,application/xml')
fp.set_preference('browser.helperApps.neverAsk.saveToDisk', 'text/csv,application/x-msexcel,application/excel,application/x-excel,application/vnd.ms-excel,image/png,image/jpeg,text/html,text/plain,application/msword,application/xml')
fp.set_preference('browser.helperApps.alwaysAsk.force', False)
fp.set_preference('browser.download.manager.alertOnEXEOpen', False)
fp.set_preference('browser.download.manager.focusWhenStarting', False)
fp.set_preference('browser.download.manager.useWindow', False)
fp.set_preference('browser.download.manager.showAlertOnComplete', False)
fp.set_preference('browser.download.manager.closeWhenDone', False)
driver = webdriver.Firefox(fp)
driver.window_handles
driver.switch_to_window(driver.window_handles[0])
url=''
driver.get(url)
pass=driver.find_element_by_id('pswd')
pass.send_keys('xyz123')
driver.find_element_by_id('btnLogin').click()
driver.implicitly_wait(30)
driver.find_element_by_link_text('FileName').click()
time.sleep(5)

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import time
import pyautogui
try :
driver = webdriver.Firefox()
driver.implicitly_wait(30)
driver.maximize_window()
driver.get("https://www.citysdk.eu/wp-content/uploads/2013/09/DELIVERABLE_WP4_TA_SRS_0.21.pdf")
# WebDriverWait(driver, 10).until(lambda d: d.execute_script('return document.readyState') == 'complete')
# Click the OK button and close
time.sleep(5)
webelem = driver.find_element_by_id('download')
webelem.click()
time.sleep(5)
print('press enter')
pyautogui.press('enter')
except Exception as err:
print('ERROR: %sn' % str(err))
driver.quit()

Related

Youtube comment use selenium

import subprocess
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
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.chrome.options import Options
subprocess.Popen(r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\chrometemp"') # 디버거 크롬 구동
option = Options()
option.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = webdriver.Chrome('chromedriver', options = option)
url = 'https://www.youtube.com/watch?v=_XulUbBra5M'
driver.get(url)
driver.maximize_window() # 크롬 창 크기 최대화
driver.implicitly_wait(3) # 페이지 로드까지 3초간 기다림
heihgt = driver.execute_script(
"return document.documentElement.scrollHeight"
)
# 기존 위치
stand_height = 0
while True:
# 현재 높이
current_height = driver.execute_script(
"return document.documentElement.scrollHeight"
)
driver.execute_script(
f"window.scrollTo(0, {stand_height});" #스크롤 내리기
)
time.sleep(1)
# 스크롤 내린 페이지의 높이
new_page_height = driver.execute_script(
"return document.documentElement.scrollHeight"
)
stand_height = heihgt
heihgt = new_page_height
time.sleep(1)
driver.find_element(By.XPATH, "//*[#id='contenteditable-root']")
#driver.close()
I'm making a program that uses crawling to comment comments, but when I find the location of comments with xpath, I get the following error: I don't know why.
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id='contenteditable-root']"}
(Session info: chrome=96.0.4664.110)
Python does not support driver.find_element_by_xpath , it supports driver.find(By.XPATH,) . Does this cause an error? please tell me why
The input element to insert a new comment is not initially loaded on the page.
To make this element loaded you need to scroll the page down.
Also, to make the actual input comment element to be interactable you first need to click another element.
This should work:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
url = 'https://www.youtube.com/watch?v=_XulUbBra5M'
driver.get(url)
wait = WebDriverWait(driver, 20)
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "button.ytp-play-button")))
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
wait.until(EC.visibility_of_element_located((By.XPATH, "//*[#id='simplebox-placeholder']"))).click()
wait.until(EC.visibility_of_element_located((By.XPATH, "//*[#id='contenteditable-root']"))).send_keys(your_comment_text)

gspread data does not appear in Google Sheet

I'm trying to write sensor data to a google sheet. I was able to write to this same sheet a year or so ago but I am active on this project again and can't get it to work. I believe the Oauth has changed and I've updated my code for that change.
In the below code, I get no errors, however no data in entered in the GoogleSheet. Also, If I look at GoogleSheets, the "last opened" date does not reflect the time my program would/should be writing to that google sheet.
I've tried numerous variations and I'm just stuck. Any suggestions would be appreciated.
#!/usr/bin/python3
#-- developed with Python 3.4.2
# External Resources
import time
import sys
import json
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import traceback
# Initialize gspread
scope = ['https://spreadsheets.google.com/feeds']
credentials = ServiceAccountCredentials.from_json_keyfile_name('MyGoogleCode.json',scope)
client = gspread.authorize(credentials)
# Start loop ________________________________________________________________
samplecount = 1
while True:
data_time = (time.strftime("%Y-%m-%d %H:%M:%S"))
row = ([samplecount,data_time])
# Append to Google sheet_
try:
if credentials is None or credentials.invalid:
credentials.refresh(httplib2.Http())
GoogleDataFile = client.open('DataLogger')
#wks = GoogleDataFile.get_worksheet(1)
wks = GoogleDataFile.get_worksheet(1)
wks.append_row([samplecount,data_time])
print("worksheets", GoogleDataFile.worksheets()) #prints ID for both sheets
except Exception as e:
traceback.print_exc()
print ("samplecount ", samplecount, row)
samplecount += 1
time.sleep(5)
I found my issue. I've changed 3 things to get gspread working:
Downloaded a newly created json file (probably did not need this step)
With the target worksheet open in chrome, I "shared" it with the email address found in the JSON file.
In the google developers console, I enabled "Drive API"
However, the code in the original post will not refresh the token. It will stop working after 60 minutes.
The code that works (as of July 2017) is below.
The code writes to a google sheet named "Datalogger"
It writes to the sheet shown as Sheet2 in the google view.
The only unique information is the name of the JSON file
Hope this helps others.
Jon
#!/usr/bin/python3
# -- developed with Python 3.4.2
#
# External Resources __________________________________________________________
import time
import json
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import traceback
# Initialize gspread credentials
scope = ['https://spreadsheets.google.com/feeds']
credentials = ServiceAccountCredentials.from_json_keyfile_name('MyjsonFile.json',scope)
headers = gspread.httpsession.HTTPSession(headers={'Connection': 'Keep-Alive'})
client = gspread.Client(auth=credentials, http_session=headers)
client.login()
workbook = client.open("DataLogger")
wksheet = workbook.get_worksheet(1)
# Start loop ________________________________________________________________
samplecount = 1
while True:
data_time = (time.strftime("%Y-%m-%d %H:%M:%S"))
row_data = [samplecount,data_time]
if credentials.access_token_expired:
client.login()
wksheet.append_row(row_data)
print("Number of rows in out worksheet ",wksheet.row_count)
print ("samplecount ", samplecount, row_data)
print()
samplecount += 1
time.sleep(16*60)

Spotfire - mark records and send to clipboard

I'd like to create a Spotfire button action control that does the following
Select all rows in a table visualization
Send the selected rows to the clipboard
First step was handled pretty easily (borrowed from here). For the second step, I was unsuccessful in my initial attempts to send to clipboard with script (e.g. as suggested here). I was partially successful in a followup attempt by sending ctrl-c programatically to spotfire (see spotfired.blogspot.co.id/2014/04/pressing-keys-programatically.html).
Here's the [mostly] functioning code:
from Spotfire.Dxp.Application.Visuals import VisualContent
from Spotfire.Dxp.Data import IndexSet
from Spotfire.Dxp.Data import RowSelection
#Get table reference
vc = vis.As[VisualContent]()
dataTable = vc.Data.DataTableReference
#Set marking
marking=vc.Data.MarkingReference
#Setup rows to select from rows to include
rowCount=dataTable.RowCount
rowsToSelect = IndexSet(rowCount, True)
#Set marking
marking.SetSelection(RowSelection(rowsToSelect), dataTable)
#Script to send keystroke to Spotfire
import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import SendKeys, Control, Keys
#Send keystroke for CTRL-C Copy-to-clipboard
SendKeys.Send("^c") #Ctrl+C
The code works as expected, except that I have to hit the button twice for the ctrl-c part of the script to work (i.e. hitting once results in marking all rows in the table visualization).
Another issue that I seemed to have resolved is that the originally suggested syntax to send the ctrl-c keystroke command was SendKeys.Send("(^+C)"). However, this didn't work, so I rewrote as SendKeys.Send("^c"), which does work, except only after I hit the button twice.
Any thoughts on how I could fix the issue of having hit the action control button twice?
A workaround could be to avoid sending keystrokes with script and revisit my first attempt code the copy-to-clipboard functionality, but my Ironpython skills are a limiting factor here.
Using the same post as reference I used this code to use the windows clipboard
tempFolder = Path.GetTempPath()
tempFilename = Path.GetTempFileName()
tp = mytable.As[TablePlot]()
writer = StreamWriter(tempFilename)
tp.ExportText(writer)
f = open(tempFilename)
html=""
for line in f:
html += "\t".join(line.split("\t")).strip()
html += "\n"
f.close()
import clr
clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import Clipboard
Clipboard.SetText(html)
Thanks, sayTibco, code working for me, now. See below for updated version. Still curious to know how to better utilize SendKeys.Send(), but will make that the subject of a separate post after I have some time to experiment.
from Spotfire.Dxp.Application.Visuals import VisualContent, TablePlot
from Spotfire.Dxp.Data import IndexSet
from Spotfire.Dxp.Data import RowSelection
#get table reference
vc = mytable.As[VisualContent]()
dataTable = vc.Data.DataTableReference
#set marking
marking=vc.Data.MarkingReference
#setup rows to select from rows to include
rowCount=dataTable.RowCount
rowsToSelect = IndexSet(rowCount, True)
#Set marking
marking.SetSelection(RowSelection(rowsToSelect), dataTable)
#Copy marked records to Clipboard
import clr
import sys
clr.AddReference('System.Data')
import System
from System.IO import Path, StreamWriter
from System.Text import StringBuilder
#Temp file for storing the table data
tempFolder = Path.GetTempPath()
tempFilename = Path.GetTempFileName()
#Export TablePlot data to the temp file
tp = mytable.As[TablePlot]()
writer = StreamWriter(tempFilename)
tp.ExportText(writer)
f = open(tempFilename)
#Format table
html=""
for line in f:
html += "\t".join(line.split("\t")).strip()
html += "\n"
f.close()
#Paste to system Clipboard
clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import Clipboard
Clipboard.SetText(html)

Firefox webdriver opens first run page all the time

How to disable this "first run" page once and for all for FF?
When FF driver is created, it opens tab with -
https://www.mozilla.org/en-US/firefox/42.0/firstrun/learnmore/
and additional tab with target page.
To turn off this annoying start page:
in C# with Selenium 2.48 I found the following solution:
FirefoxProfile prof = new FirefoxProfile();
prof.SetPreference("browser.startup.homepage_override.mstone", "ignore");
prof.SetPreference("startup.homepage_welcome_url.additional", "about:blank");
Driver = new FirefoxDriver(prof);
...and it will never bother you again.
Note: One of these settings alone will also work. I use them together to make it bullet-proof.
Ifound a solution, works fine
FirefoxProfile fp = new FirefoxProfile();
fp.setPreference("browser.startup.homepage", "about:blank");
fp.setPreference("startup.homepage_welcome_url", "about:blank");
fp.setPreference("startup.homepage_welcome_url.additional", "about:blank");
I have faced the same problem. I have just changed the Selenium version to 2.48 and the problem solved.
This is caused by incompatibility between Selenium and Firefox versions, but not by any one specific version number.
You should be 1-2 Firefox versions behind the newest, if your WebDriver is on the latest version. Otherwise, roll the Firefox version back even further if your WebDriver is older, or upgrade Webdriver.
To get an older Firefox, try https://ftp.mozilla.org/pub/firefox/releases/ or http://www.oldapps.com/
or on Linux, depending on your distro
yum list --showduplicates firefox
sudo yum install firefox-<version>
or
apt-cache show firefox | grep Version
sudo apt-get install firefox=<version>
C# solution, upgraded Selenium WebDriver to 2.49.0 solved the issue for me.
The above solutions do not work, I've tried them.
What did work for me, and probably will for you (if using firefox 43 or less) is:
prof.setPreference("xpinstall.signatures.required", false);
prof.setPreference("toolkit.telemetry.reportingpolicy.firstRun", false);
The problems with 43 and selenium are twofold, the default signed extensions setting (to true) and the first run page. These lines solve both. These must be set programatically. If you try to set them in about:config (or directly in prefs.js) it will not affect the new browsers you open with selenium. It should be noted that they say firefox 44 will not allow you to set the signed extensions variable (so this will not work on 44).
I include the codeblock from my now working code showing the correct use:
FirefoxProfile prof = new FirefoxProfile();
//FirefoxProfile prof = profile.getProfile("default");
//prof.setPreference("browser.startup.homepage", proteinPageUrl);
//prof.setPreference("startup.homepage_welcome_url", proteinPageUrl);
//prof.setPreference("startup.homepage_welcome_url.additional", proteinPageUrl);
prof.setPreference("xpinstall.signatures.required", false);
prof.setPreference("toolkit.telemetry.reportingpolicy.firstRun", false);
//Object socketLock = new Object();
//synchronized(socketLock){
//driver = new FirefoxDriver();
driver = new FirefoxDriver(prof);
//driver = forceInit();
//driver.open();
//}//end synch block
//get protein page
boolean done = true;
do{
driver.get(proteinPageUrl);
final Wait<WebDriver> waitDriver = new FluentWait<WebDriver>(driver)
.withTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
.pollingEvery(5, java.util.concurrent.TimeUnit.SECONDS);
try{
inputTextFeildElement = waitDriver.until(new Function<WebDriver,WebElement>(){
public WebElement apply(WebDriver diver){
return driver.findElement(By.name("term"));
}});
}
catch(NoSuchElementException nsee){
//if not find by name try find by id
if(driver.findElements(By.id("term")).size() != 0){
try{
inputTextFeildElement = driver.findElement(By.id("term"));
done = true;
} catch(NoSuchElementException nsee2){
synchronized(threadLogFile){
try {
threadLogWriter = new PrintWriter(new FileWriter(threadLogFile.getAbsoluteFile(), true));
} catch (IOException ioe) {
System.out.println("error opening file for append: " + ioe.getMessage());
ioe.printStackTrace();
}//catch
threadLogWriter.println("Thread Id: " + threadId + " with thread name: " + threadName + " fails to find input element by name or id to put accession: " + accession);
threadLogWriter.flush();
threadLogWriter.close();
}//synchronized
done = false;
}//catch nsee2
}//catch nsee
}
catch(ElementNotVisibleException enve){
done = false;
}
}while(!done);
If you using selenium webdriver from Capybara/Cucumber, then you can change the default url when you register your driver using startup.homepage_welcome_url.additional:
Capybara.register_driver :firefox do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
profile['browser.startup.homepage_override.mstone'] = 'ignore'
profile['startup.homepage_welcome_url.additional'] = 'about:blank'
Capybara::Selenium::Driver.new(app, :browser => :firefox, :profile => profile)
end
I faced the same problem.
My solution:
I downgraded Firefox to 36.0.
It worked fine with Selenium 2.53.1.
I hope this help. :)
The problem here for me was, I was using firefox 46.0.1 for testing with latest version of selenium driver which of course worked fine with modern version of the firefox but acted weird with firefox 46.0.1.
To get it working, I had to downgrade the Selenium version to 2.53.0 from 4.4.0 and the respective dependent references should be brought down too.

close pygtk dialog window after it was used

I am currently writing a wrapper for a small console program I wrote.
The c program needs a password string as input and because I intend to use it through dmenu and such, I'd like to use a little gtk entry box to enter that string.
However, I have to fork after I get the input (because I'm also handling clipboard stuff which needs deletion after some time) and the window simply won't close until the child process exits.
from subprocess import Popen, PIPE
from gi.repository import Gtk
import sys
import os
import time
import getpass
HELP_MSG = "foobar [options] <profile>"
class EntryDialog(Gtk.Dialog):
def run(self):
result = super(EntryDialog, self).run()
if result == Gtk.ResponseType.OK:
text = self.entry.get_text()
else:
text = None
return text
def __init__(self):
super(EntryDialog, self).__init__()
entry = Gtk.Entry()
entry.set_visibility(False)
entry.connect("activate",
lambda ent, dlg, resp:
dlg.response(resp),
self,
Gtk.ResponseType.OK)
self.vbox.pack_end(entry, True, True, 0)
self.vbox.show_all()
self.entry = entry
def get_pwd():
if sys.stdin.isatty():
return getpass.getpass()
else:
prompt = EntryDialog()
prompt.connect("destroy", Gtk.main_quit)
passwd = prompt.run()
prompt.destroy()
return passwd
The thought is, that it should close when I hit enter, but I'm pretty sure I'm doing something entirely wrong.
The script basically continues like this:
profile = argv[0]
pwd = get_pwd()
if pwd is None:
print(HELP_MSG)
sys.exit()
out = doStuff()
text_to_clipboard(out)
# now fork and sleep!
if os.fork():
sys.exit()
time.sleep(10)
clear_clipboard()
sys.exit(0)
I dropped the python wrapper and wrote it directly in c. However, for anyone having the same problem, the (untested) solution would be to add a function
def quit():
self.emit("destroy")
where 'self' is the dialog box - and connect that to the "activate" signal,
entry.connect("activate", quit)
so that the dialog widget emits the destroy signal as soon as the user hits Return and thus Gtk.main_quit gets called.
In c the content can be extracted nicely by specifying a GtkEntryBuffer and calling it's
gtk_entry_buffer_get_text()
I didn't find it right now, but there is probably an equivalent for pygtk available.

Resources