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
相关产品推荐
相关产品推荐

