如何解决在 AWS Lambda 上而不是在 EC2 问题我尝试过的我的猜测
问题
我一直尝试在 AWS Lambda 上使用 Firefox 运行 Selenium,但在 AWS Lambda 上运行我的代码时一直收到以下错误。但是,当我在 EC2 实例上运行时,Dockerfile 按预期成功运行(访问 google.com)。我正在运行 Firefox 60.9.0 ESR、Selenium 3.141.0、python3.8 和 Geckodriver 29。
Traceback (most recent call last):
File "/var/task/app.py",line 21,in handler
res = test.testGet()
File "/var/task/test.py",line 39,in testGet
driver = create_session_proxy("placeholder")
File "/var/task/test.py",line 27,in create_session_proxy
driver = webdriver.Firefox(profile,firefox_binary=firefox_path,executable_path=geckodriver_path,service_log_path=geckolog_path)
File "/var/lang/lib/python3.8/site-packages/selenium/webdriver/firefox/webdriver.py",line 170,in __init__
RemoteWebDriver.__init__(
File "/var/lang/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py",line 157,in __init__
self.start_session(capabilities,browser_profile)
File "/var/lang/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py",line 252,in start_session
response = self.execute(Command.NEW_SESSION,parameters)
File "/var/lang/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py",line 321,in execute
self.error_handler.check_response(response)
File "/var/lang/lib/python3.8/site-packages/selenium/webdriver/remote/errorhandler.py",line 242,in check_response
raise exception_class(message,screen,stacktrace)
selenium.common.exceptions.WebDriverException: Message: Process unexpectedly closed with status signal
...
Duration: 2534.59 ms Billed Duration: 3615 ms Memory Size: 4096 MB Max Memory Used: 419 MB Init Duration: 1079.94 ms
在我的 geckodriver 日志中,这是输出。有趣的是,有时我会在一次运行中多次收到此错误,但并非总是如此。
1626910798772\tgeckodriver\tINFO\tListening on 127.0.0.1:40439
1626910798785\tmozrunner::runner\tINFO\tRunning command: \"/tmp/firefox/firefox-bin\" \"--marionette\" \"-foreground\" \"-no-remote\" \"-profile\" \"/tmp/rust_mozprofileFhPiVM\"
ExceptionHandler::GenerateDump cloned child 30
ExceptionHandler::WaitForContinueSignal waiting for continue signal...
ExceptionHandler::SendContinueSignaltochild sent continue signal to child
这是我的 Dockerfile 的样子:
FROM public.ecr.aws/lambda/python:3.8
yum update -y
# Create function directory
workdir /app
# Install the function's dependencies
copY requirements.txt .
RUN pip install -r requirements.txt
RUN yum -y install Xvfb
RUN yum -y install gtk3
RUN yum -y install dbus-glib
# copy handler function (from the local app directory)
copY . ${LAMBDA_TASK_ROOT}
# Overwrite the command by providing a different command directly in the template.
CMD ["app.handler"]
这是 test.py 的代码:
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
import time
import random
import pickle
from selenium.webdriver.common.proxy import Proxy,ProxyType
from selenium.webdriver.support.ui import webdriverwait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
def create_session_proxy(ip_address):
options = Options()
options.headless = True
profile = webdriver.FirefoxProfile()
# Creates webdriver
LAMBDA_TASK_ROOT = os.environ.get('LAMBDA_TASK_ROOT')
geckodriver_path = '/tmp/geckodriver'
geckolog_path = '/tmp/geckodriver.log'
firefox_path = '/tmp/firefox/firefox-bin'
driver = webdriver.Firefox(profile,service_log_path=geckolog_path)
time.sleep(2)
driver.get('https://google.com')
return driver
def testGet():
display = display(visible=0,size=(1024,768))
display.start()
driver = create_session_proxy("placeholder")
time.sleep(2)
source = driver.page_source
driver.close()
return source
app.py 的代码(入口点):
import sys
import test
import os
import shutil
import time
import traceback
def handler(event,context):
# Moves files into tmp to run
start = time.time()
LAMBDA_TASK_ROOT = os.environ.get('LAMBDA_TASK_ROOT')
if not os.path.isfile("/tmp/geckodriver"):
shutil.copy(LAMBDA_TASK_ROOT + "/geckodriver","/tmp/")
if not os.path.isfile("/tmp/geckodriver.log"):
shutil.copy(LAMBDA_TASK_ROOT + "/geckodriver.log","/tmp/")
if not os.path.isdir("/tmp/firefox/"):
shutil.copytree(LAMBDA_TASK_ROOT + "/firefox/","/tmp/firefox/")
print("Time elapsed:",time.time() - start)
try:
res = test.testGet()
except:
traceback.print_exc()
error_log_text = open('/tmp/geckodriver.log').read()
return error_log_text
return 'Hello from AWS Lambda using Python' + sys.version + '!' + res
我尝试过的
- 在 Firefox 版本 66.0.5、52.9.0ESR 和 60.0.1ESR 上运行(没有区别)
- 改变 geckodriver 版本(17.0 和 29.0)和 Selenium 版本(没有区别)
- 使用 firefox/firefox 和 firefox/firefox-bin 作为可执行文件(没有区别)
我知道 Lambda 会在重新启动时删除 /tmp 文件夹,并且除了 /tmp 之外,文件系统是只读的(在 Lambda 上)。我正在将 Firefox 和 Geckodriver 可执行文件复制到 /tmp,因此问题与无法找到这两个文件无关。
我还在为 Firefox 和 Geckodriver 使用 Linux 64 位版本,所以这不是问题。
我的猜测
我应该注意,虽然我知道基础知识,但我对 Docker 并不是很有经验。
我的主要想法是,它是在 Lambda 的幕后发生的事情,并且它可能与 pyvirtualdisplay(运行 Firefox 需要它)有关。不过,其他人已经成功地在 Lambda 上运行 Selenium,所以我不确定这就是问题所在。对于pyvirtualdisplay,我安装在requirements.txt中,所以安装了,但是我想知道EC2上是否设置了一些默认情况下不在Lambda上的环境变量。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。