点击按钮后如何获取Scrapy-Playwright动态加载的新HTML内容?
解决Scrapy-Playwright无法获取PDF查看器动态内容的问题
问题核心
点击按钮打开PDF查看器后,networkidle状态可能在PDF文本层元素加载完成前就触发,导致获取的HTML仍是初始页面内容;部分网站的PDF查看器会用iframe承载内容,直接获取主页面内容会遗漏这部分动态渲染的文本。
修正方案
1. 等待目标元素加载完成
替换networkidle等待逻辑,直接等待PDF文本层元素div.page-text-layer出现,确保内容已实际渲染。
2. 处理iframe承载的PDF内容
部分网站会把PDF查看器放在iframe中,需要先切换到对应iframe才能获取内部的文本内容。
3. 优化超时与关闭逻辑
给元素等待添加超时设置,避免因网络延迟导致等待失败;确保内容获取完成后再关闭页面。
修正后的代码
import scrapy from scrapy_playwright.page import PageMethod from scrapy.selector import Selector class SchifferstadtSpider(scrapy.Spider): name = 'schifferstadt' def start_requests(self): url = 'https://schifferstadt.more-rubin1.de/meeting.php?id=ni_2022-01-147' yield scrapy.http.Request( url, callback=self.parse_sitzungen, meta=dict( playwright=True, playwright_include_page=True, playwright_page_methods=[PageMethod('wait_for_selector', 'div.tabs-details')], ), errback=self.errback_close_page, ) async def parse_sitzungen(self, response): page = response.meta["playwright_page"] # 点击按钮打开PDF查看器 await page.get_by_role("button", name="Bekanntmachung").click() # 等待PDF文本层元素加载,设置10秒超时 await page.wait_for_selector("div.page-text-layer", timeout=10000) # 检测是否存在承载PDF的iframe,有则切换到iframe内部 iframe = page.locator("iframe[src*='pdf']").first if await iframe.count() > 0: await iframe.wait_for() pdf_frame = await iframe.content_frame() html = await pdf_frame.content() else: # 无iframe则直接获取当前页面内容 html = await page.content() html_selector = Selector(text=html) content = ' '.join(html_selector.xpath("//div[@class='page-text-layer']/span/text()").getall()) # 关闭查看器和页面 await page.locator(".file-viewer-modal-document-close-button").click() await page.close() yield {'content': content} async def errback_close_page(self, failure): page = failure.request.meta["playwright_page"] await page.close()
关键修改说明
- 精准等待:用
wait_for_selector("div.page-text-layer")替代networkidle,确保PDF文本已渲染完成,而非仅网络请求结束。 - iframe适配:增加iframe检测逻辑,针对网站的PDF承载方式切换上下文,避免遗漏iframe内的动态内容。
- 超时保护:给元素等待添加10秒超时,防止因网络波动导致程序无响应。
内容的提问来源于stack exchange,提问作者grobetrotter
相关产品推荐
相关产品推荐

