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

AWS Ubuntu下PHP调用Python Selenium出现ReadTimeoutError的解决方法

问题:PHP调用Selenium脚本时出现ReadTimeoutError

在AWS Ubuntu环境中,命令行执行以下指令能成功运行带Selenium的Python脚本,完成网页访问和多媒体下载:

/usr/bin/python3.11 && /home/bitnami/spacy_venv/bin/python3.11 /home/bitnami/htdocs/android_app_selenium.py _2Qqa4ri7KQ

但通过PHP执行该脚本时,抛出ReadTimeoutError,错误详情如下:

Selenium test separated from obtainingyoutube_news

return_python_videoId: Starting Selenium test video_id: _2Qqa4ri7KQ video_id_yblink: https://www.youtube.com/watch?v=_2Qqa4ri7KQ 
Traceback (most recent call last): 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/urllib3/connectionpool.py", line 534, in _make_request 
response = conn.getresponse() 
^^^^^^^^^^^^^^^^^^ 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/urllib3/connection.py", line 571, in getresponse 
httplib_response = super().getresponse() 
^^^^^^^^^^^^^^^^^^^^ 
File "/usr/lib/python3.11/http/client.py", line 1394, in getresponse 
response.begin() 
File "/usr/lib/python3.11/http/client.py", line 323, in begin 
version, status, reason = self._read_status() 
^^^^^^^^^^^^^^^^^^ 
File "/usr/lib/python3.11/http/client.py", line 284, in _read_status 
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1") 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
File "/usr/lib/python3.11/socket.py", line 706, in readinto 
return self._sock.recv_into(b) 
^^^^^^^^^^^^^^^^^^^^^^^ 
TimeoutError: timed out 

The above exception was the direct cause of the following exception: 
Traceback (most recent call last): 
File "/home/bitnami/htdocs/android_app_selenium.py", line 79, in show_time() 
File "/home/bitnami/htdocs/android_app_selenium.py", line 31, in show_time 
driver = webdriver.Firefox(options=options) 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/selenium/webdriver/firefox/webdriver.py", line 69, in __init__ 
super().__init__(command_executor=executor, options=self.options) 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/selenium/webdriver/common/webdriver.py", line 25, in __init__ 
super().__init__(*args, **kwargs) 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py", line 276, in __init__ 
self.start_session(capabilities) 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py", line 372, in start_session 
response = self.execute(Command.NEW_SESSION, caps)["value"] 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py", line 465, in execute 
response = cast(RemoteConnection, self.command_executor).execute(driver_command, params) 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/selenium/webdriver/remote/remote_connection.py", line 407, in execute 
return self._request(command_info[0], url, body=data) 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/selenium/webdriver/remote/remote_connection.py", line 431, in _request 
response = self._conn.request(method, url, body=body, headers=headers, timeout=self._client_config.timeout) 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/urllib3/_request_methods.py", line 143, in request 
return self.request_encode_body( 
^^^^^^^^^^^^^^^^^^^^^^^^^ 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/urllib3/_request_methods.py", line 278, in request_encode_body 
return self.urlopen(method, url, **extra_kw) 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/urllib3/poolmanager.py", line 457, in urlopen 
response = conn.urlopen(method, u.request_uri, **kw) 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/urllib3/connectionpool.py", line 841, in urlopen 
retries = retries.increment( 
^^^^^^^^^^^^^^^^^^ 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/urllib3/util/retry.py", line 490, in increment 
raise reraise(type(error), error, _stacktrace) 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/urllib3/util/util.py", line 39, in reraise 
raise value 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/urllib3/connectionpool.py", line 787, in urlopen 
response = self._make_request( 
^^^^^^^^^^^^^^^^^^^ 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/urllib3/connectionpool.py", line 536, in _make_request 
self._raise_timeout(err=e, url=url, timeout_value=read_timeout) 
File "/home/bitnami/spacy_venv/lib/python3.11/site-packages/urllib3/connectionpool.py", line 367, in _raise_timeout 
raise ReadTimeoutError( 
urllib3.exceptions.ReadTimeoutError: HTTPConnectionPool(host='localhost', port=53487): Read timed out. (read timeout=120)

相关代码

Python脚本(android_app_selenium.py)

import sys
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
from selenium.webdriver.firefox.options import Options

os.environ["SE_CACHE_PATH"] = "/home/bitnami/htdocs/uploads/"

def show_time():
    textofinal = "Hola android_app_selenium"

    print("Iniciando prueba Selenium")

    print("video_id: ", sys.argv[1])
    print("video_id_yblink: ", "https://www.youtube.com/watch?v=" + sys.argv[1])

    options = Options()
    options.add_argument("--headless")

    driver = webdriver.Firefox(options=options)

    driver.get("https://media.ytmp3.gg/mx/youtube-to-wav-converter")

    print(driver.title)

    search_box = driver.find_element(By.ID, "videoUrl")
    print("search_box: ", search_box)

    search_box.clear()
    search_box.send_keys("https://www.youtube.com/watch?v=" + sys.argv[1])

    check_box = driver.find_element(By.XPATH, '//*[@id="copyright-consent-checkbox"]')
    print("check_box: ", check_box)
    check_box.click()

    time.sleep(12)

    button_download2 = driver.find_element(By.XPATH, '//*[@id="download-btn"]')

    print("button_download2: ", button_download2)
    button_download2.click()

    print("Terminando prueba Selenium")

    return textofinal

if __name__ == '__main__':
    show_time()

PHP调用脚本

<?php
    ini_set('display_errors', 1);
    echo 'Selenium test separada de obtainingyoutube_news'; echo "<br>";
    
    $return_python_videoId = shell_exec('/usr/bin/python3.11 && /home/bitnami/spacy_venv/bin/python3.11 /home/bitnami/htdocs/android_app_selenium.py _2Qqa4ri7KQ 2>&1'); 
    
    echo "return_python_videoId: ".$return_python_videoId; echo "<br>";

?>

解决方案

1. 简化Python执行命令

PHP中的命令存在冗余,直接使用虚拟环境的Python路径即可,避免环境变量混淆:

$return_python_videoId = shell_exec('/home/bitnami/spacy_venv/bin/python3.11 /home/bitnami/htdocs/android_app_selenium.py _2Qqa4ri7KQ 2>&1');

2. 修复Apache用户权限问题

PHP由www-data(bitnami环境通常为daemon)用户运行,和命令行的bitnami用户权限环境不同:

  • 给Web用户授权访问虚拟环境和脚本:
    sudo chown -R www-data:www-data /home/bitnami/spacy_venv/
    sudo chmod -R 755 /home/bitnami/spacy_venv/
    sudo chown www-data:www-data /home/bitnami/htdocs/android_app_selenium.py
    
  • 确保Firefox驱动(geckodriver)对Web用户可执行:
    sudo chmod +x /path/to/geckodriver
    sudo chown www-data:www-data /path/to/geckodriver
    

3. 完善无头模式配置

给Firefox添加更多无头模式参数,解决权限和资源限制问题:

options = Options()
options.add_argument("--headless")
options.add_argument("--no-sandbox")  # 禁用沙箱,绕过权限限制
options.add_argument("--disable-dev-shm-usage")  # 避免临时空间不足
options.add_argument("--disable-gpu")  # 无头模式无需GPU加速
options.add_argument("--window-size=1920,1080")  # 设置标准窗口尺寸,避免元素定位异常
options.set_preference("dom.disable_open_during_load", True)  # 禁止页面弹窗干扰

4. 增加Selenium超时控制

显式设置驱动连接和页面加载超时,避免默认超时过短:

from selenium.webdriver.firefox.service import Service

# 指定geckodriver路径(若未加入系统PATH)
service = Service(executable_path='/path/to/geckodriver')
driver = webdriver.Firefox(service=service, options=options)
driver.set_page_load_timeout(30)  # 页面加载超时设为30秒
driver.implicitly_wait(10)  # 元素定位隐式等待10秒

5. 替换固定等待为显式等待

用Selenium的显式等待替代time.sleep(12),提升可靠性并减少无效等待:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 等待下载按钮可点击后再执行操作
wait = WebDriverWait(driver, 20)
button_download2 = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="download-btn"]')))
button_download2.click()

6. 确保环境变量正确

在Python脚本中显式设置PATH,保证驱动能被找到:

os.environ["PATH"] += ":/path/to/directory/containing/geckodriver"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:22:03