使用nodriver实现DOM动态等待,解决页面重定向引发的爬虫崩溃问题
解决nodriver爬虫多次重定向崩溃及页面完全加载的动态等待方案
针对多次重定向导致程序崩溃的问题,核心是在每次导航完成后确保页面完全加载再执行后续逻辑,以下是几种实用的动态等待实现方式:
基础等待:页面状态完成
等待浏览器的document.readyState变为complete,这是判断页面基本资源加载完成的标准方法:
from nodriver import Tab async def wait_for_page_ready(tab: Tab): await tab.wait_for(lambda tab: tab.evaluate("document.readyState === 'complete'"))
定向等待:目标元素出现
如果已知最终页面的标志性元素(比如特定按钮、容器),可以直接等待该元素加载,确保页面核心内容就绪:
async def wait_for_target_element(tab: Tab, css_selector: str, timeout: int = 30_000): # 等待元素出现,超时时间设为30秒 await tab.wait_for_selector(css_selector, timeout=timeout)
重定向专属处理:监听导航事件
针对多次重定向场景,可以监听页面导航事件,直到重定向停止后再等待页面加载:
from nodriver import Tab import asyncio async def handle_redirects(tab: Tab, max_redirects: int = 5): redirect_counter = 0 final_navigation = asyncio.Event() async def track_navigation(event): nonlocal redirect_counter redirect_counter += 1 # 达到最大重定向次数或当前URL稳定时,标记导航完成 if redirect_counter >= max_redirects or event.url == tab.url: final_navigation.set() # 绑定导航监听事件 tab.on_navigation(track_navigation) await final_navigation.wait() # 导航结束后再等待页面完全就绪 await wait_for_page_ready(tab)
进阶:等待网络空闲
如果页面存在大量异步请求(比如Ajax加载数据),可以等待网络请求完全空闲一段时间,确保动态内容加载完毕:
async def wait_for_network_idle(tab: Tab, idle_duration: int = 2000): # 等待2秒内没有新的网络请求 await tab.wait_for(lambda tab: tab.network.is_idle(idle_duration))
综合使用示例
将上述方法结合,处理重定向并确保页面完全加载:
async def main(): from nodriver import start browser = await start() tab = await browser.new_tab() # 打开目标页面 await tab.goto("https://example.com/redirect-heavy-page") # 处理重定向并等待页面就绪 await handle_redirects(tab) # 若有动态内容,等待网络空闲 await wait_for_network_idle(tab) # 执行后续爬取逻辑 page_content = await tab.get_html() print(page_content) await browser.close() if __name__ == "__main__": import asyncio asyncio.run(main())
注意事项
- 合理设置超时时间,避免因页面异常导致程序无限等待
- 若目标网站重定向逻辑复杂,可适当调高
max_redirects数值 - 优先使用目标元素等待,比单纯等待页面状态更精准
内容的提问来源于stack exchange,提问作者Lucas Vasquez
相关产品推荐
相关产品推荐

