使用crontab运行Selenium(python)
我有一个Python脚本,它通过Selenium来调用Chrome,代码是这样的:
ff = webdriver.Chrome('/home/user01/webScraping/CollectAndGo/chromedriver')
这个Python脚本是从一个Shell脚本中调用的。
python /home/user01/webScraping/CollectAndGo/cgcom.py > /home/user01/webScraping/CollectAndGo/cgcom.log 2>&1
当我从终端运行这个脚本或者直接执行.sh文件时,一切都很顺利,但当我设置一个定时任务(crontab)时,就出现了错误。
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: u'unknown error: Chrome failed to start: exited abnormally\n (Driver info: chromedriver=2.9.248304,platform=Linux 3.5.0-36-generic x86_64)'
这个错误和我提问的第一行代码有关。有没有人知道这可能是什么原因呢?
5 个回答
Crontab 可能是以一个没有权限访问 chromedriver 文件夹或文件的用户身份在运行。
可以看看 这里的回答,了解如何以特定用户身份运行 crontab。
Selenium网页驱动需要一个X会话来运行脚本。而定时任务(Cron脚本)通常是在没有X会话的情况下运行的。所以你需要在你的定时任务脚本中添加X会话。可以这样写:
* 11 * * * export DISPLAY=:0; your script.py
在MacOS Catalina上,只有这个命令对我有效。
* * * * * export DISPLAY=:0 && export PATH=$PATH:/usr/local/bin && /usr/bin/python3 ~/Documents/Scripts/my_script.py
使用 pyvirtualdisplay 和 Xvfb 来帮你管理窗口会话(这个方法最初来自 这个回答)
背景:
在我的情况下,之前的答案没有奏效。
解决方案:
- 安装 PyVirtualDisplay 和 Xvfb
pip3 install pyvirtualdisplay
sudo apt-get install xvfb
- 在你的
.py
脚本中分配窗口处理器
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from pyvirtualdisplay import Display
import time
# Display creates a virtual frame buffer and manages it for you
with Display(visible=False, size=(1200, 1500)):
driver = webdriver.Firefox()
driver.get("https://website-target.com")
time.sleep(1)
print(driver.current_url) # check connection
time.sleep(1)
print(driver.current_url)
driver.close()
从 cron
启动浏览器时,最明显的问题是即使你的机器上运行着 X 窗口系统,来自 crontab
的进程也没有设置 DISPLAY
环境变量,这样从那里启动浏览器就会失败。
解决方案有简单的,也有复杂的。简单的解决办法是接受如果没有 X 运行,脚本就不会执行,并手动将 DISPLAY
设置为 :0
,这是 Ubuntu 启动的默认 X 服务器的显示编号。
例如,如果我在 crontab
的 command
列中放入这个命令,Chrome 就能正常启动:
DISPLAY=:0 google-chrome
在用户特定的 crontab 文件中,完整的行可能是这样的:
0 * * * * DISPLAY=:0 google-chrome
如果你想运行一个通过 selenium 启动 Chrome 的 Python 脚本,那么这一行应该是:
0 * * * * DISPLAY=:0 python my_script.py
这个命令字符串会原封不动地发送给 shell,所以在最后一个例子中,字符串 DISPLAY=:0 python my_script.py
会直接传给 shell。常见的 shell 语法是将命令开头的变量赋值视为设置环境变量。(这对于 dash
和 bash
是成立的,这两者中大多数安装的默认 shell 可能是其中之一。)所以 shell 解释的命令会将环境变量 DISPLAY
设置为 :0
,然后运行 python my_script.py
。由于 python
从启动它的 shell 继承环境,因此对它来说,DISPLAY
变量也是 :0
。
像我上面展示的那样设置 DISPLAY=:0
只会为后面的命令设置这个变量。也可以将 DISPLAY
设置为 :0
,使 crontab 执行的所有命令都使用这个值。例如,在以下用户特定的 crontab 中:
DISPLAY=:0
30 * * * * google-chrome
0 * * * * python my_script.py
这一行 DISPLAY=:0
会为执行 google-chrome
和 python my_script.py
设置环境变量 DISPLAY
。