crawl4ai------AsyncPlaywrightCrawlerStrategy使用教程
AsyncPlaywrightCrawlerStrategy 使用教程(crawl4ai)
适用版本:crawl4ai==0.7.8
AsyncPlaywrightCrawlerStrategy 是 crawl4ai 默认的“抓取策略(Crawler Strategy)”之一:底层使用 Playwright 启动/连接浏览器,执行真实页面导航、渲染与 JS,然后把最终 HTML 返回给 crawl4ai 的后处理流程(抽取 Markdown、截图/PDF、提取链接等)。
如果你遇到以下场景,优先考虑使用它:
- 站点是 SPA/SSR 混合、内容需要 JS 执行后才能出现
- 需要登录态、Cookie、localStorage 等浏览器状态
- 需要做滚动加载(lazy load / infinite scroll)
- 需要截图、导出 PDF、抓取 mhtml、采集网络请求/控制台日志
0. crawl4ai 架构速览:Strategy 在哪里
在 crawl4ai 中,你通常会用 AsyncWebCrawler 作为入口:
AsyncWebCrawler:负责生命周期(start/close)、调度并发(arun_many)、缓存、HTML 后处理(markdown/抽取)。CrawlerRunConfig:一次抓取任务的配置(等待策略、截图、滚动、抓取网络等)。AsyncPlaywrightCrawlerStrategy:负责“怎么把 URL 变成 HTML”(也就是浏览器导航、等待、执行 JS、拿page.content())。BrowserConfig:浏览器/上下文级别配置(是否 headless、代理、UA、stealth、是否 text_mode 等)。
你可以:
- 直接用
AsyncWebCrawler(config=BrowserConfig(...))—— 默认就会用AsyncPlaywrightCrawlerStrategy - 或显式传入:
AsyncWebCrawler(crawler_strategy=AsyncPlaywrightCrawlerStrategy(...))
1. 环境准备(Playwright 必做)
1.1 安装 Python 包
pip install "crawl4ai==0.7.8" playwright
1.2 安装浏览器运行时
二选一即可:
# crawl4ai 提供的初始化命令(本仓库 crawl.py 也提到)
crawl4ai-setup
或直接用 Playwright:
playwright install chromium
建议:优先 chromium,兼容性最好。
2. 最小示例:用默认 AsyncPlaywrightCrawlerStrategy 抓一页
AsyncWebCrawler 默认就是 AsyncPlaywrightCrawlerStrategy,因此你只要提供 BrowserConfig + CrawlerRunConfig 即可:
import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig
async def main():
browser_cfg = BrowserConfig(
headless=True,
enable_stealth=True, # 可选:启用 stealth(基于 playwright_stealth)
light_mode=True, # 可选:轻量模式(少加载资源,通常更快)
)
run_cfg = CrawlerRunConfig(
wait_until="domcontentloaded", # 常用:domcontentloaded / load
page_timeout=60_000, # 单页超时(毫秒)
verbose=False,
)
async with AsyncWebCrawler(config=browser_cfg) as crawler:
result = await crawler.arun("https://example.com", config=run_cfg)
# result 是 CrawlResultContainer,可像 result.success/result.markdown 这样直接用(会代理到第一个结果)
print("success:", result.success)
print("url:", result.url)
print("html_len:", len(result.html or ""))
print("md_len:", len(result.markdown or ""))
if __name__ == "__main__":
asyncio.run(main())
3. BrowserConfig:浏览器/上下文级别配置(非常重要)
BrowserConfig 会影响浏览器如何启动、context 如何创建(代理、UA、headers、下载等)。这些配置通常在一个 crawler 生命周期内复用。
3.1 常用字段速查
下面只列最常用、最影响效果/性能的字段(更多字段可见 crawl4ai/async_configs.py 的注释):
headless:是否无头(默认 True)。调试时可设 False。browser_type:chromium/firefox/webkit(默认 chromium)。channel/chrome_channel:chromium 发行通道(如 chrome/msedge/chromium),仅对 chromium 有效。proxy_config:代理配置(推荐用这个,proxy字段已不推荐)。headers:全局请求头(对整个 context 生效)。cookies:启动后注入 cookies(全局)。storage_state:加载 Playwright storage_state(登录态/本地存储)。use_persistent_context+user_data_dir:使用持久化 profile(适合“长期登录态”)。enable_stealth:启用 stealth(非 undetected 模式下生效)。light_mode:轻量模式(减少加载资源/特性,通常更快、更省内存)。text_mode:文本模式(会拦截大量静态资源/图片等,适合只要正文的场景)。accept_downloads+downloads_path:允许并保存下载文件。
3.2 代理(proxy_config)
from crawl4ai import BrowserConfig, ProxyConfig
browser_cfg = BrowserConfig(
proxy_config=ProxyConfig.from_string("http://user:pass@host:port"),
)
说明:
proxy_config会在浏览器 context 层生效(更可靠)。- 如果你同时设置了
proxy和proxy_config,crawl4ai 会优先用proxy_config。
3.3 反爬:Stealth vs Undetected
在 crawl4ai 里常见有两种路线:
-
Stealth(推荐先试):
BrowserConfig(enable_stealth=True)→BrowserManager会使用StealthAdapter(基于playwright_stealth)对 page 做补丁。 -
Undetected(更强但依赖更多):
初始化AsyncPlaywrightCrawlerStrategy(browser_adapter=UndetectedAdapter())
→BrowserManager会切到patchright的 playwright 实现(更偏“反检测”)。
示例(Undetected):
import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig
from crawl4ai.async_crawler_strategy import AsyncPlaywrightCrawlerStrategy
from crawl4ai.browser_adapter import UndetectedAdapter
async def main():
browser_cfg = BrowserConfig(headless=True) # undetected 仍可 headless,但部分站点更偏好 headful
strategy = AsyncPlaywrightCrawlerStrategy(browser_config=browser_cfg, browser_adapter=UndetectedAdapter())
run_cfg = CrawlerRunConfig(verbose=False)
async with AsyncWebCrawler(crawler_strategy=strategy) as crawler:
result = await crawler.arun("https://example.com", config=run_cfg)
print(result.success, result.url)
asyncio.run(main())
经验建议:先用
enable_stealth=True,不行再上UndetectedAdapter(),并配合代理/合理 UA/等待策略。
3.4 连接已有 Chrome(CDP 模式)
当你希望复用一个已启动的浏览器(例如你自己打开 Chrome 登录后,再让爬虫接管),可以用 CDP:
- 启动 Chrome(示例):
chrome --remote-debugging-port=9222
- 让 crawl4ai 连接:
from crawl4ai import BrowserConfig
browser_cfg = BrowserConfig(
cdp_url="http://localhost:9222", # 注意:0.7.8 会访问 {cdp_url}/json/version 做探活
use_managed_browser=True,
headless=False, # 通常你本地 Chrome 是 headful
)
4. CrawlerRunConfig:一次抓取任务的配置(与 Playwright 强相关)
CrawlerRunConfig 是“每次请求”的配置,最影响页面等待、滚动、截图、网络抓取等行为。
下面按“你最常调的参数”分类说明(只列 Playwright 相关的核心项)。
4.1 导航与等待
wait_until:传给 Playwrightpage.goto(..., wait_until=...)
常见值:"domcontentloaded"、"load"(有些版本 Playwright 也支持"networkidle",但对长连接站点不友好)。page_timeout:传给page.goto(..., timeout=...)的超时(毫秒)。wait_for:二段等待(goto 完成后再等)- 支持:
css:...:按 CSS selector 等待出现js:...:按 JS 表达式等待返回 true- 不写前缀:策略内部会“先当 JS 试一下,不行就当 CSS”
- 支持:
wait_for_timeout:wait_for的超时,缺省则回退到page_timeout。delay_before_return_html:在拿 HTML 前 sleep 一下(适合等待最后一波异步渲染)。
示例:等某个主内容节点出现:
run_cfg = CrawlerRunConfig(
wait_until="domcontentloaded",
wait_for="css:main article", # 或 "css:#content"
wait_for_timeout=20_000,
)
4.2 js_only(容易踩坑)
在 AsyncPlaywrightCrawlerStrategy 的实现里:
- 当
js_only=False(默认)时:会正常执行page.goto(url, ...) - 当
js_only=True时:会跳过 goto(不会导航到 URL)
除非你非常清楚自己在做什么(例如你在 hook 里自行导航/复用 page),否则请保持 js_only=False。
4.3 滚动与懒加载
scan_full_page=True:会执行“整页滚动”以触发懒加载(lazy load)。scroll_delay:每次滚动的等待(秒)。max_scroll_steps:最大滚动次数(防止无限滚动页面卡死)。
virtual_scroll_config:处理“虚拟列表”场景(DOM 会复用/替换),常见于信息流。- 结构:
VirtualScrollConfig(container_selector, scroll_count, scroll_by, wait_after_scroll)
- 结构:
示例:整页滚动 + 限制最多滚 30 次:
run_cfg = CrawlerRunConfig(
scan_full_page=True,
scroll_delay=0.2,
max_scroll_steps=30,
)
示例:虚拟列表滚动(信息流容器):
from crawl4ai.async_configs import VirtualScrollConfig
from crawl4ai import CrawlerRunConfig
run_cfg = CrawlerRunConfig(
virtual_scroll_config=VirtualScrollConfig(
container_selector="div[role='feed']",
scroll_count=12,
scroll_by="container_height", # 也可以是 "page_height" 或数字像素
wait_after_scroll=0.6,
)
)
4.4 执行自定义 JS(js_code)
js_code 可以是字符串或字符串列表,策略会执行并把结果写到 AsyncCrawlResponse.js_execution_result,最终在 CrawlResult.js_execution_result 里可取到。
典型用途:
- 点击“加载更多”
- 关闭弹窗
- 展开折叠内容
示例(点击“加载更多”按钮 5 次):
run_cfg = CrawlerRunConfig(
js_code="""
() => {
const btn = document.querySelector('button.load-more');
if (btn) btn.click();
return {clicked: Boolean(btn)};
}
""",
scan_full_page=True,
max_scroll_steps=10,
wait_for="css:article", # 等正文出现
)
建议:
js_code往往需要配合delay_before_return_html/wait_for,否则点击后内容还没渲染完就取 HTML 了。
4.5 只抓某些 DOM(css_selector)
如果你只关心页面某些区域,可以设置 css_selector(支持逗号分隔多个 selector)。策略会执行:
Array.from(document.querySelectorAll(selector)).map(el => el.outerHTML).join('')
最后把结果包在一个 <div class='crawl4ai-result'>...</div> 返回。
示例:只抓 main + article:
run_cfg = CrawlerRunConfig(css_selector="main, article")
4.6 iframe 与遮罩
process_iframes=True:会尝试处理 iframe(把 iframe 内容“合并/展开”进结果,具体行为取决于策略实现)。remove_overlay_elements=True:会尝试移除 overlay(弹窗/遮罩层),减少“Cookie 同意框遮住正文”的情况。
4.7 截图 / PDF / MHTML
策略支持三种“导出型”产物:
screenshot=True:截图(可配screenshot_wait_for/screenshot_height_threshold)pdf=True:导出 PDF(export_pdf)capture_mhtml=True:抓 mhtml
示例(截图 + PDF):
run_cfg = CrawlerRunConfig(
screenshot=True,
screenshot_wait_for=1.0,
pdf=True,
)
4.8 捕获网络请求/控制台(调试神器)
capture_network_requests=True:记录 request/response/failed 等事件(注意:response body 可能很大)capture_console_messages=True:记录 console 输出(在排查站点脚本错误时很有用)
示例:
run_cfg = CrawlerRunConfig(
capture_network_requests=True,
capture_console_messages=True,
)
抓取后可在结果里读取:
result.network_requestsresult.console_messages
5. 直接使用 AsyncPlaywrightCrawlerStrategy(需要 hooks/自定义行为时)
如果你需要:
- 在
goto前后插入逻辑(改 headers、注入脚本、设置路由) - 或做更细的 Playwright 操作
可以显式创建 strategy 并设置 hooks。
5.1 可用 hook 列表
AsyncPlaywrightCrawlerStrategy 内置 hooks:
on_browser_created:browser 创建完成(参数:browser, context, **kwargs)on_page_context_created:拿到 page/context 后(参数:page, context=…, config=…)on_user_agent_updatedon_execution_started/on_execution_endedbefore_goto/after_gotobefore_retrieve_html:准备拿 HTML 前before_return_html:HTML 已拿到、返回前(可修改 HTML)
5.2 示例:在 page 创建后注入路由(拦截图片)
如果你只是想“更快”,优先用
BrowserConfig(text_mode=True);route 更适合做更细粒度控制。
import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig
from crawl4ai.async_crawler_strategy import AsyncPlaywrightCrawlerStrategy
async def on_page_created(page, *, context, config, **kwargs):
# 例:拦截图片请求
await page.route("**/*.{png,jpg,jpeg,gif,webp,svg}", lambda route: route.abort())
async def main():
browser_cfg = BrowserConfig(headless=True, enable_stealth=True)
strategy = AsyncPlaywrightCrawlerStrategy(browser_config=browser_cfg)
strategy.set_hook("on_page_context_created", on_page_created)
run_cfg = CrawlerRunConfig(wait_until="domcontentloaded", verbose=False)
async with AsyncWebCrawler(crawler_strategy=strategy) as crawler:
result = await crawler.arun("https://example.com", config=run_cfg)
print(result.success, result.url, len(result.html or \"\"))
asyncio.run(main())
6. 和 BFSDeepCrawlStrategy 配合(深度爬取)
深度爬取的关键点是:把 deep_crawl_strategy 放进 CrawlerRunConfig。
import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig
from crawl4ai import FilterChain, URLPatternFilter
from crawl4ai.deep_crawling import BFSDeepCrawlStrategy
async def main():
browser_cfg = BrowserConfig(headless=True, enable_stealth=True)
filter_chain = FilterChain([
URLPatternFilter(["https://example.com/**"]),
])
deep = BFSDeepCrawlStrategy(max_depth=2, max_pages=50, filter_chain=filter_chain)
run_cfg = CrawlerRunConfig(
deep_crawl_strategy=deep,
stream=True, # 深度爬取推荐 stream,边抓边处理
wait_until="domcontentloaded",
verbose=False,
)
async with AsyncWebCrawler(config=browser_cfg) as crawler:
async for r in await crawler.arun("https://example.com", config=run_cfg):
depth = (r.metadata or {}).get("depth")
parent = (r.metadata or {}).get("parent_url")
print(r.success, depth, r.url, "<-", parent)
asyncio.run(main())
7. 性能与稳定性建议(实战经验)
-
不要盲目用
wait_until="networkidle"
很多站点有长连接/埋点/轮询,会导致网络永远不 idle;更推荐domcontentloaded + wait_for(css:...)。 -
对滚动/信息流页面一定加
max_scroll_steps
防止无限滚动导致一页耗时失控。 -
正文抓取优先 text/light mode
light_mode=True:更像“少加载一些资源”text_mode=True:更激进,会 route abort 多种静态资源(速度明显提升,但站点可能缺少某些依赖导致渲染异常)
-
并发要克制
Playwright 每开一个 page/context 都是实打实的资源;arun_many并发过大很容易触发Target closed/ 内存飙升。 -
需要登录态时优先 storage_state 或 persistent context
- 临时:
storage_state="state.json"(可复用一次登录态) - 长期:
use_persistent_context=True + user_data_dir=...
- 临时:
8. 常见问题排查
8.1 页面空白/只返回 about:blank
优先检查 CrawlerRunConfig(js_only=True) 是否误开;在该策略实现中 js_only=True 会跳过 page.goto()。
8.2 下载文件时报 net::ERR_ABORTED
如果你启用了下载(BrowserConfig(accept_downloads=True)),导航可能会被浏览器中止(这是下载触发时常见行为)。策略里对这种情况做了兼容:会把它当作“可能在下载”并继续流程。
你可以从结果里取 downloaded_files。
8.3 超时(Timeout)
排查顺序:
- 降低
wait_until的严格程度(先用domcontentloaded) - 用
wait_for="css:..."精准等待关键节点 - 增大
page_timeout/wait_for_timeout - 对滚动页面设置
max_scroll_steps,避免卡在滚动
更多推荐



所有评论(0)