fix: 增强导出下载诊断能力,缩短超时时间
下载超时从 300s 减至 120s,失败时自动保存截图、打印服务端响应内容、 检查页面错误提示和新标签页,便于定位 download 事件未触发的根因。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+89
-14
@@ -159,10 +159,11 @@ class SecsionDownloader:
|
||||
|
||||
await asyncio.sleep(3)
|
||||
|
||||
# 如果配置了 shop_id,拦截导出请求注入 shop_id
|
||||
if self.shop_id:
|
||||
import json
|
||||
# 如果配置了 shop_id,拦截导出请求注入 shop_id,并捕获服务端响应
|
||||
import json
|
||||
export_response = {'status': None, 'body': None, 'content_type': None}
|
||||
|
||||
if self.shop_id:
|
||||
async def inject_shop_id(route):
|
||||
request = route.request
|
||||
body = json.loads(request.post_data)
|
||||
@@ -173,18 +174,92 @@ class SecsionDownloader:
|
||||
await page.route('**/api/bill/export', inject_shop_id)
|
||||
logger.info(f"已设置 shop_id 拦截: {self.shop_id}")
|
||||
|
||||
# 点击导出报表并捕获下载(Docker 中增加超时到300秒)
|
||||
logger.info("点击导出报表...")
|
||||
async with page.expect_download(timeout=300000) as download_info:
|
||||
await export_btn.click()
|
||||
logger.info("等待文件下载中...")
|
||||
# 捕获导出接口的响应(用于调试)
|
||||
async def on_response(response):
|
||||
if '/api/bill/export' in response.url:
|
||||
export_response['status'] = response.status
|
||||
export_response['content_type'] = response.headers.get('content-type', '')
|
||||
try:
|
||||
body = await response.text()
|
||||
export_response['body'] = body[:2000] if body else ''
|
||||
except Exception:
|
||||
export_response['body'] = '(binary or empty)'
|
||||
logger.info(f"导出接口响应: status={response.status}, content-type={export_response['content_type']}, body长度={len(export_response['body'] or '')}")
|
||||
|
||||
download = await download_info.value
|
||||
filename = download.suggested_filename
|
||||
save_path = os.path.join(self.download_dir, filename)
|
||||
await download.save_as(save_path)
|
||||
logger.info(f"报表已保存至: {save_path}")
|
||||
return save_path
|
||||
page.on("response", on_response)
|
||||
|
||||
# 点击导出报表并捕获下载
|
||||
logger.info("点击导出报表...")
|
||||
download_timeout = 120000 # 2 分钟
|
||||
|
||||
try:
|
||||
async with page.expect_download(timeout=download_timeout) as download_info:
|
||||
await export_btn.click()
|
||||
logger.info("等待文件下载中...")
|
||||
|
||||
download = await download_info.value
|
||||
filename = download.suggested_filename
|
||||
save_path = os.path.join(self.download_dir, filename)
|
||||
await download.save_as(save_path)
|
||||
logger.info(f"报表已保存至: {save_path}")
|
||||
return save_path
|
||||
|
||||
except Exception as download_err:
|
||||
# 下载事件未触发,进行诊断
|
||||
logger.warning(f"下载事件捕获失败: {download_err}")
|
||||
|
||||
# 保存调试截图
|
||||
try:
|
||||
screenshot_path = os.path.join(self.download_dir, f"debug_export_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png")
|
||||
await page.screenshot(path=screenshot_path, full_page=True)
|
||||
logger.info(f"调试截图已保存: {screenshot_path}")
|
||||
except Exception as ss_err:
|
||||
logger.warning(f"截图保存失败: {ss_err}")
|
||||
|
||||
# 打印捕获到的响应信息
|
||||
if export_response['status']:
|
||||
logger.info(f"服务端实际响应: status={export_response['status']}, content-type={export_response['content_type']}")
|
||||
if export_response['body']:
|
||||
logger.info(f"响应内容(前500字): {export_response['body'][:500]}")
|
||||
else:
|
||||
logger.warning("未捕获到 /api/bill/export 响应,可能是请求被拦截或未发出")
|
||||
|
||||
# 检查页面是否有错误提示
|
||||
try:
|
||||
error_text = await page.evaluate("""() => {
|
||||
const msgs = document.querySelectorAll('.t-message--error, .t-notification--error, [class*="error"], .el-message--error');
|
||||
return Array.from(msgs).map(el => el.textContent.trim()).filter(Boolean).join(' | ');
|
||||
}""")
|
||||
if error_text:
|
||||
logger.error(f"页面错误提示: {error_text}")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 检查是否有新打开的标签页(某些网站通过 window.open 下载)
|
||||
try:
|
||||
pages = page.context.pages
|
||||
if len(pages) > 1:
|
||||
logger.info(f"检测到 {len(pages)} 个标签页,检查新标签页...")
|
||||
for p in pages[1:]:
|
||||
url = p.url
|
||||
logger.info(f"新标签页 URL: {url}")
|
||||
if url.startswith('blob:') or 'download' in url.lower() or 'export' in url.lower():
|
||||
# 尝试从新标签页下载
|
||||
try:
|
||||
async with p.expect_download(timeout=30000) as dl_info:
|
||||
pass
|
||||
download = await dl_info.value
|
||||
filename = download.suggested_filename
|
||||
save_path = os.path.join(self.download_dir, filename)
|
||||
await download.save_as(save_path)
|
||||
logger.info(f"从新标签页下载成功: {save_path}")
|
||||
return save_path
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
raise
|
||||
|
||||
async def _set_date(self, page, input_box, date_str):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user