必须用 async with async_playwright() as p: 管理生命周期,否则因事件循环关闭导致 runtimeerror;浏览器、上下文、页面须在此块内创建销毁;page.goto() 后应配合 wait_until 或 wait_for_selector 确保页面就绪,避免截图失败。

async with async_playwright() 为什么必须用上下文管理器
直接调用 playwright.chromium.launch() 而不进 async with async_playwright() 会报 RuntimeError: Event loop is closed。Playwright 的 async API 不是简单加 await 就行,整个生命周期(包括浏览器进程、浏览器上下文、页面)都绑定在 playwright 实例的上下文中。
漏掉这层会导致后续所有 page.screenshot() 调用失败,且错误信息不直观——它可能表现为页面未加载完成就截图,或根本拿不到 page 对象。
- 必须写成
async with async_playwright() as p:,不能拆成两行手动await p.start()类操作 - 浏览器实例(
browser)、上下文(context)、页面(page)都应在该async with块内创建和销毁 - 若需并发多个页面,
context.new_page()比反复browser.new_page()更轻量,也更利于资源复用
page.goto() 后要不要 await page.wait_for_load_state()
大多数网页截图失败,其实不是截图函数的问题,而是页面还没真正“可用”就执行了 screenshot() —— 比如 JS 还在渲染首屏内容、字体未加载、动态广告占位符未替换。默认 page.goto(url) 只等 load 事件,但现代 SPA 页面常依赖 networkidle 或自定义 selector。
- 对静态页或 CMS 页面,
await page.goto(url, wait_until="networkidle")通常够用 - 对 React/Vue 应用,建议加一层
await page.wait_for_selector("main", timeout=10000),选一个你确认渲染完成的稳定容器 - 避免用
time.sleep():它不感知页面状态,既慢又不可靠;而wait_for_*系列方法带超时和重试,失败时抛明确异常(如TimeoutError),方便捕获处理
批量截图时如何避免内存泄漏和浏览器崩溃
一次性开 100 个 page 并发截图?大概率触发 Chromium 内存溢出或 Playwright 报 Target crashed。Playwright 的 async 模式下,并发控制不是靠 Python 的 asyncio.gather() 数量决定的,而是受浏览器上下文和进程资源限制。
- 单个
browser实例下,用context = await browser.new_context()创建上下文,再用context.new_page()开页面,比每个页面配独立 browser 轻得多 - 并发数建议 ≤ 5~10(取决于机器内存),用
asyncio.Semaphore(5)控制同时活跃的page数量 - 每截完一个图,立刻
await page.close();整个 batch 结束后await context.close(),否则 context 和 page 对象持续驻留内存 - 截图路径注意:Windows 下路径含中文或特殊字符易失败,推荐先
pathlib.Path(output_dir).mkdir(exist_ok=True),再用page.screenshot(path=str(p))
截图尺寸和裁剪怎么精准控制
page.screenshot() 默认截可视区(viewport),但很多需求要全页(full_page=True)或固定区域(clip=)。这两个参数行为差异大,容易混淆:
-
full_page=True会滚动并拼接,适合长文章页;但它无法截取 overflow:hidden 的弹窗或 fixed 定位遮罩层 -
clip={x:, y:, width:, height:}是像素坐标,原点在 viewport 左上角,不是 document;想截某个元素,得先await element.bounding_box()拿真实位置 - 如果页面缩放(zoom)非 100%,
clip坐标需按缩放比例换算,否则偏移;稳妥做法是截图前执行await page.evaluate("document.body.style.zoom = '1'") - 格式选
type="png"(默认);type="jpeg"不支持透明,且必须显式传quality=80,否则报错
page 真正“准备好了”再动手——等待逻辑写得松,截图就糊;并发控得死,机器就卡;路径或格式漏一个参数,整批就静默失败。这些点不体现在文档首页,但卡住你三小时。大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











