
1. 项目概述与设计思路1.1 ScrapeGraphAI 到底是什么在做信息采集和数据分析的时候我经常会遇到一个很折腾的场景目标网站的结构变了之前写好的爬虫脚本立刻失效又要重新对着开发者工具看 class、id一条条改选择器。这种循环持续了很长时间直到我开始用 ScrapeGraphAI。这个项目在 GitHub 上的名字是 ScrapeGraphAI/Scrapegraph-ai核心思路很简单用大语言模型来驱动网页抓取不再靠死写 CSS 选择器或 XPath而是把“你想抓什么”用自然语言告诉它由模型负责分析页面结构、定位数据、整理输出。本质上它把传统爬虫的“规则匹配”换成了“语义理解”。它还引入了一个很有意思的概念抓取图ScrapeGraph。可以把一个抓取任务拆成一连串小步骤像流水线一样串联起来每一步之间传数据最终直接给你一份结构化结果。对我来说它最大的价值不是“又多了一个爬虫框架”而是把网页解析这件事从写代码变成了写需求。这篇文章适合谁看如果你用过 Requests、Scrapy 这类库知道选择器是什么但被页面改版搞得头大或者你想在项目里快速实现一个“给个链接就能抽数据”的能力都在这个范围内。我会把它的设计逻辑、具体用法、我踩过的坑全部拆开讲一遍尽量做到看完能直接上手。1.2 为什么需要用 LLM 做爬虫传统爬虫的根基是“定位”。你得告诉程序目标数据在哪个标签、哪个 class、哪一层兄弟节点里。这个方案在页面稳定的场景下效率很高但代价是脆弱。页面只要加了个包裹层、改了属性名或换了渲染方式之前的 url 规则就全线崩溃。ScrapeGraphAI 换了一条路让模型看页面内容来判断“哪里是要找的数据”。它把 HTML 转成文本、Markdown有时还会配合 DOM 树结构交给 LLM 去推理。模型不需要知道选择器只需要理解用户的需求比如“提取所有文章的标题、发布时间和作者”就能自己找到相应内容。这样做带来几个直接好处页面结构和样式变了只要内容还在通常还能抓对不用针对每个站点单独写解析逻辑站点多了以后工作量能明显降下来对动态渲染的页面配合 Playwright 这类工具也能处理覆盖面更广。当然它也有代价。LLM 的推理速度比正则表达式慢得多Token 消耗也要花钱而且模型偶尔会“自由发挥”把抓取结果整理成不太符合预期的格式。所以它更适合做“规模可控、变化频繁、结构复杂”的任务而不是让你拿它去爬千万级页面。想要高吞吐量的批量任务还是传统方案更合适。1.3 技术栈与架构拆解ScrapeGraphAI 的核心是用图结构来描述抓取任务。我刚开始看到 “ScrapeGraph” 这个名字时以为是什么复杂的数据结构用下来才发现它就是把你需要执行的抓取步骤定义成节点节点之间用边连接数据沿着边流动。常见的内置“图”有这么几类SmartScraperGraph单页抓取给定 URL 和需求直接出结果。这是平时用得最多的。SearchGraph从搜索引擎结果页出发把多个页面串起来抓取。适合做竞品信息汇总。SpeechGraph抓取结果直接用语音合成播报偏演示场景实际工作里很少用。ScriptCreatorGraph让 LLM 自动生成一个抓取脚本本质是用模型写代码。ExtractGraph直接从一个 URL 批量提取多个维度的信息。底层方面它支持对接 OpenAI、Anthropic、Google Gemini、Ollama 本地模型等也就是说你可以完全离线跑不用把页面内容发到第三方。这对处理敏感数据来说很关键我这边有一类内部信息抓取任务就是全部走 Ollama 的本地模型解决。抓取引擎支持 Requests 和 Playwright后者在遇到需要 JS 渲染的页面时是必需品。整条链路你可以理解为三部分入口是自然语言需求中间是图编排和模型推理出口是结构化数据。ScrapeGraphAI 所做的就是把中间这层包装得足够简单让你不用关心模型怎么调用、提示词怎么组织、结果怎么解析。2. 核心概念与关键参数2.1 图结构理解 ScrapeGraph 的工作方式要真正用好 ScrapeGraphAI就必须理解“图”是怎么组织的。官方仓库里的文档把节点分为两类抓取节点和解析节点。抓取节点负责把页面内容抓下来可以只抓静态 HTML也可以渲染 JS 之后再抓。解析节点负责把抓取到的内容连同用户需求一起交给 LLM让模型返回结构化数据。图的好处是什么呢我举个例子。你想抓一个新闻列表页但摘要信息不完整需要点进详情页才能拿到正文。传统爬虫你得分别写列表页的解析函数、详情页的解析函数再用代码把它们串起来。在 ScrapeGraphAI 里你可以定义两个抓取步骤前一步把详情页链接找出来后一步逐个访问这些链接提取正文中间用边连起来它就自动执行完了。这就是“SearchGraph”这类预置图的工作原理。它对搜索页面的结果链接进行遍历再对每个链接执行一次内容提取最后汇总。由于链接数量不定运行时间也会波动但思路很直观不要一个人干完所有事而是拆成步骤每个步骤只干一件事。了解了这个原理你在遇到复杂需求时就能自己组装图。虽然官方提供的预置图覆盖了大多数场景但真正符合自己业务的流程通常需要自定义节点逻辑。比如某个页面需要先登录那你就要在抓取节点之前加一步“带 Cookie 请求”的处理。2.2 Prompt 设计决定抓取质量的第一因素ScrapeGraphAI 把用户输入的自然语言需求直接拼进发给模型的提示词里。所以你的需求写得清不清楚直接决定返回结果好不好。我见过不少用户反馈“抓出来的东西不对”看代码没什么问题最后几乎全是提示词写得太模糊。先看一个反面例子提取这个页面的所有信息这种提示词基本等于没有模型不知道你要什么就会把整个页面的大段文字一股脑给你或者自行臆断输出结构。更好的写法是这样从页面中提取所有产品的名称、价格、评分和库存状态。 以 JSON 数组格式返回每个产品包含 name、price、rating、stock 四个字段。这里我强烈建议在提示词里明确给出三样东西要哪些字段尽量用明确的名词输出格式JSON、Markdown 表格还是纯文本取数范围是只要第一屏内容还是要遍历全部分页。你仔细想就会发现这跟带人干活是一样的。你只说“把资料整理一下”对方不知道整理成什么样但你如果告诉他“把这三列数据抽出来整理成 CSV表头用中文”他就能直接上手。还有一个细节模型对数字和名称的理解存在概率性。同一页面跑两次返回结果可能在字段命名上略有差异。所以我的习惯是在提示词里把字段名固定死并且在拿到数据之后再做一层校验而不是默认模型每次输出都是完美的。2.3 模型 Provider 与本地化部署选择ScrapeGraphAI 的模型接入层做得很灵活支持的 Provider 包括 OpenAI、Anthropic、Gemini、Azure OpenAI、Ollama 等。它的设计里把“模型”和“抓取流程”解耦了所以切换模型不需要改业务代码只需要改配置项。我这边在实际项目中试过几类模型简单做个对比如下Provider优势劣势适合场景OpenAI GPT-4o / GPT-4o-mini理解能力强结构化输出稳定API 费用高数据出境对准确性要求高的商业采集Gemini / Claude长文本处理能力好需要科学访问部分地区不稳定海外站点采集Ollama 本地模型免费数据不出内网响应慢参数量小的模型精度一般敏感数据、内部系统DeepSeek 等国内模型费用低中文理解好生态相对小众中文站点、成本敏感项目我个人的建议是先拿 GPT-4o-mini 这类便宜模型跑通流程确认提示词没问题后再根据数据敏感等级决定是继续用云端还是切到本地 Ollama。如果你选择 Ollama配置非常简单。先拉一个模型ollama pull llama3.2然后在代码里指定 Model 为ollama/llama3.2再配置 Ollama 的服务地址即可。用本地模型的代价是速度和精度比如一次简单的单页提取可能要花十几秒而云端模型只要两三秒。有一点需要特别注意不同模型的输出格式遵从能力差别很大。GPT-4o 系列对 JSON 格式的把握很稳而一些参数量较小的模型偶尔会输出多余的注释或 Markdown 标记。遇到这种情况不要一味换模型可以在提示词里补充一句“只输出 JSON不要输出任何解释性文字”往往能明显改善。2.4 数据输出格式与结构化提取ScrapeGraphAI 的核心输出是ScrapeResult对象里面包含提取结果、抓取截图等信息。默认情况下如果你不指定额外参数输出的格式由模型自己决定。但为了后续处理方便我建议每次都显式要求 JSON 格式。举一个实际使用 SDK 的例子from scrapegraph_py import Client sgai Client(api_keyyour-api-key) response sgai.smartscraper( website_urlhttps://example.com/products, user_prompt提取页面上所有产品名称和价格输出 JSON 数组, )response里通常包含result字段直接就是字符串形式的 JSON。解析这一步的关键在于容错。因为任何一个 LLM 都不可能保证 100% 输出合法 JSON尤其当页面内容复杂时可能多一个逗号、少一个引号导致json.loads抛异常。我的处理办法是先用strip()去掉首尾空白再把常见的 Markdown 代码块标记去掉最后尝试解析。如果解析失败就把它当作纯文本返回并打日志便于人工介入。这套容错逻辑几乎用在了我所有基于 ScrapeGraphAI 的项目里。3. 实操过程与核心环节实现3.1 环境准备与安装先说环境要求。ScrapeGraphAI 基于 Python 3.9 以上版本安装时强烈建议用虚拟环境避免污染系统级 Python。我用的是venvpython -m venv venv source venv/bin/activate # Windows 下是 venv\Scripts\activate核心库安装一行命令pip install scrapegraph-py如果只是用 SDK 方式调用云端的 ScrapeGraphAI 服务这个就够了。但如果你想跑本地库版本那需要换一种安装方式因为开源版和 SaaS 版的包名不同。本地库版本安装的是scrapegraphaipip install scrapegraphai我强烈建议你先把“使用方式”和“底层依赖”分开理解。当我们讨论一个开源项目时说的是代码库当我们使用 SaaS 服务时说的是 API。很多东西在文档里混在一起新人特别容易搞混。我的经验是如果目标只是快速验证想法先注册 ScrapeGraphAI 的云服务拿 API Key 跑一遍如果想深度定制、离线运行再切换到本地开源版本。继续安装本地版本会默认安装 Playwright但浏览器内核需要单独下载playwright install这一步很多人漏掉结果代码一跑就报browser executable not found。另外确认一下 Python 环境里没有缺少torch或transformers因为本地模型推理依赖这些重量级库。3.2 第一个样例SmartScraperGraph我们先跑通一个最基础的流程给定 URL让模型提取产品名称和价格。这里我用的是本地库方式方便展示完整代码from scrapegraphai.graphs import SmartScraperGraph graph_config { llm: { model: openai/gpt-4o-mini, api_key: your_openai_api_key, temperature: 0.1, }, verbose: True, } graph SmartScraperGraph( sourcehttps://example.com/products, prompt提取所有产品名称和价格以 JSON 数组格式返回字段为 name 和 price, configgraph_config, ) result graph.run() print(result)这段代码很短但里面有 4 个关键点llm.model用了openai/前缀表示走 OpenAI 兼容的接口。temperature我习惯调低到 0.1 左右因为提取信息属于“确定性任务”不需要模型发挥创造力。source可以是 URL也可以是本地 HTML 文件路径。传本地文件在调试时特别有用既能省 Token又能反复测同一份页面。graph.run()返回的是一个字典可以直接按字段取数据。跑完你大概率会遇到问题模型输出被截断、字段名和你预期不一致、或者返回了空数组。这些都不用慌我把常见问题的排查方法单独放在第 4 节里讲先继续往下走流程。3.3 自定义提示词与结构化输出用了一段时间之后你会发现自己 80% 的时间其实都花在调提示词上。这个项目本身没有逼你写爬虫代码但它逼你把需求描述清楚。这里我把自己常用的一个“模板”写出来你可以直接抄你是数据提取助手。请从给定网页中提取以下字段 - 字段1字段1描述 - 字段2字段2描述 - 字段3字段3描述 要求 1. 如果页面中不存在某个字段用 null 代替不要省略。 2. 只输出 JSON不要输出任何解释性文字。 3. 如果有多个条目以 JSON 数组形式返回。为什么要写得这么死板因为我发现模型在输出时总是倾向于“换一种说法”导致字段名不稳定。例如你要求price它可能返回Product Price或价钱。在提示词里明确字段名的同时再给一个“If not found, use null”的兜底规则会让结果格式稳定很多。另外对于需要返回较多字段的页面我通常把网页内容分成多个区块来抓。原因很简单上下文长度有限如果整页丢给模型它会抓不住重点。比如一个长文章页面我先提取标题和 Meta再单独提取正文最后合并结果。这比一次性让模型输出全文摘要更可控。你也可以在提示词里指定“只考虑页面左上角的产品区域”来缩小范围但这种情况模型有时会误解所以还是分块最靠谱。3.4 CLI 用法除了写 Python 代码ScrapeGraphAI 还提供一个命令行工具适合快速试一下效果。安装之后直接在终端里跑scrapegraphai smartscraper \ --url https://example.com/products \ --prompt 提取所有产品名称和价格 \ --model openai/gpt-4o-mini \ --api-key your_openai_api_keyCLI 的命令规范和 Python SDK 基本一致只是参数用--传。它的价值在于你不用打开编辑器直接在终端验证一个想法。我经常用它来测试不同提示词的效果比如写好一句话跑一遍看结果不满意就改提示词再跑效率比来回改 Python 文件高挺多。需要注意的是CLI 工具默认输出到标准输出如果结果很长会被终端截断或刷屏。我一般会加 output.json重定向到文件里再查看结果。3.5 参数优化与性能调优跑通之后很多人会关心怎么让结果更准、更快、更省。这里我从三个维度分享我的调优经验。准确率维度。核心是提示词和模型选择。如果你的抓取内容涉及复杂的长文本理解例如从一段新闻里抽出发言人的观点那用小模型很容易漏信息这时要换强一点的模型。反过来如果只是提取标题、日期、作者这种显式字段小模型就够用了完全没必要上旗舰型号。速度维度。影响最大的是页面加载和模型推理。静态页面用默认抓取器就好不要一上来就开 Playwright因为浏览器渲染通常要多等好几秒。判断一个页面是否不需要动态渲染最简单的方法是用 Requests 拉一遍看看关键数据在不在 HTML 源码里。如果在就不用上 Playwright。成本维度。Token 消耗主要受页面文本长度影响。网页除了正文往往还有导航、广告、页脚这些噪声。ScrapeGraphAI 支持在抓取节点后接一个“内容过滤”步骤但更实用的做法是在graph_config里设置max_tokens限制输出长度。另一个有效手段是如果只是测试就用本地 HTML 文件代替线上抓取这样重复运行只消耗模型推理的 Token不消耗抓取流量和渲染时间。还有一个细节temperature参数不要设置得太高。我见过有人直接复制默认配置temperature0.7结果抓同一个页面两次结果不一致。数据提取是“低熵”任务温度越低输出越稳定。你会把 temperature 设到 0.2 以下除非你确实需要模型生成一些非确定性的语义内容。4. 常见问题与排查技巧实录4.1 典型报错与解决方法用 ScrapeGraphAI 的过程中报错是常态。我把自己遇到最多的几个问题整理成表格方便直接对照报错信息原因解决方法ModuleNotFoundError: No module named playwright没有安装 Playwright执行pip install playwright playwright installbrowser executable not foundPlaywright 浏览器内核缺失执行playwright install chromiumInvalid API keyAPI Key 填错或环境变量没加载检查api_key确认没多余空格JSONDecodeError模型返回内容不是合法 JSON在提示词里明确“只输出 JSON”代码里做容错Token limit exceeded页面内容太长超过模型上下文使用内容过滤节点或改用支持更长上下文的模型Timeout页面响应太慢或请求超时增大timeout参数检查网络这里面最容易踩的坑是Token limit exceeded。你抓一个超长新闻页面正文动不动几万字直接塞给模型当然会超。解决办法是先用正则或 BeautifulSoup 把 HTML 里的正文部分提取出来再交给 ScrapeGraphAI 处理。不要指望模型能在几万 Token 的上下文中做到精确定位它的注意力会被噪声稀释。另一个高频问题跟代理有关。如果你的服务器访问 OpenAI API 不稳定程序会反复重试然后宕掉。代码层面上我建议把 API 调用封装在重试机制里比如用tenacity库设置最多重试 3 次每次间隔递增。但更根本的解法是换模型 Provider或者把模型服务部署在内网。4.2 失败重试与日志ScrapeGraphAI 的verbose参数打开之后会打印详细日志。我建议在所有非生产脚本里都开启它能帮你看到每次请求调用的模型、消耗的 Token、执行过程中的每个节点状态。逻辑上抓取流程会经历“抓取 HTML - 清理 HTML - LLM 推理 - 输出格式化”这几个阶段。如果在日志里看到“Cleaning HTML”阶段花了很久那说明页面有很多无效标签可以考虑用内容过滤节点。如果日志显示 LLM 推理刚结束就报错那大概率是输出格式问题。对于重试我自己的做法是这样的当模型返回结果为空或者格式错误时先不急着报错把同一个请求再发一次。因为 LLM 有随机性第二次大概率能输出正确结果。如果第二次还失败再走异常流程。这个“一次不行再来一次”的思路看着笨实际挺管用毕竟重试一次的成本通常远低于人工排查的成本。4.3 反爬与速率控制说到网页抓取反爬是个躲不开的话题。ScrapeGraphAI 本身不处理反爬只负责解析所以遇到 403、验证码、IP 封禁你得在它之前加处理层。我的处理顺序是设置合理的请求头尤其是User-Agent别用默认的 Python 默认 UA加入requests的Session在抓取前先访问一次首页获取必要 Cookie控制请求频率同一域名下两次请求间隔至少 2 到 3 秒如果目标站对 JS 渲染要求很高再用 Playwright并配合动态 UA 和随机延迟。在 ScrapeGraphAI 的graph_config里你可以传入loader_params来设置请求头graph_config { llm: { model: openai/gpt-4o-mini, api_key: ..., }, loader_params: { headers: { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Accept-Language: zh-CN,zh;q0.9, } } }为什么这个参数很多人忽略因为默认配置能跑通大多数规范站点但一旦遇到严格的反爬策略就找不到排查方向。先在loader_params里把请求头模拟成一个真实浏览器能解决掉大部分 403 问题。需要明确一点抓取公开数据时要遵守网站的 robots 协议和使用条款只把爬虫用在合法、合规的场景里。并且请求频率尽量放低别把自己的 IP 打爆了这更多是对自己负责跑批任务时挂掉是最烦人的。4.4 成本控制与 Token 用量LLM 爬虫最大的争议就是成本。如果你抓一个页面消耗 5000 Token一次抓取按 GPT-4o-mini 的定价算可能还要几分钱但大批量跑起来成本就不可忽视了。这里分享几个我实际用下来的省钱策略。第一优先用便宜模型。不是所有任务都需要 GPT-4o很多简单的单页字段提取用gpt-4o-mini甚至llama3.2就能完成。你可以先拿便宜模型跑准确率不够再局部换强模型。第二裁剪输入内容。把页面 HTML 先转成纯文本去掉脚本、样式、导航菜单。本来 5000 Token 的工作量裁剪后可能只剩 1500 Token成本直接降 70%。ScrapeGraphAI 内部虽然也有清理步骤但如果你自己提前处理会省得更多。第三设置max_tokens。这能在模型生成超长结果时及时止损。比如你只提取 5 个字段输出不超过 300 Token那完全可以把max_tokens设为 500防止模型自由发挥写一大段解释。第四加缓存。对同一个页面如果数据没变没必要反复抓。可以给 URL 和提示词的组合做一层哈希缓存命中缓存直接读文件不调用任何模型。我这边专门做了一个“URL 需求 页面版本”的三层缓存抓取成本降了相当多。培养一个意识把 Token 当钱花把抓取逻辑当成成本优化对象。LLM 很好用但不是所有场景都适合用能不用模型的步骤尽量不用。5. 从爬虫到知识管线的扩展思考5.1 把 ScrapeGraphAI 嵌入完整数据流程只把 ScrapeGraphAI 当作一个抓取工具多少有点辜负它的设计。在实际工程里我更喜欢把它放在整个数据处理链路里当作数据接入口。一个典型流程是调度器定时触发任务 - ScrapeGraphAI 抓取并结构化 - 写入数据库 - 变更检测 - 触发下游数据分析。在这个流程里ScrapeGraphAI 负责最难的“从非结构化页面到结构化数据”这一步而其他部分可以全部用普通代码解决。举个例子我在做某个行业的信息监控时需要每天跟踪十几家竞品的新闻页。传统做法是给每个网站写一套解析规则等到网站改版就修一轮。用 ScrapeGraphAI 后我只需要维护一个需求模板例如“提取新闻标题、日期、正文摘要、原文链接”。不管网站怎么改版只要新闻内容还在页面上模型基本都能找到。这种模式的另一层价值是它把“字段变更”的成本从开发变成了配置。以往业务上增加一个字段要改爬虫代码、改解析正则、重新上线现在只需要改提示词里的字段列表。对一个小团队来说效率差异非常明显。5.2 多步骤抓取与自定义图的设计当任务变得复杂时预置图可能不够用需要自己设计图。比如一个典型的商品页你可能要先抓列表页拿到所有详情页链接再逐条抓取详情页的价格和库存。这个流程可以用两个节点串起来。在代码层面官方提供了BaseGraph类可以在里面添加自定义的抓取节点和解析节点。我还没有深入源码层面的高度但从使用者的角度你只需要理解每个节点接收什么输入、返回什么输出即可。设计图的时候有几个经验节点职责要单一。一个节点只做一件事不要既抓列表又抓详情节点间数据格式要明确。你可以定义一个 JSON 结构让上一个节点的结果刚好是下一个节点的输入增加异常分支。比如详情页访问失败时是跳过还是重试这个逻辑要在图里体现。最理想的状态是你的抓取流程变成一张可以配置“依赖关系”的图不同站点套不同模板不用为每个站点写一套代码。这也是 ScrapeGraphAI 和传统爬虫相比最吸引我的地方。5.3 与 LangChain、RAG 的结合空间顺着知识管线的思路往下走ScrapeGraphAI 还可以和 RAG检索增强生成链路很好地结合。最朴素的用法是它负责把网页变成干净的 Markdown 或 JSON然后交给向量库做切片和 embedding。后续的问答机器人、知识库查询全都建立在这个结构化的数据之上。我之前做过一个内部资料助手数据源是几十个内部系统页面。没有用 ScrapeGraphAI 之前光是清洗 HTML、抽取正文就写了很长一段代码而且每个系统页面结构不一样维护成本很高。后来改用 ScrapeGraphAI 统一抽取正文所有页面输出同一份 Markdown 格式下游处理完全无需关心来源差异。结合 LangChain 的DocumentLoader接口理论上可以直接把抓取结果包装成统一的 Document 对象然后接各种文本分割器、向量存储。这样从抓取到问答链路上没有一处需要手写解析逻辑维护成本降了一个量级。当然这也意味着你要接受模型推理的延迟。在 RAG 的场景里增量更新不需要实时但如果你做的是实时页面监控那就需要考虑异步任务队列。我的建议是把抓取和入库拆成异步任务用 Redis/RabbitMQ 做缓冲避免阻塞主流程。6. 聊聊我的使用体会做技术选型的时候我很少因为“某个框架火”就去用它更多是看它能不能解决实际问题。ScrapeGraphAI 给我的最大帮助是它把网页抓取从“面向代码”变成了“面向需求”。我不再需要为每个网站精心编写选择器也不用在网站改版时苦哈哈地改代码交需求的时候说一句“我要什么”就够了。当然它不是一个万能工具。大规模抓取、极高性能场景传统方案依然不可替代精确到像素级别的页面解析它也不如专门写正则的脚本稳。但恰恰是在中小规模、数据结构频繁变化、人力有限的场景里它的价值最大。如果你正准备用它我的建议是先花半小时跑通官方示例再用一个你自己真实的页面做测试。等你试过 3 到 5 个不同网站后你基本就能感受到它在什么场景是强项在什么场景是弱项。还有一个更实际的小技巧项目写到一半可以把抓到的 HTML 保存成本地文件后续所有调试都用文件源不重复请求线上页面。既快又省钱还稳定。等你把提示词调好了再切回线上 URL 跑最终流程。这个小习惯能让你的调试效率提升不少。