使用Playwright+Asyncio爬取RBI新闻时DOM元素脱离问题求解
解决Playwright爬取RBI官网时"Element is not attached to the DOM"错误
错误原因
页面跳转、刷新或局部渲染后,之前获取的DOM元素引用会失效——浏览器已重构DOM树,循环爬取时若复用初始获取的元素列表,后续循环就会触发该错误。
具体解决方法
1. 每次循环重新定位元素
不要提前缓存所有新闻元素,而是在每次循环开始时重新查询当前页面的目标元素,确保操作的是最新DOM节点:
import asyncio from playwright.async_api import async_playwright async def crawl_rbi_news(): async with async_playwright() as p: browser = await p.chromium.launch(headless=False) page = await browser.new_page() await page.goto("https://www.rbi.org.in/scripts/NewLinkDetails.aspx") while True: # 每次循环重新获取当前页面的新闻条目 await page.wait_for_selector(".table tr") news_items = await page.query_selector_all(".table tr") for item in news_items[1:]: # 跳过表头行 # 提取标题与日期 title_elem = await item.query_selector("td a") title = await title_elem.text_content() date = await item.query_selector("td:last-child").text_content() # 进入详情页,等待页面加载完成 await title_elem.click() await page.wait_for_load_state("networkidle") # 提取正文内容 content = await page.query_selector("#contentDiv").text_content() print(f"标题: {title}\n日期: {date}\n正文: {content[:200]}...\n") # 返回列表页,等待DOM稳定 await page.go_back() await page.wait_for_load_state("networkidle") # 检查并点击下一页 next_btn = await page.query_selector("a:has-text('Next')") if not next_btn: break await next_btn.click() await page.wait_for_load_state("networkidle") await browser.close() asyncio.run(crawl_rbi_news())
2. 核心避坑原则
- 绝不缓存元素对象,每次操作前通过选择器重新查询。
- 页面跳转/更新后,必须等待
networkidle或目标选择器出现,确保DOM稳定。 - 避免依赖全局元素引用,优先使用相对选择器定位目标节点。
内容的提问来源于stack exchange,提问作者kalin.klinkov
相关产品推荐
相关产品推荐

