This is a Win10 machine.
I have a file on disk called "test.html". When I run this in a terminal window C:\>test.html my default browser opens, and that is chrome.
Now I do the same in python
C:\> copy con test.py
import webbrowser
webbrowser.open('http://www.python.org')
^Z
1 file(s) copied.
C:\>python test.py
and Chrome, the default browser opens
But when I take an HTML response from an API call, and do the same webbrowser.open(...) then Internet Explorer opens. Not Edge, not Chrome, but Internet explorer.
How? It's almost as if there is something in the response that tells it "open with IE" except that if do it manually from the command line with C:\>response.html it opens chrome too.
Where is this instruction to open Internet Explorer coming from?
It should use your default browser. Otherwise, it falls back to IE
It appears to use os.startfile() to detect file associations, so running os.startfile('response.html') apparently throws a OSError for you, and you have no other browser installed in the list. Surprisingly, "chrome" nor "edge" is listed there.
Related - https://github.com/python/cpython/pull/11327
Another option you could try is to use something like webbrowser.open("file://c/response.html")
You can try webbrowser.get().
For example, opening a new tab in Google Chrome:
webbrowser.get(using='google-chrome').open_new_tab('https://google.com')
But it is not always possible to get by with .get () alone, and in this case the .register () function comes to the rescue, for example:
import webbrowser
webbrowser.register('Chrome', None, webbrowser.BackgroundBrowser('C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'))
webbrowser.get('Chrome').open_new_tab('google.com')
You can also check these links:
https://docs.python.org/3/library/webbrowser.html
http://pymotw.com/2/webbrowser/
https://discourse.world/h/2019/10/10/How-to-open-a-link-in-Python.Working-with-WebBrowser-and-solving-a-problem-with-Internet-Explorer
Related
I have to bring to front a Chrome tab (already open) with code.
More precisely, I have a tab (with its url) open in a Chrome browser (in kiosk mode) and, when the tab is in background, I want to bring it to front by means of a Chrome shortcut, an execuble file or a script.
The tab brought to front must be the same that was in background, and with the same url.
Can I do this with Python or by means of a Chrome shortcut, configuring its properties?
#Open google in python - Windows.
import webbrowser
url='https://google.com'
webbrowser.get('C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s').open(url)
When I try to use Cookies file (sqlite fomatted) on Linux (Ubuntu) and Windows I fall into troubles with decryption of 'encrypted_value'. Is there any chance to make Cookies file compatible with two systems?
Basically selenium driver use Cookies file for various purpouses, and everything works on Linux. Sometimes my action is needed, so I want to have this Cookies file on my desktop which works on Windows, but when I download it directly and copy-paste it to my profile directory, my chromedriver logs error:
[4708:4884:0604/082853.607:ERROR:os_crypt_win.cc(61)] Failed to decrypt: The parameter is incorrect. (0x57)
I assume that there is some problem with 'encrypted_value' column decryption but I am unable to work-around this issue.
I use selenium for python this is snippet where I create options for my webdriver:
def create_options_for_webdriver(session_directory):
print('Creating options for webdriver!')
options = Options()
options.add_argument("user-data-dir=my_userdir")
options.add_argument("user-agent=my_useragent")
options.add_argument('--disable-background-networking ')
options.add_argument('--disable-client-side-phishing-detection')
options.add_argument('--disable-default-apps')
options.add_argument('--disable-hang-monitor')
options.add_argument('--disable-popup-blocking')
options.add_argument('--disable-prompt-on-repost')
options.add_argument('--disable-sync')
options.add_argument('--disable-web-resources')
options.add_argument('--enable-automation')
options.add_argument('--enable-blink-features=ShadowDOMV0')
options.add_argument('--force-fieldtrials=SiteIsolationExtensions/Control')
options.add_argument('--ignore-certificate-errors')
options.add_argument('--no-first-run')
options.add_argument('--password-store=basic')
options.add_argument('--use-mock-keychain')
return options
before option creating I create minimal directory structure which looks like my_userdir/Default/, and I download Cookies file to Default folder.
... when I download it directly and copy-paste it to my profile directory, my chromedriver logs error:
[... ERROR:os_crypt_win.cc(61)] Failed to decrypt: The parameter is incorrect. (0x57)
It looks like it is not possible. Or maybe not possible they way you are trying to do it. It takes extra effort.
The question Decrypting Chrome's cookies on windows has a link to os_crypt_win.cc. os_crypt_win.cc uses DPAPI, which is the old WinCrypt gear. DPAPI ties encryption to a user's Windows login. DPAPI also places a MAC on the encrypted data. I believe the MAC is the reason for the message you are seeing: "The parameter is incorrect". DPAPI sees the MAC over the encrypted data is wrong, and it gives you the generic error message.
So if you truly want to use the Linux cookie on Windows, you will need to decrypt it using the Linux spec, and then re-encrypt it using the Windows spec.
If you are going to pursue it, then you may want to visit this BlackHat talk: Reversing dpapi and stealing windows secrets offline. It will allow you to encrypt the user's data on Linux for Windows.
Coming back with update!
It appears that, as #jww mentioned process is more complicated, but just a little :)
In order to make Cookies fully compatible with any OS some special treatment must be applied.
In my case I used pickle library to create compatible file. To achieve it, things needs to be done as follow:
from selenium.webdriver import Chrome
import pickle
driver = Chrome()
####here you do some job which generate cookies like FB login or whatever
input("Press any key to close session") #you cant simply close browser, in order to make it work browser have to be closed in console so the rest of script will execute
pickle.dump(driver.get_cookies(), open('cookies.pkl',"wb"))
driver.quit()
print("Session closed!")
This will create cookies.pkl file which can be accessed under any OS like that:
import pickle
from selenium import Chrome
driver = Chrome()
for cookie in pickle.load(open("cookies.pkl"."rb")):
driver.add_cookie(cookie)
### anything you want to execute
As I mentioned this kind of cookies file will work under any OS, sadly it forced me to use selenium, but better this than nothing :)
Below is the code I'm using - I've attempted to make it as concise as possible.
import selenium
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import bs4
options=Options()
#options.add_argument('--headless') # Works while not headless?
options.add_argument('--disable-gpu') # Last I checked this was necessary.
options.add_argument("--user-data-dir=profiles\\") #Keeps login data
options.add_argument("--profile-directory=Profile 1")
driver=webdriver.Chrome(chrome_options=options)
driver.get("http://www.google.com")
html=driver.page_source
soup=bs4.BeautifulSoup(html, "html.parser")
print(soup)
The main problem stems from the --user-data-dir and --profile-directory parameter. In my test example a custom chrome profile (usually found at C:\Users\User\AppData\Local\Google\Chrome\User Data) is in the current directory to keep it separate from any currently running chrome sessions.
If the --headless parameter is enabled while using the above parameters the driver hangs (the CMD stays and does not produce output on the Python command line). However, when not enabled the window pops open and performs as expected.
However, --headless does work while using any profile within the above default directory.
This is the console output;
[0120/222514.611:ERROR:gpu_process_transport_factory.cc(967)] Lost UI shared context.
DevTools listening on ws://127.0.0.1:59961/devtools/browser/ee317ed6-93c7-47c2-b26d-63647980ba0d
[0120/222514.619:ERROR:devtools_http_handler.cc(289)] Error writing DevTools active port to file
[0120/222514.624:ERROR:cache_util_win.cc(19)] Unable to move the cache: 0
[0120/222514.625:ERROR:cache_util.cc(140)] Unable to move cache folder profiles\Default\GPUCache to profiles\Default\old_GPUCache_000
[0120/222514.625:ERROR:disk_cache.cc(184)] Unable to create cache
[0120/222514.625:ERROR:shader_disk_cache.cc(622)] Shader Cache Creation failed: -2
So, it looks like somewhere Chromium is assuming I'm using the Default profile when in fact I specify I am not.
Does anyone have any suggestions? Thanks in advance!
I was able to your code to run with the following option added.
options.add_argument('--remote-debugging-port=45447')
Without it the code was hanging for around a minute before the following error was thrown:
WebDriverException: Message: unknown error: DevToolsActivePort file doesn't exist
Comment excerpt which pointed me to a solution:
When you send --remote-debugging-port=0 to Chrome, devtools chooses
its own port and writes it to chrome::DIR_USER_DATA as a file
named "DevToolsActivePort".
Basically once the port is set to something other than the default of 0 the DevToolsActivePort file does not need to be checked.
The full comment and bug are here: chromedriver bug
Hope this helps!
I solved this error by closing the command prompt and reopening it in administrator mode (right-click on the cmd.exe and click Run as administrator).
Nothing else worked.
I am using "Python-3.4.1 32 bit" on "Windows 7 64 bit" machine with "Selenium" using "Firefox 33". I am trying to automate downloading a "CSV" file from a secured website after furnishing the necessary credentials.
I have written the required code to navigate to the correct element to initiate the download of the file but I am stuck when Firefox gives the download box (Dialog box title: Opening export.csv, "Open with" and "Save File" options as radio buttons with "OK" and "Cancel" as buttons). I want the file to be downloaded automatically and for that I have tried the following codes without success:
from selenium import webdriver
fp = webdriver.FirefoxProfile()
fp.set_preference("browser.download.manager.showWhenStarting",False)
fp.set_preference("browser.download.folderList",2)
fp.set_preference("browser.download.dir", "C:\\Users\\arun\\Downloads")
fp.set_preference("browser.download.downloadDir", "C:\\Users\\arun\\Downloads")
fp.set_preference("browser.download.defaultFolder", "C:\\Users\\arun\\Downloads")
fp.set_preference('browser.helperApps.neverAsk.saveToDisk',"text/csv")
fp.set_preference("browser.helperApps.neverAsk.openFile", "CONTENT-TYPE")
fp.set_preference("browser.helperApps.neverAsk.saveToDisk","CONTENT-TYPE")
driver = webdriver.Firefox(fp)
driver.get("http://website-url.com")
and then click on the button to start the download. But, it still shows the dialog box. I even tried handling it as an alert and tried:
alert = driver.switch_to_alert()
alert.accept()
but this always gave an exception of alert not found which led me to the conclusion that it might not be a JavaScript functionality after all but rather a web element.
What do I do to get this downloaded automatically without the dialog box interaction (the way it's handled in Google Chrome browsers)
Thanks for your help and time
Cheers!
You set browser.helperApps.neverAsk.saveToDisk to text/csv and then two lines later you set it to CONTENT-TYPE.
According to this page this preference is interpreted as a list of MIME types. CONTENT-TYPE is not a valid MIME type and it has no other special meaning. You want to remove the 2nd assignment to browser.helperApps.neverAsk.saveToDisk. You probably also don't want the assignment to browser.helperApps.neverAsk.openFile.
Once, your browser.helperApps.neverAsk.saveToDisk is set properly, you should not have to worry about accepting a dialog box.
Selenium doesn't allow interaction with dialog windows (Save As dialog windows, for example). selenium is a web driver, so it only interacts with the browser.
I recommend using pywinauto and pywin32. It is a form of windows automation.
The problem is that selenium will "pause" while the dialog window is up, so to achieve this, the only way I know would be to write two scripts. The first would be the selenium / web automation process, and the other one the windows automation using pywinauto and/or pywin32.
You can then call the windows automation script at the end of the selenium/web automation script by:
import subprocess
subprocess.call("python C:\Python27\Scripts\windowsAutomation.py", shell=True)
One more thing, I am using FireFox 31
You can try with Chrome chrome browser if all else fails. Chrome will not ask for download location but you have to enable multiple file download and set a save location
I am using a hmtl file as a help document for my program, and would really like to be able to open the file at a specific point. i assumed i would be able to do this using the built in webbrowser module by specifying a url with a bookmark.
this is my html file name: help.html
i assumed that i would be able to use: help.html#top
this is the code i am using to open the file, this works fine:
webbrowser.open("Files\help.html")
and this is the code i have been trying to use to open at a specific point which ie9 apparently cant display (not sure why it is trying to load in ie9 as chrome is my default browser, and the working one above loads in chrome):
webbrowser.open("Files\help.html#2.1.0")
any ideas guys?
webbrowser.open() calls the browser from the command line. So you might try to do that yourself first. If that doesn't work, it's likely that your browser just doesn't support that for local files or something.
With Ubuntu+Firefox for example, webbrowser.open() does what you ask. (but - as Dave Webb said in his answer - you do have to provide a file: url, not just a filename).
(not on Windows at the moment, so haven't checked there)
As for why it doesn't load chrome but ie9: (you can look in the webbrowser.py code yourself if you want) I think it does try to use your default webbrowser, by doing os.startfile(url). What happens when you doubleclick your help.html file, of when you just type help.html (adjust path as needed) at the command line? It should do the same.
EDIT:
It seems that it doesn't always use the command line. On Windows, when trying to use the default browser, it uses os.startfile() which in turn uses the win32 ShellExecute api. ShellExecute can be used to perform certain actions on a file, folder or URL, like "open", "edit" or "print" with its default application. In this case, ShellExecute is asked to "open" the URL.
It seems however, that ShellExecute ignores the fragment identifier (the part after #) when opening file: urls. Strangely enough, this is not the case with http:urls. Presumably, a file: url is just converted to a plain filename first.
There seems to be little you can do about this except:
write something that "does the right thing" yourself (and register it as a browser controller for the webbrowsermodule, and use webbrowser.get() to get your controller, see docs)
as many applications do: configure the browser you want to use (or make it possible for your users to do so). The easiest way would be to set the BROWSER environment variable (see webbrowser module docs)
serve the file via a localhost http server, and open the http url, which would then be something like "http://. "http://localhost:8000/help.html#2.1.0". (The SimpleHttpServer module might come in handy)
Or, the easiest way: as you seem to be on windows: just try to open internet explorer specifically:
try:
browser = webbrowser.get('c:\\Program Files\\Internet Explorer\\IEXPLORE.EXE')
except Webbrowser.Error:
browser = webbrowser.get()
browser.open(url)
(This will fall back to using the default, so your code would still work on other platforms)
I think webbrowser is expecting a URL, so have you tried something like:
webbrowser.open("file://c:/path/to/files/html.html#2.1.0")