fix: 全面增强 SSL 证书错误处理和弹窗监控
- 添加 --ignore-certificate-errors 浏览器级参数 - 注册 popup 事件处理器,监控导出触发的弹窗 - 弹窗出现时自动绕过 SSL 拦截 - 失败时遍历所有页面(主页面+弹窗+新标签页)进行 SSL 绕过和下载重试 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+35
-10
@@ -50,7 +50,8 @@ class SecsionDownloader:
|
|||||||
args=[
|
args=[
|
||||||
"--disable-dev-shm-usage",
|
"--disable-dev-shm-usage",
|
||||||
"--disable-gpu",
|
"--disable-gpu",
|
||||||
"--no-sandbox"
|
"--no-sandbox",
|
||||||
|
"--ignore-certificate-errors"
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
context = await browser.new_context(
|
context = await browser.new_context(
|
||||||
@@ -191,6 +192,18 @@ class SecsionDownloader:
|
|||||||
|
|
||||||
page.on("response", on_response)
|
page.on("response", on_response)
|
||||||
|
|
||||||
|
# 监控弹窗(导出可能在新窗口打开下载链接)
|
||||||
|
popup_pages = []
|
||||||
|
|
||||||
|
async def handle_popup(popup):
|
||||||
|
popup_pages.append(popup)
|
||||||
|
logger.info(f"检测到弹窗: {popup.url}")
|
||||||
|
# 弹窗的 SSL 拦截也要处理
|
||||||
|
await popup.wait_for_load_state("domcontentloaded", timeout=15000)
|
||||||
|
await self._bypass_ssl_interstitial(popup)
|
||||||
|
|
||||||
|
page.on("popup", handle_popup)
|
||||||
|
|
||||||
# 记录下载目录现有文件(用于兜底检测)
|
# 记录下载目录现有文件(用于兜底检测)
|
||||||
existing_files = set(os.listdir(self.download_dir)) if os.path.exists(self.download_dir) else set()
|
existing_files = set(os.listdir(self.download_dir)) if os.path.exists(self.download_dir) else set()
|
||||||
|
|
||||||
@@ -203,9 +216,16 @@ class SecsionDownloader:
|
|||||||
await export_btn.click()
|
await export_btn.click()
|
||||||
logger.info("等待文件下载中...")
|
logger.info("等待文件下载中...")
|
||||||
|
|
||||||
# 点击导出后,可能弹出 SSL 证书过期拦截页面
|
# 等待弹窗出现
|
||||||
|
await asyncio.sleep(2)
|
||||||
|
|
||||||
|
# 先处理主页面 SSL 拦截
|
||||||
await self._bypass_ssl_interstitial(page)
|
await self._bypass_ssl_interstitial(page)
|
||||||
|
|
||||||
|
# 再处理所有弹窗
|
||||||
|
for popup in popup_pages:
|
||||||
|
await self._bypass_ssl_interstitial(popup)
|
||||||
|
|
||||||
download = await download_info.value
|
download = await download_info.value
|
||||||
filename = download.suggested_filename
|
filename = download.suggested_filename
|
||||||
save_path = os.path.join(self.download_dir, filename)
|
save_path = os.path.join(self.download_dir, filename)
|
||||||
@@ -214,24 +234,29 @@ class SecsionDownloader:
|
|||||||
return save_path
|
return save_path
|
||||||
|
|
||||||
except Exception as download_err:
|
except Exception as download_err:
|
||||||
# Playwright download 事件未触发,尝试 SSL 绕过后再等
|
|
||||||
logger.warning(f"Playwright 下载事件捕获失败: {download_err}")
|
logger.warning(f"Playwright 下载事件捕获失败: {download_err}")
|
||||||
|
|
||||||
# 二次尝试:可能 SSL 页面刚出现,再尝试绕过
|
# 处理所有已知页面的 SSL 拦截
|
||||||
bypassed = await self._bypass_ssl_interstitial(page)
|
all_pages = [page] + popup_pages + [p for p in page.context.pages if p != page]
|
||||||
if bypassed:
|
for p in all_pages:
|
||||||
logger.info("SSL 拦截已绕过,等待下载...")
|
|
||||||
try:
|
try:
|
||||||
async with page.expect_download(timeout=30000) as dl_info:
|
await self._bypass_ssl_interstitial(p)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 绕过 SSL 后重新等待下载
|
||||||
|
for p in all_pages:
|
||||||
|
try:
|
||||||
|
async with p.expect_download(timeout=15000) as dl_info:
|
||||||
pass
|
pass
|
||||||
download = await dl_info.value
|
download = await dl_info.value
|
||||||
filename = download.suggested_filename
|
filename = download.suggested_filename
|
||||||
save_path = os.path.join(self.download_dir, filename)
|
save_path = os.path.join(self.download_dir, filename)
|
||||||
await download.save_as(save_path)
|
await download.save_as(save_path)
|
||||||
logger.info(f"SSL 绕过后下载成功: {save_path}")
|
logger.info(f"SSL 绕过后从页面下载成功: {save_path}")
|
||||||
return save_path
|
return save_path
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.warning("SSL 绕过后仍未触发下载事件")
|
continue
|
||||||
|
|
||||||
logger.info("尝试文件系统兜底检测...")
|
logger.info("尝试文件系统兜底检测...")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user