selenium webdriver.Firefox not starting for non-sudo user - python

I have a python method that sets up a browser in headless-mode on a linux server for website scraping with selenium. The display gets setup perfectly fine regardless of which user executes the python script but if the sudo user doesn't execute the script it will hang at the webdriver.Firefox() setup line indefinitely.
Here is the full method:
def browserSetup(self, browser=None):
try:
# now Firefox will run in a virtual display. you will not see the browser.
self.display = Display(visible=0, size=(800, 600))
self.display.start()
if self.verbose:
print "Virtual display started for browser instantiation."
#change user agent
profile = webdriver.FirefoxProfile()
profile.set_preference("general.useragent.override", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/536.30.1 (KHTML, like Gecko) Version/6.0.5 Safari/536.30.1")
profile.set_preference("webdriver.log.file", "webdriver.log")
# Create a new instance of the Firefox driver
browser = webdriver.Firefox(profile)
if self.verbose:
print "Browser window object established # %s." % browser
return browser
except Exception, e:
raise e
So, to repeat my issue: if the script is not executed as sudo then the script will hang indefinitely at the webdriver.Firefox creation line. Why would this be happening?
UPDATE: The problem is this line here:
browser = webdriver.Firefox() #with or without the profile variable - the results are the same
UPDATE AGAIN
Several people in the comments below have suggested I try running Firefox from the command line manually to see if there are any issues; here are the results:
#initialize the virtual display
$ sudo Xvfb :10 -extension RANDR
[dix] Could not init font path element /usr/share/fonts/X11/cyrillic, removing from list!
[dix] Could not init font path element /usr/share/fonts/X11/100dpi/:unscaled, removing from list!
[dix] Could not init font path element /usr/share/fonts/X11/75dpi/:unscaled, removing from list!
[dix] Could not init font path element /usr/share/fonts/X11/Type1, removing from list!
[dix] Could not init font path element /usr/share/fonts/X11/100dpi, removing from list!
[dix] Could not init font path element /usr/share/fonts/X11/75dpi, removing from list!
[dix] Could not init font path element /var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType, removing from list!
#now start firefox in another ssh window (since the Xvfb process is consuming my prompt)
$ export DISPLAY=:10
$ firefox
(firefox:6347): GConf-WARNING **: Client failed to connect to the D-BUS daemon:
//bin/dbus-launch terminated abnormally without any error message
The last error message displays hundreds of times...

I can only guess, but here's what I suspect.
sudo clears your environment variables when you start Firefox via it. That includes the DISPLAY variable as well.
Two ways to disable this behavior:
- Disable env_reset in your sudoers configuration.
- Use sudo -i, that will preserve the value of DISPLAY.

First you need to start the Xvfb (virtual frame-buffer X server) in the background.
For example, $ sudo Xvfb :1 & or $ sudo Xvfb :1 -screen 0 1280x1024x8.
Then, whenever you want to run your script, do it with the DISPLAY environment variable set accordingly.
For example, $ DISPLAY=:1 python your_script.py.

You may not want to open usr/lib up for good but try testing it with open perms on the directory.
sudo chmod 755 /usr/lib
If that's the issue, you can always move the drivers inside your application. Unless you're sharing them with many people, they're small enough to have several copies.

For anyone else like me that until today could be having this problem:
For me was due to Firefox needs to be able to create a profile, which is created at the user home folder. The user i created didn't had its own user home folder so when i created it the problem was solved.

Related

How can I get a variable valued current working directory (pwd) in powershell profile

I was trying to use anaconda as my Python virtual environment, and my virtual environment is stored in project directory.
Manually, I need to use following command to activate my local virtual environment:
conda activate ./envs
Before that, I edited script of profile.ps1 with following code:
conda init powershell
and which is revealed as following content:
#region conda initialize
# !! Contents within this block are managed by 'conda init' !!
(& "C:\Users\dengyijian\anaconda3\Scripts\conda.exe" "shell.powershell" "hook") | Out-String | Invoke-Expression
#endregion
So, every time when I lauch my powershell window in project directory (press shift + right click mouse), and I got (base) environment.
What I need is enabling local environment ./venv automatically, for which I tried Including $(pwd) command, but I only got PS C:\Windows\system32>.
So as my title asking, how can I get a variable valued current working directory (pwd) in powershell profile when I launch powershell in specified working directory?
Unfortunately, the "Open PowerShell window here" explorer context menu option doesn't do things in the right order to allow for this. The basic command it runs does this:
working directory starts at c:\Windows\system32\
Starts powershell with command to set directory (you can see this in task manager):
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -noexit -command Set-Location -literalPath '[explorer directory]'
Powershell starts,
then runs your profile .ps1
then finally runs the Set-Location command to switch directory
Your profile script has no idea where it's being sent to yet.
You can kind of get around this by parsing the path from the command line, using $pid to get the process info:
# example of command line when starting powershell from explorer in C:\temp\
(Get-CimInstance win32_process -Filter "Handle=$pid").CommandLine
"PowerShell.exe" -noexit -command Set-Location -literalPath 'C:\temp'
# so, in your profile.ps1, take whatever is after "literalpath", then whatever is between single quotes:
$ExplorerPath = (((Get-CimInstance win32_process -Filter "Handle=$pid").CommandLine -split 'literalPath')[1] -split "'")[1]
# Then feed it to conda however you need,
# BUT remember that the next command to run after your profile script will be the "Set-Location" above
$ExplorerPath
C:\temp

Selenium crashing (chrome & firefox) within a flask route on ubuntu 20.04

Running Ubuntu 20.04 LTS server
Trying to save a screenshot via selenium within a flask route.
Issue is no matter what I try it crashes.
Using --headless
#api.route('/image/<path:encoded_url>.png')
def generate_image(encoded_url):
"""
Returns an image (PNG) of a URL. The URL is encoded in the path of the image being requested.
"""
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.headless = True
options.add_argument("--disable-gpu")
options.add_argument("--disable-dev-shm-using")
driver = webdriver.Chrome(f"{os.getcwd()}/chromedriver", options=options)
url = urllib.parse.unquote_plus(encoded_url)
driver.get(url if "http" in url else "https://" + url)
driver.set_window_size(1200, 630)
while True:
x = driver.execute_script("return document.readyState")
if x == "complete":
break
driver.save_screenshot("screen.png")
driver.close()
return send_file("screen.png", mimetype='image/png')
I've tried everything but firefox exits with error 127 (not much online regarding this)
selenium.common.exceptions.WebDriverException: Message: Process unexpectedly closed with status 127
I've tried running with Xvfb with no luck.
Ok, so after trying a whole load of options it turns out the issue was with my setup of gunicorn.
go to
cd /etc/systemd/system/
open the service you made for guinocorn
sudo nano {servicename}
The issue was the Environment line
Originally I has it as this:
Environment="PATH=/home/ubuntu/retrotex/environment/bin"
But once I changed it to the below everything worked:
Environment="PATH=/home/ubuntu/retrotex/environment/bin:/usr/bin:/bin"
It seems that flask didn't have access to the folders needed to run chome or selenium.
Make sure you run the below to reload the service after
sudo systemctl daemon-reload
sudo systemctl restart {service_name}
What a waste of a day.

how to execute remote python to open a web on remote machine by using a command on a local machine

I've been searching on net for a long time but I still don't get the answer.
Let me give an examle to describe my question more clearly:
machine A(local) is now conneted with machine B(remote).ALL I WANT TO DO is to :
run a command on A(local),then stop and wait ,and do nothing,and then,a web page is opened on B(remote) automatically.
P.S this python program is stored on machine B.
Here's what I've achived by now:
This is my python program named test.py,and it is stored on B under /home/pi/Documents:
import webbrowser
webbrowser.open('http://www.google.com')
On A,I used command:
ssh <username of B>#<ip of B> python /home/pi/Documents/test.py
After running the above command on A,there is no errors on A but also no action on B.
if I change the command into creating a file on B or sudo reboot,then after running this command there will be a file on B created or B is shut down successfully.
if I change the python program into printing something,like:
print("hello from B")
the content is magically printed on A's terminal.
It seems this command does not work well if I want to open a web on B or print somthing on B.
Can anyone help me with this or is there any other way to accomplish it?
helpless..
Someone has any ideas please???
Thanks in advance!
Assuming B is a Linux or Unix-like system, you have a DISPLAY problem. The webbrowser module locates a browser on the machine, and tries to open it on current display. It works when you launch it localy, but a ssh session has by default no configured display, so any attempt to launch a XWindow (GUI) application will fail.
The rationale behind it is that the -X and -Y flags of the ssh command allow to pass the client display to the server and open the window on the local screen (in your example on A). So if the permissions of the X servers on A and B are compatible, you could try:
A$ ssh -Y <username of B>#<ip of B> # open an interactive shell on B
B$ echo $DISPLAY # control the DISPLAY env variable
-> localhost:10.0 # common value for ssh transported DISPLAY
B$ python /home/pi/Documents/test.py # open the window on A
To force the opening on B, you could set the DISPLAY to localhost:0.0 (primary XWindow)
A$ ssh ssh <username of B>#<ip of B> # open an interactive shell on B
B$ DISPLAY = localhost:0.0 # sets the DISPLAY env variable
B$ export DISPLAY
B$ python /home/pi/Documents/test.py # open the window on B
You might need to tweek authorization of the XWindow servers (or use the awful xhost +) on A and/or B to make the above examples work
Once you have been able to successfully open a window on the proper screen, you will just have to set the DISPLAY environment variable to the correct value in your Python script before opening the browser window.
One of the simplest solutions is to use redirect of stdin
$ ssh pi#B python <<EOF
> print "Hello World from B"
> EOF
Hello World from B
$
However, if the script is quite big, it is better to copy py file to server B and then call ssh with the file name as #Eliethesaiyan suggested.
$ scp X.py pi#B:/home/pi/
X.py 100% 26 0.0KB/s 00:00
$ ssh pi#B python X.py
Hello World from B
$
I've tested this using a VM running Ubuntu, which OS are you running on your remote system? Here's my launch_google.py:
import os
os.environ["DISPLAY"] = ":0"
import webbrowser
webbrowser.open("https://google.com")
Launch this using:
ssh <user>#<IP Address> "python launch_google.py&"
I included the ampersand otherwise the ssh session remains open. The python process doesn't need to keep running.
It is important to set the DISPLAY environment variable before importing the webbrowser module, otherwise the browsers won't be setup correctly. You can verify this running python via SSH:
>>> import os
>>> "DISPLAY" in os.environ
False
>>> import webbrowser
>>> len(webbrowser._browsers)
0
>>> webbrowser.open("https://google.com")
False
>>> os.environ["DISPLAY"] = ":0"
>>> reload(webbrowser)
<module 'webbrowser' from '/usr/lib/python2.7/webbrowser.pyc'>
>>> len(webbrowser._browsers)
3
>>> webbrowser.open("https://google.com")
True
>>>

How to fix Selenium WebDriverException: The browser appears to have exited before we could connect?

I have installed firefox and Xvfb on my centos6.4 server to use selenium webdriver.
But, when I run the code, I got an error.
from selenium import webdriver
browser = webdriver.Firefox()
Error
selenium.common.exceptions.WebDriverException: Message:
'The browser appears to have exited before we could connect. The output was: None'
I read some related pages on stackoverflow and someone suggested to remove all files in tmp folder, so I did it. But, it still doesn't work.
Could anyone please give me a help?
Thank you in advance!
Edit
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.4/site-packages/selenium/webdriver/firefox/webdriver.py", line 59, in __init__
self.binary, timeout),
File "/usr/local/lib/python3.4/site-packages/selenium/webdriver/firefox/extension_connection.py", line 47, in __init__
self.binary.launch_browser(self.profile)
File "/usr/local/lib/python3.4/site-packages/selenium/webdriver/firefox/firefox_binary.py", line 64, in launch_browser
self._wait_until_connectable()
File "/usr/local/lib/python3.4/site-packages/selenium/webdriver/firefox/firefox_binary.py", line 103, in _wait_until_connectable
self._get_firefox_output())
selenium.common.exceptions.WebDriverException: Message: 'The browser appears to have exited before we could connect. The output was: None'
for Googlers, this answer didn't work for me, and I had to use this answer instead. I am using AWS Ubuntu.
Basically, I needed to install Xvfb and then pyvirtualdisplay:
sudo apt-get install xvfb
sudo pip install pyvirtualdisplay
Once I had done that, this python code worked:
#!/usr/bin/env python
from pyvirtualdisplay import Display
from selenium import webdriver
display = Display(visible=0, size=(1024, 768))
display.start()
browser = webdriver.Firefox()
browser.get('http://www.ubuntu.com/')
print browser.page_source
browser.close()
display.stop()
Thanks to #That1Guy for the first answer
I was running into this on an (headless) Ubuntu 14.04 server with Jenkins and xvfb installed. I had installed the latest stable Firefox (47) which started a build failing that ran a python script which used the Firefox driver for selenium (version 2.53).
Apparently Firefox 47+ is not compatible with the driver used in Selenium 2.53, and Selenium 3+ will be using a new driver called "Marionette" or "Gecko Driver" (which isn't officially released yet).
This page explains how to use the new driver pretty well, in several languages: https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/WebDriver
Basically:
get/build the executable from the project on github: https://github.com/mozilla/geckodriver/releases (and make sure it's perms are set to be executable, IE chmod a+x /path/to/geckdriver-executable)
rename/copy binary to "wires"
make sure the binary's location is added to the PATH that the build uses when executing the selenium test
update the selenium test to use the new driver
For Python, step 4 looked something like the following for me:
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
firefox_capabilities = DesiredCapabilities.FIREFOX
firefox_capabilities['marionette'] = True
firefox_capabilities['binary'] = '/usr/bin/firefox'
driver = webdriver.Firefox(capabilities=firefox_capabilities)
I too had faced same problem. I was on Firefox 47 and Selenium 2.53; I downgraded Firefox to 45. This worked.
Remove Firefox 47 first :
sudo apt-get purge firefox
Check for available versions:
apt-cache show firefox | grep Version
It will show available firefox versions like:
Version: 47.0+build3-0ubuntu0.16.04.1
Version: 45.0.2+build1-0ubuntu1
Install a specific version
sudo apt-get install firefox=45.0.2+build1-0ubuntu1
Next you have to not upgrade to the newer version again.
sudo apt-mark hold firefox
If you want to upgrade later
sudo apt-mark unhold firefox
sudo apt-get upgrade
Check your DISPLAY environment variable. Run echo $DISPLAY in the command line.
If nothing is printed, then you are running FireFox without any DISPLAY assigned. You should assign one! Run export DISPLAY=:1 in the command line before running your python script.
Check this thread for more information: http://hashcat.net/forum/thread-1973.html
I think the simplest solution here is just run Python with xvfb-run:
sudo apt-get install xvfb
xvfb-run python <your_file_or_args>
Rollback your Firefox to the previous working version. I suggest 2 versions back. Disable Firefox Maintenance Service.
I was working on a solution and the Firefox Maintenance Service updated Firefox to the latest build in the background. This broke my code and it was giving me this error.
Now it is fixed!
Thank you everyone!
This error is due to your Xvfb is not running. So restart your xvfb:
Xvfb :99 -ac
then check.
This works for me.
Instead of downgrading firefox from 47 version to 45 or something I'll suggest to upgrade to 47.0.1 or above since they seem to fix an issue.
But if your OS doesn't have new packages in repo (for example Ubuntu 14.04 in time of this answer), you can use debs from ubuntuzilla project:
wget sourceforge.net/projects/ubuntuzilla/files/mozilla/apt/pool/main/f/firefox-mozilla-build/firefox-mozilla-build_47.0.1-0ubuntu1_amd64.deb
sudo dpkg -i firefox-mozilla-build_47.0.1-0ubuntu1_amd64.deb
For x86 use _i386.deb postfix.
That sold problem for me
I fixed this by running a recursive chown against not only the python script using selenium, but against the entire virtualenv that script was running in. I changed the ownership to the user running the file. After that, this error went away.
I also faced the same issue, what I did was:
Upgrade selenium package
sudo pip install -U selenium
Instead of rolling back to older version(like suggested) I rolled up to newer version(48.0, I was previously using V47.0).
(for upgrading follow the instructions given by Toby Speight but instead of choosing older version choose newer version)
I found this solution on Windows 10 Build 18363. I had to call out specifically the Firefoxbinary and the geckdriver executable path.
from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
caps = DesiredCapabilities.FIREFOX.copy()
caps['marionette'] = True
# Path to Firefox binary
binary = FirefoxBinary(r'C:\Program Files\Mozilla Firefox\firefox.exe')
# Browser (driver) binary assigned, capabilities, and executable path for the geckodriver
driver = webdriver.Firefox(firefox_binary=binary, capabilities=caps,
executable_path=r'C:\Users\<name>\python\python-projects\geckodriver-v0.28.0-win64\geckodriver.exe')
# get google.co.in
driver.get("https://google.com")
update your selenuim version ---> pip install -U selenium
It can be solved by changing the file permission of the output file ( or related files to the program).
I used Firefox's webdriver.
Try:
chmod -R 777 output_file
This solved me the same trouble you have.

How can I disable web security in selenium through Python?

Apparently it's common for google-chrome to get this: http://jira.openqa.org/browse/SRC-740
The key is to start it without security enabled. To disable security,
"--disable-web-security",
I'm having trouble wondering how to actually specify these command line arguments, though, so it fails on the open invocation here:
from selenium import selenium
sel = selenium('localhost', 4444, '*googlechrome', 'http://www.google.com/')
sel.start()
sel.open('/')
Here's how I start the selenium server:
shogun#box:~$ java -jar selenium-server-standalone-2.0b3.jar
To get this to work, I had to create an external script to wrap the chrome browser. Place a script somewhere your Selenium server can reach it (mine is at ~/bin/startchrome, and chmod it executable:
#!/bin/sh
# chrome expects to be run from the .app dir, so cd into it
# (the spaces in the path are a Mac thing)
cd /Applications/Google\ Chrome.app
exec ./Contents/MacOS/Google\ Chrome --disable-security $*
Then in your Python code, do this:
from selenium import selenium
browser = '*googlechrome /Users/pat/bin/startchrome'
sel = selenium('localhost', 4444, browser, 'http://www.google.com')
sel.start()
sel.open('/')

Categories

Resources