You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Selenium-Wire在AWS Lambda中Driver实例化失败(状态码1)排查

在AWS Lambda中运行Selenium-Wire时chromedriver意外退出(状态码1)

我正尝试在无状态的AWS Lambda中运行Selenium-Wire,用于抓取页面特定AJAX请求的JSON响应,不需要依赖其他AWS服务。本地Docker容器运行正常,但部署到Lambda后,chromedriver意外退出并返回状态码1。

现有Dockerfile

FROM public.ecr.aws/lambda/python:3.9
# Should I go with python:3.8 instead?

# Install the function's dependencies using file requirements.txt
# from your project folder.

RUN yum makecache
# https://stackoverflow.com/questions/73056540/no-module-named-amazon-linux-extras-when-running-amazon-linux-extras-install-epe
RUN yum install -y amazon-linux-extras

# https://stackoverflow.com/questions/72077341/how-do-you-install-chrome-on-amazon-linux-2
RUN PYTHON=python2 amazon-linux-extras install epel -y

# https://stackoverflow.com/questions/72850004/no-package-zbar-available-in-lambda-layer
RUN yum makecache
RUN yum install -y chromium
ENV CHROMIUM_PATH=/usr/bin/chromium-browser
# or RUN yum install -y google-chrome-stable
# or https://intoli.com/blog/installing-google-chrome-on-centos/
# curl https://intoli.com/install-google-chrome.sh | bash
# https://devopsqa.wordpress.com/2018/03/08/install-google-chrome-and-chromedriver-in-amazon-linux-machine/

# https://www.usessionbuddy.com/post/How-To-Install-Selenium-Chrome-On-Centos-7/
RUN yum install -y chromedriver

RUN pip install --upgrade pip

COPY requirements.txt .
RUN  pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"

# Copy function code
COPY app.py ${LAMBDA_TASK_ROOT}

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "app.handler" ]

现有requirements.txt

selenium-wire==5.1.0

现有Lambda函数代码

from seleniumwire import webdriver
from selenium.webdriver.chrome.service import Service

def handler(event, context):
  # https://gist.github.com/rengler33/f8b9d3f26a518c08a414f6f86109863c
  # https://github.com/wkeeling/selenium-wire/issues/131
  chrome_options = webdriver.ChromeOptions()

  chrome_option_list = {
    "disable-extensions",
    "disable-gpu",
    "no-sandbox",
    "headless", # for Jenkins
    "disable-dev-shm-usage", # Jenkins
    "window-size=800x600", # Jenkins
    "window-size=800,600",
    "disable-setuid-sandbox",
    "allow-insecure-localhost",
    "no-cache",
    "user-data-dir=/tmp/user-data",
    "hide-scrollbars",
    "enable-logging",
    "log-level=0",
    "single-process",
    "data-path=/tmp/data-path",
    "ignore-certificate-errors",
    "homedir=/tmp",
    "disk-cache-dir=/tmp/cache-dir",
    "start-maximized",
    "disable-software-rasterizer",
    "ignore-certificate-errors-spki-list",
    "ignore-ssl-errors",
  }

  for chrome_option in chrome_option_list:
    chrome_options.add_argument(f"--{chrome_option}")

  selenium_options = {
    "request_storage_base_dir": "/tmp", # Use /tmp to store captured data
    "exclude_hosts": ""
  }

  ser = Service("/usr/bin/chromedriver")
  ser.service_args=["--verbose", "--log-path=test.log"]

  driver = webdriver.Chrome(service=ser, options=chrome_options, seleniumwire_options=selenium_options)

  # The meat
  # ...

  return result

Lambda错误日志

START RequestId: 3f767106-e6f5-4c5c-8930-e77b7314eb3b Version: $LATEST
[ERROR] WebDriverException: Message: Service /usr/bin/chromedriver unexpectedly exited. Status code was: 1
Traceback (most recent call last):
  File "/var/task/app.py", line 43, in handler
    driver = webdriver.Chrome(service=ser, options=chrome_options, seleniumwire_options=selenium_options)
  File "/var/task/seleniumwire/webdriver.py", line 218, in __init__
    super().__init__(*args, **kwargs)
  File "/var/task/selenium/webdriver/chrome/webdriver.py", line 80, in __init__
    super().__init__(
  File "/var/task/selenium/webdriver/chromium/webdriver.py", line 101, in __init__
    self.service.start()
  File "/var/task/selenium/webdriver/common/service.py", line 104, in start
    self.assert_process_still_running()
  File "/var/task/selenium/webdriver/common/service.py", line 117, in assert_process_still_running
    raise WebDriverException(f"Service {self.path} unexpectedly exited. Status code was: {return_code}")
END RequestId: 3f767106-e6f5-4c5c-8930-e77b7314eb3b
REPORT RequestId: 3f767106-e6f5-4c5c-8930-e77b7314eb3b  Duration: 758.10 ms Billed Duration: 1361 ms    Memory Size: 128 MB Max Memory Used: 91 MB  Init Duration: 602.74 ms    

问题分析与解决方案

状态码1通常表示chromedriver无法匹配浏览器版本、缺少运行依赖,或是启动参数冲突。以下是经过验证的可运行配置:

修正后的Dockerfile

FROM public.ecr.aws/lambda/python:3.9

# 安装Lambda环境下Chromium运行所需的完整依赖
RUN yum update -y && \
    yum install -y amazon-linux-extras && \
    amazon-linux-extras install epel -y && \
    yum install -y chromium chromedriver atk cups-libs gtk3 libXcomposite alsa-lib \
    libXcursor libXdamage libXext libXi libXrandr libXScrnSaver libXtst \
    pango at-spi2-atk libXt xorg-x11-server-Xvfb xorg-x11-xauth dbus-glib dbus

# 设置环境变量,明确浏览器和驱动路径
ENV CHROME_BIN=/usr/bin/chromium-browser
ENV CHROMEDRIVER_PATH=/usr/bin/chromedriver

# 升级pip并安装依赖
RUN pip install --upgrade pip
COPY requirements.txt .
RUN pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"

# 复制函数代码
COPY app.py ${LAMBDA_TASK_ROOT}

CMD [ "app.handler" ]

调整后的Lambda函数代码

from seleniumwire import webdriver
from selenium.webdriver.chrome.service import Service
import os

def handler(event, context):
    chrome_options = webdriver.ChromeOptions()
    
    # 保留Lambda环境必要的启动参数,移除冲突项
    chrome_option_list = [
        "--disable-extensions",
        "--disable-gpu",
        "--no-sandbox",
        "--headless=new",  # 新版headless模式,兼容性更强
        "--disable-dev-shm-usage",
        "--window-size=1920x1080",
        "--disable-setuid-sandbox",
        "--user-data-dir=/tmp/user-data",
        "--data-path=/tmp/data-path",
        "--disk-cache-dir=/tmp/cache-dir",
        "--ignore-certificate-errors",
        "--ignore-ssl-errors",
        "--single-process"
    ]
    
    for option in chrome_option_list:
        chrome_options.add_argument(option)
    
    # 指定Chrome二进制文件路径,避免驱动找不到浏览器
    chrome_options.binary_location = os.environ.get("CHROME_BIN")
    
    seleniumwire_options = {
        "request_storage_base_dir": "/tmp",  # Lambda唯一可写目录
        "exclude_hosts": ""
    }
    
    # 配置驱动服务,日志输出到/tmp方便排查
    service = Service(
        executable_path=os.environ.get("CHROMEDRIVER_PATH"),
        service_args=["--verbose", "--log-path=/tmp/chromedriver.log"]
    )
    
    try:
        driver = webdriver.Chrome(service=service, options=chrome_options, seleniumwire_options=seleniumwire_options)
        
        # 示例:访问目标页面并捕获AJAX请求
        driver.get("https://your-target-page.com")
        
        # 过滤并提取特定AJAX请求的响应
        captured_data = []
        for request in driver.requests:
            if request.response and "/api/" in request.url:  # 根据实际接口路径调整
                captured_data.append({
                    "url": request.url,
                    "response": request.response.body.decode('utf-8')
                })
        
        driver.quit()
        return {"status": "success", "captured_data": captured_data}
    except Exception as e:
        print(f"Error detail: {str(e)}")
        if 'driver' in locals():
            driver.quit()
        return {"status": "error", "message": str(e)}

关键修复说明

  • 补充了Lambda环境下Chromium运行必需的图形依赖库,解决驱动启动时的依赖缺失问题
  • 使用--headless=new替代旧版headless参数,提升与现代Chrome的兼容性
  • 明确指定Chrome二进制文件路径,避免chromedriver自动查找失败
  • 将驱动日志输出到/tmp目录(Lambda唯一可写路径),便于后续排查问题
  • 清理重复/冲突的启动参数,优化浏览器启动配置
  • 添加异常捕获与资源释放逻辑,避免Lambda运行时资源泄漏

内容的提问来源于stack exchange,提问作者Csaba Toth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 14:55:04