
这次要聊的是两个经常放在一起使用的项目Firecrawl 和 pdf-inspector。前者是目前非常受 RAG、知识库和 LLM 应用开发者关注的网页抓取与内容提取工具核心能力是把网站、单页、PDF 等内容直接转换成干净的 Markdown 或结构化数据后者则用来检查 PDF 解析结果是否完整、是否乱码、表格是否保留。两个工具配合起来可以搭一条“网页/PDF 抓取 → 文本清洗 → 知识库/大模型应用”的处理链路。先说值不值得关注。Firecrawl 的核心卖点不是爬虫本身而是“为 LLM 而生的内容归一化”它抓完网页后不是给你一堆带导航、广告、弹窗的 HTML而是直接给出一份可以喂给模型的 Markdown 文本。对做本地知识库、RAG 问答、文档站镜像、批量资料采集的人来说这一步能省掉大量清洗脏数据的功夫。更友好的地方在于它自带搜索接口、爬整站接口和 API 服务也支持自托管部署社区版可以跑在自己的服务器上不依赖云端额度。云服务那边也有免费额度适合先小批量验证流程。pdf-inspector 在材料里没有特别详细的展开所以文章中我会把它作为一个“PDF 转换后的质量校验环节”来讲解它帮助你确认 Firecrawl 从 PDF 里抓出来的标题、正文、表格、页眉页脚是否真实可用。类似思路也可以直接用 Python 脚本实现针对批量 PDF 做基础体检。本文会覆盖环境准备、本地部署、接口调用、批量任务、资源占用观察和常见问题排查尽量按可落地的实操顺序来写。如果你想快速跑通一条“网页转 Markdown、PDF 转文本、批量进知识库”的管线这篇文章可以直接收藏。1. 核心能力速览能力项说明项目类型网页抓取与内容提取服务配套 PDF 内容校验工具主要功能单页抓取、整站爬取、关键词搜索、PDF 转 Markdown、结构化数据输出输出格式Markdown、HTML、结构化 JSON自托管方式Docker Compose 或源码运行常见依赖包括 PostgreSQL、Redis、Playwright 浏览器组件GPU 需求不需要 GPUCPU 和内存即可运行重点资源是带宽和磁盘是否支持 API支持自托管和云服务都提供 HTTP API是否支持批量任务支持可循环提交多个 URL或使用整站爬取任务队列免费额度云服务提供免费额度具体数值以官方平台实时页面为准自托管不受额度限制适用场景RAG 知识库采集、文档站归档、PDF 内容提取、SEO 研究、资讯监控使用边界需要遵守目标站点 robots 协议、版权要求和访问频率限制PDF 内容使用前需确认授权这里需要注意一个事实Firecrawl 的 API 路径和字段会随版本更新自托管版本与云服务也可能有差异。所以你在看接口示例时先把它当成“通用调用范式”实际部署后要以项目自带的 OpenAPI 文档和 README 为准。不要拿着旧版本的字段直接套到新版服务上排查接口问题时非常容易翻车。2. 适用场景与使用边界2.1 适合谁用从实际用途倒推Firecrawl 最合适的用户有这么几类。第一类是做大模型知识库的开发者。你需要把公司文档站、API 文档、产品手册、FAQ 页面批量抓下来转成 Markdown 后做向量化。用 Firecrawl 的好处是抽取出来的正文比较干净没有顶部导航、侧边栏、页脚和弹窗广告文本质量比直接用 requests 拉 HTML 再正则清洗高得多。第二类是做内容研究和情报监控的人。你可以用/v1/search按关键词搜索网页也可以定期用/v1/crawl把某个网站的最新文章同步到本地然后通过 diff 对比发现新增内容。这类需求里Firecrawl 相当于一个带解析能力的调度器省掉了自己造轮子的时间。第三类是做 PDF 数据集准备的人。Firecrawl 可以处理 PDF 文件和包含 PDF 链接的页面把 PDF 内容转成 Markdown。如果你在准备微调语料或 RAG 测试集pdf-inspector 或等效校验脚本可以在转换后批量检查文本完整性避免大量“坏样本”进入知识库。2.2 不适合什么场景Firecrawl 比较适合“公开可访问、内容相对静态”的页面。以下场景不建议硬用需要登录才能访问的账户后台、付费课程、会员资料这类内容抓取涉及授权问题不建议绕过。高频实时变化的接口型页面比如需要不断点击按钮才能加载动态数据的 Web 应用抓取结果可能不稳定。页面大量依赖视频、图片、音视频流的内容Firecrawl 主要提取文本媒体文件需要另做处理。需要严格遵守 robots 协议且明确禁止爬虫的站点不要用任何工具去绕。2.3 版权、隐私与安全边界这是必须重点强调的一块。Firecrawl 本身是合法开源工具但工具合法不意味着使用行为一定合规。抓取任何网站内容之前先确认该站点的服务条款和 robots.txt用于商用、公开传播或大模型训练的内容必须确认版权归属和授权范围。涉及 PDF 文档时尤其要注意很多 PDF 是有版权声明的不能抓下来就进公开数据集。涉及个人信息的页面抓取后要做好脱敏和访问控制不要把敏感数据暴露在公网接口上。3. 环境准备与前置条件Firecrawl 自托管对硬件要求不高但依赖比较多。从常见部署方式看核心组件包括一台能跑 Docker 的 Linux 服务器或 Windows / macOS 开发机。Docker 与 Docker Compose。如果不想用 Docker需要本地安装 Node.js 18 和相关运行时。PostgreSQL 数据库用于存储抓取任务、URL 记录和结果索引。Redis用于任务队列和缓存。Playwright 浏览器组件用于渲染 JavaScript 动态页面。至少 4GB 内存推荐 8GB 以上。主要是浏览器渲染进程和 API 服务比较吃内存。磁盘空间按抓取量规划。如果只是测试20GB 足够如果要做整站镜像和 PDF 批量入库建议准备 100GB 以上。如果只是先体验功能没必要一上来就自托管。建议先去云服务注册一个账号用免费额度把单页抓取、搜索、PDF 转换这几个接口跑通确认输出质量是否满足需求再决定是否部署自己的实例。这样可以省去很多依赖安装的时间。3.1 环境检查清单# 确认 Docker 版本 docker --version docker compose version # 确认 CPU 和内存 lscpu | grep Model name free -h # 确认磁盘空间 df -h /var/lib/docker在没有材料提供精确配置要求的情况下这个检查清单可以帮你快速判断当前机器能不能跑。一般 ECS 2 核 4G 可以跑起来但整站爬取时浏览器并发渲染会吃内存建议控制并发数。4. 本地部署自托管与一键启动4.1 使用官方 Docker Compose 部署从公开部署文档看Firecrawl 自托管主要围绕 API、Worker、Playwright 渲染服务和数据库组件展开。官方仓库通常会提供一份 docker-compose.yaml建议优先使用官方文件而不是自己手写配置。下面给出一个简化示意真实部署时以官方仓库文件为准# docker-compose.yml 简化示意请用官方仓库文件替换 version: 3.8 services: db: image: postgres:16 environment: POSTGRES_USER: firecrawl POSTGRES_PASSWORD: firecrawl POSTGRES_DB: firecrawl volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U firecrawl] interval: 5s timeout: 5s retries: 5 redis: image: redis:7 command: redis-server --appendonly yes healthcheck: test: [CMD, redis-cli, ping] interval: 5s timeout: 5s retries: 5 api: image: firecrawl-api-image depends_on: db: condition: service_healthy redis: condition: service_healthy environment: DATABASE_URL: postgresql://firecrawl:firecrawldb:5432/firecrawl REDIS_URL: redis://redis:6379 PORT: 3002 ports: - 3002:3002 volumes: - ./firecrawl-data:/app/data worker: image: firecrawl-worker-image depends_on: db: condition: service_healthy redis: condition: service_healthy environment: DATABASE_URL: postgresql://firecrawl:firecrawldb:5432/firecrawl REDIS_URL: redis://redis:6379 volumes: pgdata:使用方式# 把 docker-compose.yaml 放到项目目录后执行 docker compose pull docker compose up -d # 查看日志 docker compose logs -f api worker启动后访问http://127.0.0.1:3002浏览器打开可以看到 API 文档或健康检查页面。如果访问不到先查日志再看端口是否被占用。4.2 使用官方托管服务自托管适合批量生产环境。如果只是测试功能直接使用官方云服务更快。注册后拿到 API Key然后通过 HTTP 接口调用即可。云服务的免费额度适合小流量验证但每个账号的具体额度会随活动调整以官方页面显示为准。免费额度用完后再考虑自托管是比较理性的路径。4.3 源码启动方式不想用 Docker 时也可以 clone 仓库后按 README 安装依赖。# 通用模板具体命令以项目 README 为准 git clone firecrawl-repo cd firecrawl npm install npm run build npm start源码启动通常需要单独配置数据库和 Redis 连接环境变量比 Docker 方案多。除非你要二次开发否则更推荐 Docker Compose依赖管理更省心。5. pdf-inspectorPDF 内容质量检查工作流5.1 为什么要单独检查 PDF 转换结果Firecrawl 抓取 PDF 时核心动作是“把 PDF 里的文本抽取出来再转成 Markdown”。但 PDF 是排版文件不是纯文本文件很多情况下提取结果并不完美扫描版 PDF 没有文本层抓出来可能是空文本或乱码需要 OCR。双栏排版的论文文本抽取顺序可能错乱导致段落逻辑断裂。表格可能被拆成碎片或者合并成一段文字。页眉页脚、页码会混入正文。如果直接把这种结果送进知识库检索质量会受影响。pdf-inspector 的思路就是在批量入库之前对每个 PDF 的转换结果做一轮“体检”把可疑文件挑出来人工处理。5.2 通用 PDF 检查脚本下面是一个不依赖具体项目实现的基础检查思路使用 PyMuPDF 读取 PDF 的页数、文本长度和基础元信息。如果你遇到的是本地 PDF 文件可以直接用这个思路做筛查import fitz # PyMuPDF def inspect_pdf(pdf_path): doc fitz.open(pdf_path) total_chars 0 empty_pages [] print(f文件: {pdf_path}) print(f总页数: {doc.page_count}) for i, page in enumerate(doc): text page.get_text(text).strip() total_chars len(text) if len(text) 20: empty_pages.append(i 1) print(f总字符数: {total_chars}) print(f疑似空页: {empty_pages if empty_pages else 无}) meta doc.metadata print(f标题: {meta.get(title)}) print(f作者: {meta.get(author)}) doc.close() if __name__ __main__: inspect_pdf(sample.pdf)这个脚本只能做基础判断。如果要检查 Firecrawl 转换后的 Markdown 是否完整可以再写一个对比逻辑统计 PDF 里的标题数量、页数和 Markdown 文件里的标题数量、段落数做交叉验证偏差大的文件单独标记。import re def inspect_markdown(md_path): with open(md_path, r, encodingutf-8) as f: content f.read() headings re.findall(r^#{1,6}\s, content, flagsre.MULTILINE) paragraphs [p for p in content.split(\n\n) if p.strip()] print(fMarkdown 标题数: {len(headings)}) print(fMarkdown 段落数: {len(paragraphs)}) print(f总字符数: {len(content)})把这两个脚本串起来就能在批量任务里对每个 PDF 输出一份“体检报告”。判断标准建议设置为页数差距超过设定阈值、空页超过 N 页、Markdown 标题数为 0 等满足任一条件即判定为异常文件。5.3 与 Firecrawl 的配合方式实际使用中pdf-inspector 不一定是一个独立程序更多的是一个“校验环节”。流程可以这样设计Firecrawl 抓取 PDF 并把结果保存为 Markdown。保存原始 PDF 文件到本地。对原始 PDF 执行基础信息检查。对转换后的 Markdown 执行结构和长度检查。输出一份 CSV 报告人工查看异常项。import csv import os def generate_report(pdf_dir, md_dir, output_csv): rows [] for filename in os.listdir(pdf_dir): if not filename.lower().endswith(.pdf): continue pdf_path os.path.join(pdf_dir, filename) md_path os.path.join(md_dir, filename.replace(.pdf, .md)) if not os.path.exists(md_path): rows.append({pdf: filename, status: markdown_missing}) continue # 实际项目里在这里调用 inspect_pdf 和 inspect_markdown rows.append({pdf: filename, status: checked}) with open(output_csv, w, newline, encodingutf-8) as f: writer csv.DictWriter(f, fieldnames[pdf, status]) writer.writeheader() writer.writerows(rows) if __name__ __main__: generate_report(./pdfs, ./markdowns, report.csv)这段代码是可运行的通用模板核心是帮你建立一个“有据可查”的校验流程。批量处理 PDF 时千万不要省掉这一步否则很难定位是抓取环节的问题还是解析环节的问题。6. Firecrawl 功能测试与效果验证6.1 单页抓取测试先从最简单的开始抓取一个网页并转成 Markdown。curl -X POST http://127.0.0.1:3002/v1/scrape \ -H Content-Type: application/json \ -d { url: https://example.com/docs/getting-started, formats: [markdown] }预期结果是返回 JSON其中data.markdown字段包含页面正文的 Markdown 内容。判断成功的标准很简单Markdown 里没有导航菜单、没有弹窗文案正文段落完整。常见失败原因有两个页面是纯 JavaScript 渲染但配置里没有启用浏览器渲染导致抓到的只有空白框架。目标站点有反爬限制返回 403 或验证码页面。此时需要检查抓取配置是否启用了真实浏览器模式和延迟策略。6.2 整站爬取测试整站爬取使用/v1/crawl接口通常分两步先提交任务再轮询结果。# 提交爬取任务 curl -X POST http://127.0.0.1:3002/v1/crawl \ -H Content-Type: application/json \ -d { url: https://example.com/docs, limit: 50, maxDepth: 2 }响应里一般包含一个任务 ID例如{id: crawl_xxx}。随后用这个 ID 查询任务状态curl http://127.0.0.1:3002/v1/crawl/crawl_xxx如果所有页面抓取完成返回结果里会包含每个 URL 的 Markdown 内容。判断成功标准是任务状态为完成页面数量接近预期且没有大量抓取失败记录。分批测试时建议先把limit设小一点比如 10 个页面。等确认页面结构没问题再放宽到全站。直接全站抓一个 5000 页的大站很容易被反爬机制盯上。6.3 PDF 抓取与转换测试测试 PDF 转换时可以直接给一个 PDF 文件的公开 URLcurl -X POST http://127.0.0.1:3002/v1/scrape \ -H Content-Type: application/json \ -d { url: https://example.com/files/report.pdf, formats: [markdown] }预期结果是把 PDF 内容转换后的 Markdown 放在data.markdown中。判断标准PDF 有文本层时内容应完整提取。扫描版 PDF 如果没有 OCR 支持可能返回空文本或乱码需要另接 OCR 服务。表格和代码块可能丢失格式需要结合 pdf-inspector 做质量评分。对于本地 PDFFirecrawl 可能也支持上传方式具体以当前版本 API 文档为准。如果本地 PDF 很多更推荐先用脚本批量抽取文本再组装成 Markdown最后一个批次通过 API 写入知识库。6.4 搜索功能测试搜索接口适合做信息收集。比如你想找一批关于“大模型 Agent”的公开文章curl -X POST http://127.0.0.1:3002/v1/search \ -H Content-Type: application/json \ -d { query: large language model agent, limit: 5 }返回结果通常包含搜索结果列表和每篇页面的 Markdown 内容。这个功能适合做关键词监控和竞品内容分析但要注意返回内容仅限公开可抓取的网页不要把搜索结果直接用于商用语义训练。7. 接口 API 与批量任务设计7.1 使用 Python 调用 API下面是一个 Python 请求模板可以封装成通用抓取函数。实际使用时需要把http://127.0.0.1:3002/v1/scrape替换成你的服务地址并处理鉴权字段。import requests import time import json API_URL http://127.0.0.1:3002/v1/scrape API_KEY # 自托管可以不填云服务需要填 def scrape_url(url, formats(markdown,)): headers {Content-Type: application/json} if API_KEY: headers[Authorization] fBearer {API_KEY} payload { url: url, formats: list(formats), } resp requests.post(API_URL, jsonpayload, headersheaders, timeout120) resp.raise_for_status() return resp.json() if __name__ __main__: result scrape_url(https://example.com) print(json.dumps(result, ensure_asciiFalse, indent2))这是一个可运行的最小示例。判断接口是否跑通的标准返回 JSON 中success为 true且data.markdown非空。如果返回 401检查 API Key 或请求头如果返回 408 超时可能是目标站点响应太慢或浏览器渲染等待时间不足。7.2 批量任务多 URL 抓取与结果落盘批量抓取的核心思路是读入 URL 列表逐个调用接口保存 Markdown 到本地目录同时记录成功和失败日志。import os import json import logging from datetime import datetime logging.basicConfig( filenamecrawl_batch.log, levellogging.INFO, format%(asctime)s %(levelname)s %(message)s ) SAVE_DIR ./markdown_output FAIL_LOG ./failed_urls.json os.makedirs(SAVE_DIR, exist_okTrue) def process_urls(url_list): failed [] for idx, url in enumerate(url_list, start1): try: result scrape_url(url) content result.get(data, {}).get(markdown, ) if not content: raise ValueError(empty markdown) safe_name url.replace(https://, ).replace(http://, ).replace(/, _)[:80] with open(os.path.join(SAVE_DIR, f{idx}_{safe_name}.md), w, encodingutf-8) as f: f.write(content) logging.info(f[OK] {url}) print(f[{idx}/{len(url_list)}] OK: {url}) except Exception as e: logging.error(f[FAIL] {url}: {e}) failed.append({url: url, error: str(e), time: str(datetime.now())}) with open(FAIL_LOG, w, encodingutf-8) as f: json.dump(failed, f, ensure_asciiFalse, indent2) if __name__ __main__: urls [ https://example.com/docs/page1, https://example.com/docs/page2, ] process_urls(urls)批量任务建议遵循几个约定每抓完一个 URL立即写盘避免内存里堆大量文本。日志里同时记录成功和失败失败原因要具体到状态码或异常类型。失败任务不要立即重试放在一个队列里统一二次处理避免雪崩。7.3 批量任务的延时与限速批量抓取最容易踩的坑就是频率太高被目标站封禁。建议在循环体内加time.sleep比如time.sleep(1)表示每秒最多一个请求。生产环境更稳妥的做法是维护一个独立队列使用 Redis 做任务分发每个 Worker 处理一个 URL并按域名拆分限速。这样即使同时跑几十个任务也能保证对每个站点都处于低频访问状态。7.4 免费额度的使用建议如果使用云服务免费额度批量任务要提前规划。免费额度适合验证接口、测试输出质量和小规模演示不适合直接跑全站抓取。建议先在本地自托管试跑确认逻辑没问题后再决定是否购买付费额度。自托管没有额度概念但你需要承担服务器带宽、磁盘和数据库维护成本两者各有利弊。8. 资源占用与性能观察8.1 自托管资源占用Firecrawl 自托管不是 GPU 任务核心资源消耗集中在内存、CPU、磁盘和带宽上。可以从这几个维度观察# Docker 容器资源占用 docker stats # 系统整体状态 htop # 磁盘占用 du -sh ./markdown_output df -h从常见部署情况看API 服务本身占用内存不高但 Playwright 负责渲染 JavaScript 页面时每个浏览器实例会消耗几百 MB 内存。如果你同时并发 5 个页面渲染内存占用会迅速上升。启动后如果发现内存占用偏高优先检查并发数和浏览器实例数。8.2 影响性能的关键因素单页内容长度正文超长的页面转 Markdown 时间更长。是否启用 JavaScript 渲染不渲染静态页面很快渲染动态页面需要额外启动浏览器耗时和内存都显著增加。PDF 文件大小一个 100MB 的 PDF 扫描件解析时间要比普通小文件长很多同时内存占用也高。目标站点响应速度服务器响应慢会直接拖慢抓取任务建议设置合理的超时时间。并发数并发越高总吞吐越大但被反爬封禁的概率也越高。初次测试建议并发为 1。8.3 如何降低资源占用如果机器配置不高可以从这几个方向优化关闭或减少 JavaScript 渲染只对确实需要渲染的页面启用。批量任务限速设置每请求之间的间隔。限制整站爬取的总页面数和最大深度。定期清理数据库中的历史任务记录避免任务表无限膨胀。Markdown 结果使用压缩存储或直接落盘为文件减少数据库体积。9. 常见问题与排查方法问题现象可能原因排查方式解决方案自托管服务启动后页面打不开端口被占用或依赖未启动查看 docker compose 日志检查端口监听换端口或重启依赖容器抓取结果返回空 Markdown页面是动态渲染但未启用浏览器或页面被反爬拦截用浏览器打开确认页面内容检查返回状态码启用 JS 渲染设置延迟重试PDF 抓取后内容乱码扫描版 PDF 没有文本层用 pdf-inspector 检查文本层是否存在接入 OCR 服务做识别爬取任务一直 pendingRedis 或 Worker 没有正常消费队列查看 worker 日志检查 Redis 连接重启 worker确认队列连接批量任务中途大量失败并发过高触发目标站限流查看日志中的状态码降低并发增加 sleep 间隔API 返回 401API Key 缺失或错误检查请求头和云服务 Key修正鉴权字段数据库连接失败DATABASE_URL 配置错误或 PostgreSQL 未初始化查看 API 容器日志检查连接串、数据库账号和网络Markdown 里有大量广告残留目标页面广告动态注入或抽取规则不够严格对比原始页面与 Markdown 片段在配置中指定正文选择器磁盘占用增长过快整站爬取保存了太多页面查看 markdown 目录和数据库大小设置更大的爬取间隔清理历史任务抓取稳定性差时好时坏目标站点有反爬策略或 CDN 变更观察失败时间点和频率降低频率使用分布式抓取时隔离域名10. 最佳实践与使用建议10.1 先小批量再全量我第一次跑 Firecrawl 整站爬取时习惯先把limit设为 10确认输出质量和频率都没问题再放宽到 100 或全站。这个习惯在自托管场景尤其重要因为整个任务队列跑起来后如果数据源站点临时变更页面结构你会浪费大量请求和时间。10.2 保留原始内容Firecrawl 输出 Markdown 后不要直接删掉原始 HTML 或 PDF。保留原始文件的好处是当你发现提取规则有问题时可以回看原始内容重新处理。建议目录结构做成这样project/ ├── raw/ # 原始 HTML / PDF ├── markdown/ # 提取后的 Markdown ├── reports/ # 校验报告 └── configs/ # 抓取配置文件10.3 批量任务必须有日志和重试批量任务只要超过 50 个 URL就应该有完善的日志和失败重试机制。日志记录每个 URL 的状态、耗时、错误类型重试时建议做指数退避不要失败后立刻重试。对于反复失败的 URL先查反爬策略再调整抓取参数。10.4 接口服务控制访问范围自托管 API 服务默认可能监听所有网络接口。如果是自己调试建议监听127.0.0.1如果必须局域网访问要加鉴权或放在内网反向代理后面不要直接把未鉴权的 API 暴露到公网。10.5 合规意识要前置Firecrawl 是工具使用责任在操作者。抓取前看 robots.txt抓取后看内容授权商用前看版权声明。涉及 PDF 文档、图片、人物信息时额外确认是否涉及隐私和个人信息保护。任何工具都不该被用来抓取账号内数据、绕过付费墙或大规模收集个人信息。11. 总结与下一步Firecrawl 最值得尝试的点是它能快速把复杂的网页和 PDF 变成干净的 Markdown这和常见爬虫工具的体验差别很明显。如果你想先验证一波就先注册云服务用免费额度跑一个单页抓取再试一个 PDF 抓取重点看输出格式是否满足你的知识库要求。如果确认可用再考虑 Docker Compose 自托管。最容易踩的坑有三个第一动态页面忘记开 JavaScript 渲染抓到空内容第二批量任务并发太快被目标站限流第三PDF 扫描件直接抓取得到乱码没有接 OCR。这些在初测时都要重点观察。下一步可以按这个方向继续扩展把 Firecrawl 接进 RAG 流水线定期抓取文档站并增量更新向量库或者在 pdf-inspector 基础上增加自动校验规则把异常 PDF 自动丢给 OCR 服务二次处理。整个链路打通后维护一个高质量的知识库数据源会轻松很多。建议收藏备用方便需要的时候直接照着搭。