Selenium PHP:Chrome无头模式下无法下载XLS文件
解决Chrome无头模式下点击无href链接无法下载XLS文件的问题
问题场景
- 点击无
href属性的链接,有头模式下会打开新标签页并启动下载,一切正常 - 无头模式下新标签页立即关闭,无法切换到新标签页完成下载
- 使用版本:Selenium 4.8.1,Chrome Driver 81.0.4044.138(无法升级版本)
当前配置
Chrome选项:
$chromeoptions = ["--headless", "--disable-gpu", "--window-size=1920,1200", "--ignore-certificate-errors", "--disable-extensions", "--no-sandbox", "--disable-dev-shm-usage", "--disable-popup-blocking"];
下载偏好设置:
$preferences = array( "download.prompt_for_download" => false, 'download.default_directory' => $this->downloadDirectoryPath, "directory_upgrade" => true, "credentials_enable_service" => false, "Browser.setDownloadBehaviour" => array( "behavior" => "allow", "downloadPath" => $this->downloadDirectoryPath ), "browser.helperApps.neverAsk.saveToDisk" => "application/vnd.ms-excel" );
可行解决方案(适配Chrome 81旧版本)
1. 修正Chrome无头模式参数,缩小与有头模式的差异
旧版Chrome的--headless引擎和有头模式逻辑差异较大,添加以下参数可以减少后台进程被回收的概率:
$chromeoptions = [ "--headless", "--disable-gpu", "--window-size=1920,1200", "--ignore-certificate-errors", "--disable-extensions", "--no-sandbox", "--disable-dev-shm-usage", "--disable-popup-blocking", // 新增参数 "--disable-background-timer-throttling", // 禁用后台定时器节流,防止标签页被主动关闭 "--disable-renderer-backgrounding", // 禁用渲染进程后台化,避免标签页被系统回收 "--enable-features=NetworkService,NetworkServiceInProcess", // 启用网络服务,优化下载流程 "--start-maximized" // 最大化窗口,避免布局差异导致的交互异常 ];
2. 修正下载偏好配置
Browser.setDownloadBehaviour是Selenium专属命令,不属于Chrome原生偏好,需要移除并改用正确的配置,同时补充完整的文件MIME类型:
$preferences = array( "download.prompt_for_download" => false, "download.default_directory" => $this->downloadDirectoryPath, "directory_upgrade" => true, "credentials_enable_service" => false, "browser.helperApps.neverAsk.saveToDisk" => "application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "download.directory_upgrade" => true, "plugins.always_open_pdf_externally" => true // 确保文件直接下载而非在浏览器内打开 );
另外,需要单独通过Selenium的CDP命令设置下载行为:
// 基于PHP Selenium绑定的示例代码 $driver->executeCdpCommand('Browser.setDownloadBehavior', [ 'behavior' => 'allow', 'downloadPath' => $this->downloadDirectoryPath ]);
3. 拦截网络请求,直接获取下载链接(绕过标签页问题)
如果上述方法无效,可以通过监听网络请求的方式,直接拿到XLS文件的真实下载地址,再用HTTP工具下载:
- 启用Chrome网络监听:
$driver->executeCdpCommand('Network.enable', []);
- 点击链接后监听下载请求:
$downloadUrl = null; // 注册响应监听事件 $driver->executeCdpCommand('Network.responseReceived', function($params) use (&$downloadUrl) { $mimeType = $params['response']['mimeType']; if (in_array($mimeType, ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'])) { $downloadUrl = $params['response']['url']; } }); // 触发点击操作 $driver->findElement(WebDriverBy::cssSelector('你的链接选择器'))->click(); // 获取链接后直接下载 if ($downloadUrl) { file_put_contents($this->downloadDirectoryPath . '/target.xls', file_get_contents($downloadUrl)); }
4. 修改链接行为,强制在当前标签页打开
通过JS修改链接的target属性,避免打开新标签页,从根源上解决新标签页被关闭的问题:
$link = $driver->findElement(WebDriverBy::cssSelector('你的链接选择器')); // 执行JS修改target属性为_self $driver->executeScript("arguments[0].setAttribute('target', '_self');", [$link]); // 再点击链接 $link->click();
同类问题说明
确实有不少用户在旧版本Chrome无头模式下遇到过类似的新标签页自动关闭、下载失败问题,核心原因是旧无头引擎的后台进程管理、渲染逻辑与有头模式差异较大,通过调整参数、修正配置或绕过浏览器下载的方式基本都能解决。
内容的提问来源于stack exchange,提问作者Rodeo Genius
相关产品推荐
相关产品推荐

