首页
/ Crawl4AI 高级特性实战:代理、PDF/截图、SSL 证书、自定义请求头、会话持久化与反爬规避

Crawl4AI 高级特性实战:代理、PDF/截图、SSL 证书、自定义请求头、会话持久化与反爬规避

2026-09-04 23:13:52作者:舒璇辛Bertina

本文系统讲解 Crawl4AI 中面向生产场景的七类高级特性:通过 BrowserConfig.proxy_config 配置代理、一次性抓取 PDF 与截图、爬取并导出 SSL 证书、以多种方式注入自定义请求头、用 storage_state 持久化 Cookie 与 localStorage、遵循 robots.txt 规则,以及借助 Stealth Mode 与 Undetected Browser 应对 Bot 检测。读完后你将掌握这些参数的正确用法、底层实现位置(crawl4ai/async_configs.pycrawl4ai/ssl_certificate.pycrawl4ai/utils.pycrawl4ai/browser_adapter.py)及其组合运用的完整工作流。

前置条件:熟悉 AsyncWebCrawler 基础用法,并在 Python 环境中安装好 Playwright(pip install crawl4ai && crawl4ai-setup 或参考 安装指南)。

1. 代理配置:proxy_config 的三种输入形式

当你需要把爬虫流量路由到代理——IP 轮换、地理测试或隐私隔离——Crawl4AI 通过 BrowserConfig.proxy_config 提供支持。

import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig

async def main():
    browser_cfg = BrowserConfig(
        proxy_config={
            "server": "http://proxy.example.com:8080",
            "username": "myuser",
            "password": "mypass",
        },
        headless=True
    )
    crawler_cfg = CrawlerRunConfig(
        verbose=True
    )

    async with AsyncWebCrawler(config=browser_cfg) as crawler:
        result = await crawler.arun(
            url="https://www.whatismyip.com/",
            config=crawler_cfg
        )
        if result.success:
            print("[OK] Page fetched via proxy.")
            print("Page HTML snippet:", result.html[:200])
        else:
            print("[ERROR]", result.error_message)

if __name__ == "__main__":
    asyncio.run(main())

关键点

  • proxy_config 接受一个字典,包含 server 及可选的 username/password
  • 多数商业代理提供商给出 HTTP/HTTPS "网关" 地址,直接填入 server 即可;
  • 代理无需认证时省略 username/password

源码视角:ProxyConfig 的数据模型

crawl4ai/async_configs.py 中定义了 ProxyConfig 类,构造参数为 server(必填)、usernamepasswordip(可选,用于校验出口 IP;若不显式给出,会从 server 中自动解析出 host 部分)。配置归一化的关键逻辑在 BrowserConfig 的初始化中:传入字典时调用 ProxyConfig.from_dict(),传入字符串时调用 ProxyConfig.from_string()

from_string 支持多种写法,这让你可以用环境变量或简单字符串批量管理代理:

from crawl4ai.async_configs import ProxyConfig

# 以下格式全部合法
ProxyConfig.from_string("http://user:pass@10.0.0.1:8080")
ProxyConfig.from_string("http://10.0.0.1:8080")
ProxyConfig.from_string("socks5://10.0.0.1:8080")
ProxyConfig.from_string("10.0.0.1:8080:user:pass")
ProxyConfig.from_string("10.0.0.1:8080")

此外,ProxyConfig.from_env("PROXIES") 可从环境变量读取以逗号分隔的代理字符串列表,便于在 CI 或容器部署中免改代码地注入代理池。

版本兼容提示:从源码可确认,旧的 proxy 字符串参数已被标记为废弃(BrowserConfig 初始化中会发出 UserWarning),新代码请一律使用 proxy_config;若同时提供 proxyproxy_configproxy_config 优先。另外 CrawlerRunConfig 也支持 proxy_config 参数,且可传入代理列表用于重试轮转——这是 crawl4ai/async_configs.py_normalize_proxy_config 的归一化逻辑所支持的形态,ProxyConfig.DIRECT(值为 "direct")可作为列表中的哨兵表示"该次重试不使用代理"。

2. 抓取 PDF 与截图:一次 arun 双份产出

有时你需要页面的可视化记录或 PDF "打印件"。Crawl4AI 能在一次运行中同时完成两者:

import os, asyncio
from base64 import b64decode
from crawl4ai import AsyncWebCrawler, CacheMode, CrawlerRunConfig

async def main():
    run_config = CrawlerRunConfig(
        cache_mode=CacheMode.BYPASS,
        screenshot=True,
        pdf=True
    )

    async with AsyncWebCrawler() as crawler:
        result = await crawler.arun(
            url="https://en.wikipedia.org/wiki/List_of_common_misconceptions",
            config=run_config
        )
        if result.success:
            print(f"Screenshot data present: {result.screenshot is not None}")
            print(f"PDF data present: {result.pdf is not None}")

            if result.screenshot:
                print(f"[OK] Screenshot captured, size: {len(result.screenshot)} bytes")
                with open("wikipedia_screenshot.png", "wb") as f:
                    f.write(b64decode(result.screenshot))
            else:
                print("[WARN] Screenshot data is None.")

            if result.pdf:
                print(f"[OK] PDF captured, size: {len(result.pdf)} bytes")
                with open("wikipedia_page.pdf", "wb") as f:
                    f.write(result.pdf)
            else:
                print("[WARN] PDF data is None.")

        else:
            print("[ERROR]", result.error_message)

if __name__ == "__main__":
    asyncio.run(main())

为什么需要 PDF + 截图双通道?

  • 超长或结构复杂的页面,传统"整页截图"可能缓慢甚至出错;
  • 对极长页面,导出 PDF 更可靠;当你同时请求两者时,Crawl4AI 会自动把 PDF 首页转换为图像作为截图输出。

相关参数(均位于 CrawlerRunConfig,可参见 crawl4ai/async_configs.py 的字段文档):

参数 说明 默认值
pdf=True 将当前页面导出为 PDF,base64 编码后存放于 result.pdf False
screenshot=True 生成页面截图,base64 编码后存放于 result.screenshot False
scroll_delay 整页截图时每次滚动之间的延迟(秒),默认 0.2;页面资源加载慢时应调大 0.2
scan_full_page True 时滚动遍历整个页面以加载全部懒加载内容,配合 scroll_delay 控制节奏
force_viewport_screenshot True 时无论页面多高,只截取视口范围,避免超长页面整页截图的开销 False

对截图质量有更高要求时,还可在 BrowserConfig 中设置 device_scale_factor(设备像素比),例如 2.0 可使 1920×1080 视口产出 3840×2160 的高清截图,代价是内存与渲染时间增加。

3. 获取并导出 SSL 证书

出于合规审计、故障排查或数据分析需要,你可能要抓取目标站点的 SSL 证书。Crawl4AI 支持在爬取过程中完成这件事:

import asyncio, os
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig, CacheMode

async def main():
    tmp_dir = os.path.join(os.getcwd(), "tmp")
    os.makedirs(tmp_dir, exist_ok=True)

    config = CrawlerRunConfig(
        fetch_ssl_certificate=True,
        cache_mode=CacheMode.BYPASS
    )

    async with AsyncWebCrawler() as crawler:
        result = await crawler.arun(url="https://example.com", config=config)

        if result.success and result.ssl_certificate:
            cert = result.ssl_certificate
            print("\nCertificate Information:")
            print(f"Issuer (CN): {cert.issuer.get('CN', '')}")
            print(f"Valid until: {cert.valid_until}")
            print(f"Fingerprint: {cert.fingerprint}")

            # Export in multiple formats:
            cert.to_json(os.path.join(tmp_dir, "certificate.json"))
            cert.to_pem(os.path.join(tmp_dir, "certificate.pem"))
            cert.to_der(os.path.join(tmp_dir, "certificate.der"))

            print("\nCertificate exported to JSON/PEM/DER in 'tmp' folder.")
        else:
            print("[ERROR] No certificate or crawl failed.")

if __name__ == "__main__":
    asyncio.run(main())

关键点

  • fetch_ssl_certificate=True 触发证书抓取(默认 False);
  • result.ssl_certificate 是一个 SSLCertificate 对象,提供 to_jsonto_pemto_der 方法,可保存为多种格式(便于服务器配置、Java 密钥库导入等)。

源码视角:SSLCertificate 的设计

证书处理逻辑集中在 crawl4ai/ssl_certificate.pySSLCertificate 继承自 dict,因此实例可以直接 JSON 序列化,issuervalid_untilfingerprint 以属性形式暴露。其静态方法 from_url(url, timeout=10) 的工作方式是直接对主机名 443 端口建立 TCP 连接并用 ssl.create_default_context() 包裹 socket(见 crawl4ai/ssl_certificate.py),再把返回的 DER 数据交给 OpenSSL.crypto 解析——这意味着证书抓取独立于浏览器页面本身,即使页面渲染失败,只要 HTTPS 握手成功,证书依然可以拿到。该模块依赖 pyOpenSSL,因此安装时需要确保该依赖可用。

4. 自定义请求头:两种注入途径

某些场景需要设置自定义请求头,例如语言偏好、认证 Token 或特定的 User-Agent 字符串。Crawl4AI 提供了至少两条路径:

import asyncio
from crawl4ai import AsyncWebCrawler

async def main():
    # Option 1: Set headers at the crawler strategy level
    crawler1 = AsyncWebCrawler(
        # The underlying strategy can accept headers in its constructor
        crawler_strategy=None  # We'll override below for clarity
    )
    crawler1.crawler_strategy.update_user_agent("MyCustomUA/1.0")
    crawler1.crawler_strategy.set_custom_headers({
        "Accept-Language": "fr-FR,fr;q=0.9"
    })
    result1 = await crawler1.arun("https://www.example.com")
    print("Example 1 result success:", result1.success)

    # Option 2: Pass headers directly to `arun()`
    crawler2 = AsyncWebCrawler()
    result2 = await crawler2.arun(
        url="https://www.example.com",
        headers={"Accept-Language": "es-ES,es;q=0.9"}
    )
    print("Example 2 result success:", result2.success)

if __name__ == "__main__":
    asyncio.run(main())

两种途径的适用范围(结合 crawl4ai/async_configs.py 的字段文档可以明确区分):

途径 作用层级 适合场景
策略层 update_user_agent / set_custom_headers 浏览器上下文级,对该爬虫实例的所有请求生效 需要长期稳定的身份标识
arun(headers=...)BrowserConfig.headers 单次运行 / 上下文创建时注入 按请求变化的语言、Token

另外,BrowserConfig 还支持 user_agent(直接指定 UA 字符串)与 user_agent_mode="random" 配合 user_agent_generator_config 的随机 UA 生成模式。需要注意:

5. 会话持久化与本地存储

Crawl4AI 可以保留 Cookie 与 localStorage,让你"接着上次继续"——登录一次,之后免登录反复访问,是跳过重复认证流程的理想方案。

5.1 storage_state:以字典注入"已登录"状态

storage_stateBrowserConfig 的参数,接受路径字符串或内存字典(见 crawl4ai/async_configs.py 的字段说明):

import asyncio
from crawl4ai import AsyncWebCrawler

async def main():
    storage_dict = {
        "cookies": [
            {
                "name": "session",
                "value": "abcd1234",
                "domain": "example.com",
                "path": "/",
                "expires": 1699999999.0,
                "httpOnly": False,
                "secure": False,
                "sameSite": "None"
            }
        ],
        "origins": [
            {
                "origin": "https://example.com",
                "localStorage": [
                    {"name": "token", "value": "my_auth_token"}
                ]
            }
        ]
    }

    # Provide the storage state as a dictionary to start "already logged in"
    async with AsyncWebCrawler(
        headless=True,
        storage_state=storage_dict
    ) as crawler:
        result = await crawler.arun("https://example.com/protected")
        if result.success:
            print("Protected page content length:", len(result.html))
        else:
            print("Failed to crawl protected page")

if __name__ == "__main__":
    asyncio.run(main())

字典结构与 Playwright 的 storage state 格式一致:cookies 数组携带 namevaluedomainpathexpireshttpOnlysecuresameSite 字段;origins 数组按 origin 挂载 localStorage 键值对。

5.2 导出与复用状态:登录一次,长期受益

先手动或自动化完成登录,然后导出浏览器上下文,之后复用即可——无需再次输入凭据:

  • await context.storage_state(path="my_storage.json"):在 hooks 中通过浏览器上下文把 Cookie、localStorage 等导出到文件;
  • 后续运行传入 storage_state="my_storage.json"(路径形式)即可跳过登录步骤。

进阶场景(多步登录、交互式页面登录后再捕获状态)请参考 会话管理教程浏览器上下文与管理式浏览器说明

6. robots.txt 合规检查

Crawl4AI 支持遵循 robots.txt 规则,并带有高效的本地缓存:

import asyncio
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig

async def main():
    # Enable robots.txt checking in config
    config = CrawlerRunConfig(
        check_robots_txt=True  # Will check and respect robots.txt rules
    )

    async with AsyncWebCrawler() as crawler:
        result = await crawler.arun(
            "https://example.com",
            config=config
        )

        if not result.success and result.status_code == 403:
            print("Access denied by robots.txt")

if __name__ == "__main__":
    asyncio.run(main())

关键点

  • robots.txt 文件会被缓存到本地以提升效率;
  • 缓存数据库位于 ~/.crawl4ai/robots/robots_cache.db
  • 缓存默认 TTL 为 7 天;
  • 若 robots.txt 无法抓取,则允许爬取(fail-open 策略);
  • URL 被禁止访问时返回 403 状态码。

源码视角:缓存实现细节

上述行为在 crawl4ai/utils.py 中可以直接验证:CACHE_TTL = 7 * 24 * 60 * 60(即 7 天),缓存目录为 ~/.crawl4ai/robots,底层用 SQLite 建 robots_cache 表(按 domain 建索引),每条缓存记录保存 rulesfetch_timehash 三列——hash 用于变化检测,fetch_time 用于 TTL 过期清理(clear_expired 会删除 fetch_time 早于 now - ttl 的条目)。check 方法以 2 秒超时异步 GET https://{domain}/robots.txt,抓取失败即放行,与文档描述一致。

7. 反 Bot 特性:Stealth Mode 与 Undetected Browser

Crawl4AI 提供两套对抗 Bot 检测的机制,可按站点防护强度选择。

7.1 Stealth Mode

Stealth mode 基于 playwright-stealth 修改浏览器指纹与行为,一个开关即可启用:

browser_config = BrowserConfig(
    enable_stealth=True,  # Activates stealth mode
    headless=False
)

适用场景:具备基础 Bot 检测的站点(检查 navigator.webdriver、plugins 等)。源码中该参数定义在 crawl4ai/async_configs.pyenable_stealth 默认 False,且明确"不可与 undetected 浏览器模式同时使用"——两种机制互斥,组合时以 undetected 为准。

7.2 Undetected Browser

面对高级检测,使用 undetected 浏览器适配器:

from crawl4ai import UndetectedAdapter
from crawl4ai.async_crawler_strategy import AsyncPlaywrightCrawlerStrategy

# Create undetected adapter
adapter = UndetectedAdapter()
strategy = AsyncPlaywrightCrawlerStrategy(
    browser_config=browser_config,
    browser_adapter=adapter
)

async with AsyncWebCrawler(crawler_strategy=strategy, config=browser_config) as crawler:
    # Your crawling code

UndetectedAdapter 定义在 crawl4ai/browser_adapter.py,继承自抽象基类 BrowserAdapter(L24)。适配器模式的意义在于:AsyncPlaywrightCrawlerStrategy 不直接绑定某一浏览器实现,而是通过注入的 browser_adapter 完成启动与页面操作——换成 undetected-chromedriver 内核时,上层的爬取、提取逻辑完全不用改。

适用场景:具备复杂 Bot 检测的站点(如 Cloudflare、DataDome 一类的防护)。

7.3 选择策略对照表

检测等级 推荐方案
无防护 普通浏览器
基础检查 普通 + Stealth mode
高级防护 Undetected browser
最大规避 Undetected + Stealth mode 参数(注意源码约束:两者不可同时激活,以 undetected 为主)

最佳实践:从普通浏览器 + stealth mode 起步,仅在确实被拦截时再上 undetected browser——它可能略慢。详细示例见 Undetected Browser Mode;仓库中也有对应的可运行演示,如 docs/examples/stealth_mode_example.pydocs/examples/undetected_simple_demo.pydocs/examples/hello_world_undetected.py

注意:官方在文档中说明,未来版本可能默认启用 stealth mode 与 undetected browser;目前版本需要显式开启。

组合实战:一次运行启用全部高级特性

下面把代理、PDF、截图、SSL、自定义请求头与会话复用组合在同一次 arun 中。实际项目里请按各自需要裁剪:

import os, asyncio
from base64 import b64decode
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode

async def main():
    # 1. Browser config with proxy + headless
    browser_cfg = BrowserConfig(
        proxy_config={
            "server": "http://proxy.example.com:8080",
            "username": "myuser",
            "password": "mypass",
        },
        headless=True,
    )

    # 2. Crawler config with PDF, screenshot, SSL, custom headers, and ignoring caches
    crawler_cfg = CrawlerRunConfig(
        pdf=True,
        screenshot=True,
        fetch_ssl_certificate=True,
        cache_mode=CacheMode.BYPASS,
        headers={"Accept-Language": "en-US,en;q=0.8"},
        storage_state="my_storage.json",  # Reuse session from a previous sign-in
        verbose=True,
    )

    # 3. Crawl
    async with AsyncWebCrawler(config=browser_cfg) as crawler:
        result = await crawler.arun(
            url="https://secure.example.com/protected",
            config=crawler_cfg
        )

        if result.success:
            print("[OK] Crawled the secure page. Links found:", len(result.links.get("internal", [])))

            # Save PDF & screenshot
            if result.pdf:
                with open("result.pdf", "wb") as f:
                    f.write(b64decode(result.pdf))
            if result.screenshot:
                with open("result.png", "wb") as f:
                    f.write(b64decode(result.screenshot))

            # Check SSL cert
            if result.ssl_certificate:
                print("SSL Issuer CN:", result.ssl_certificate.issuer.get("CN", ""))
        else:
            print("[ERROR]", result.error_message)

if __name__ == "__main__":
    asyncio.run(main())

两点值得注意的配置分层:浏览器级能力(代理、UA、stealth、viewport)挂在 BrowserConfig 上,随浏览器生命周期存在;运行级能力(PDF/截图、SSL 抓取、robots 检查、缓存策略)挂在 CrawlerRunConfig 上,可按每次 arun 独立调整。需要说明的是,组合示例中的 storage_stateCrawlerRunConfig 上传递;按源码字段定义,会话状态的持久注入应使用 BrowserConfig.storage_state,两者语义接近,实际以你所用版本的字段校验为准。

小结

本文覆盖的 Crawl4AI 高级特性及其落地位置:

  • 代理BrowserConfig.proxy_config,底层为 ProxyConfig,支持 dict/字符串/环境变量/列表轮转;
  • PDF 与截图CrawlerRunConfigpdfscreenshotscroll_delayscan_full_pageforce_viewport_screenshot
  • SSL 证书fetch_ssl_certificate + SSLCertificateto_json/to_pem/to_der 导出;
  • 自定义请求头:策略层 set_custom_headers/update_user_agentarun(headers=...) 两条注入路径;
  • 会话持久化storage_state 字典或 JSON 文件复用 Cookie 与 localStorage;
  • robots.txtcheck_robots_txt,本地 SQLite 缓存 7 天 TTL,禁止访问返回 403;
  • 反 Botenable_stealth(playwright-stealth)与 UndetectedAdapter(undetected 内核适配器)。

掌握这些能力后,你可以构建模拟真实用户行为、处理安全站点、产出可视化快照、跨运行复用会话并规避 Bot 检测的稳健采集流水线。本文所有参数行为均以当前仓库源码为准;代理轮转、多步登录、undetected 模式等更深层场景,可分别深入 proxy 相关测试会话管理文档undetected browser 文档 继续学习。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
504
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384