使用Python Playwright批量下载PDF失败:仅下载1个即停止
问题分析与修复方案
脚本存在的核心问题
- DOM元素句柄失效:脚本一开始就一次性获取所有目标元素的句柄,但点击第一个下载链接后,页面会触发局部刷新或DOM重渲染,导致之前缓存的后续元素句柄直接失效,无法触发点击操作。
- 缺失状态等待逻辑:点击下载后未等待页面状态稳定,直接尝试操作下一个元素,容易遇到元素不可见、不可交互的情况,导致脚本中断。
- 硬编码会话ID:URL中硬编码的
jsessionid是临时会话标识,会随会话过期或页面跳转失效,可能导致后续请求异常。
修复后的脚本
from playwright.sync_api import sync_playwright with sync_playwright() as p: nav = p.chromium.launch(headless=False) page = nav.new_page(accept_downloads=True) # 移除硬编码的JSESSIONID,由浏览器自动维护会话 page.goto('https://www4.trf5.jus.br/diarioeletinternet/paginas/consultas/consultaDiario.faces') page.locator("[name='frmVisao:orgao']").select_option('SeçãoJudiciária do Sergipe') page.locator("[name='frmVisao:edicao']").select_option('Administrativo') page.locator("[name='frmVisao:periodo']").select_option('2021') page.wait_for_function(""" document.querySelectorAll('[id="frmVisao:meses"] option').length > 11 """) page.locator('[id="frmVisao:meses"]').select_option('03') page.locator('[id="frmVisao:j_id48"]').click() # 等待结果表格加载完成 page.wait_for_selector(".rich-table tbody tr") page.locator('[id="frmPesquisa:quantidadeRegistros"]').select_option('50') # 等待表格数据更新完成(可根据实际情况调整等待时长) page.wait_for_timeout(1000) # 获取下载链接总数量,使用动态定位避免DOM变化影响 download_links_count = page.locator(".rich-table tbody tr td:nth-child(4)").count() for i in range(download_links_count): # 每次循环重新定位当前元素,确保基于最新DOM节点操作 current_link = page.locator(f".rich-table tbody tr:nth-child({i+1}) td:nth-child(4)") # 等待元素可见且可交互 current_link.wait_for(state="visible") with page.expect_download() as download_info: current_link.click() download = download_info.value download.save_as(download.suggested_filename) # 等待下载完成或页面状态稳定,避免频繁操作触发反爬或异常 page.wait_for_timeout(500) page.close() nav.close()
关键修改说明
- 移除硬编码会话ID:让浏览器自动维护
jsessionid,避免会话过期导致的请求失败。 - 动态元素定位:每次循环都重新查询目标元素,确保操作的是最新的DOM节点,避免句柄失效问题。
- 添加状态等待:增加表格加载等待、元素可见等待、操作后缓冲等待,确保页面状态稳定后再执行下一步操作。
内容的提问来源于stack exchange,提问作者João Bosco
相关产品推荐
相关产品推荐

