2026-01-22

01月22日

一、今日完成情况

  • 把Deepseek接口切换为通义千问模型接口,然后微调prompt,让大模型的输出关于时间和地点有规范,输出100条抽象数据再让师兄审核,没问题的话,可以部署在服务器上。 –完成
    • 1、修改代码修改模型接口、修改提示词 Tongyi-Zhiwen/QwenLong-L1-32B
      • 提示词模糊点:实体的定义,这里有些模棱两可的判定–零星冲突、自民党宣布退出政府、最终投票、欧洲央行(ECB)下次会议
      • 时间方面:
        • task1- “ISO 8601时间格式 (YYYY-MM-DDTHH:MM:SS)”
        • task2-(YYYY-MM-DD 或 YYYY-MM-DD HH:MM)
        • task3-ISO 8601时间格式 (YYYY-MM-DDTHH:MM:SS)
    • 2、批量导出100条数据,看看有什么争议点 –完成
    • 3、部署到服务器,解放笔记本(推迟,等到规则确定之后再说)
  • dify工作流配置,实现一个好玩的效果 –未全部完成
    • 实现效果: 你输入一个 B 站视频链接,Dify 自动抓取字幕,生成一份“太长不看”的摘要,甚至帮你把内容改写成一篇小红书/推特风格的笔记。 –未完成
      • 1、视频链接解析agent,导出音频或者文字内容
        • 需要API接口(服务器)对视频进行解析服务,我打算使用实验室服务器 –已完成
        • 需要whisper本地音频解析,会快很多,我打算配置实验室显卡。 –完成
      • 2、内容总结按照提示词模板,总结内容agent
  • 关于记忆承载公众号文章批量导出的顺序标号–按照时间顺序导出而不是混乱的顺序。 –有思路
    • 因为导出的时候,是没有顺序的,现在我可以导出为Excel表格,时间和标题一一对应的方式,这样的话,我就可以通过程序,搜索Excel和markdown文件的标题,从而批量修改文章的标题。从而对文章批量命名, 达成我的文章顺序按照发布时间来的效果。 –明天在干,今天拉满了没力气了。
  • firecrawl 配置完成 –好用的爬虫工具
    • Docker形式的配置
    • 分别安装包进行配置

二、今日感悟

  • 核心业务数据​:
    • 实验室要求的数据导出技术模型替换,并且使用操作系统的思路,异步处理,两个AI的API异步工作,从而实现并行的效果,效率大幅提高,未来需要1000+数据的话,直接让其在服务器上跑一天,肯定数量达标了。
  • ​今日工作总结:​
    • 学习技术还是要看官方的文档,今天完成firecrawl的时候,用了csdn 的方法走弯路了,之后找到官方资料,直接手把手教,顺利的很
    • 爬虫还是遇到用户登录的问题,效果一般,可以覆盖的范围还是小了点。所以,花钱能解决的还是建议花钱,自己琢磨技术非常困难,必要时候拿来主义。
  • ​明日工作计划:
    • 学习一下师兄让我了解诶的两个技术和术语,不需要太深入。
    • 使用自己部署的crawl服务,让我的dify工作流访问。
    • dify打通一下B站字幕总结的问题,whisper本地模型导出速度凑合,
  • ​今日学习成长:​
    • 耐心很重要啊,实验室研三师兄旁边的机械键盘咔哧咔哧,还在打游戏听的我心慌,然后晚上回到寝室,室友双排英雄联盟,一直在说话,我也可以静下来来慢慢调试,我相信自己内心的平静可以战神一切噪音
    • 还有,感觉室友这样放假之后每天打游戏好没有一丝,我这样的生活搞个一星期就受不了,我的基因里面就是折腾,一成不变的,没有输入没有思考没有成果的生活,才不是我想要的。

三、备注

四、实验室服务器whisper和 pytorch配置

1、本地部署

显卡型号

Pasted image 20260122135826
  • 显卡:2 张 NVIDIA A100 80GB PCIe(这是目前市面上单卡显存最大的型号之一)。
  • CUDA 版本12.4(非常新,完全支持最新的 PyTorch 2.x)。
  • 显存状态:GPU 0 还有约 48GB 剩余,GPU 1 几乎全空(79GB 剩余)。

是市面上最高的配置,不训练大模型,日常使用模型足够了

安装对应版本pytorch

# 确保你已经激活环境
conda activate whisper_server

# 安装配套 CUDA 12.1 运行库的 PyTorch (完全兼容 12.4 驱动)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
# 安装 faster-whisper (核心库)
pip install faster-whisper

# 安装 FFmpeg (Conda 安装最省事,处理音频流必备)
conda install -c conda-forge ffmpeg -y

# 安装 FastAPI (如果你要给 Dify 做接口)
pip install fastapi uvicorn python-multipart
python -c "import torch; print(f'CUDA是否可用: {torch.cuda.is_available()}'); print(f'当前显卡: {torch.cuda.get_device_name(0)}')"
Pasted image 20260122141002

现在运行刚才的示例代码网络不通,即使我开启了代理,并且可以访问到谷歌:

python -c "import os; print(f'HTTP:', os.environ.get('http_proxy')); print(f'HTTPS:', os.environ.get('https_proxy'))"
Pasted image 20260122144456

现在直接在python内部配置实验室代理访问huggingface,打通了:

python -c "import requests; proxies={'https': 'http://kb314314.asuscomm.com:8007'}; print('状态码:', requests.get('https://huggingface.co', proxies=proxies, timeout=10).status_code)"
Pasted image 20260122144633

为了以后使用python服务,和使用apt get下载安装包,一劳永逸的解决这个问题,我可以使用

# 编辑 root 的 bashrc
echo 'export http_proxy="http://kb314314.asuscomm.com:8007"' >> ~/.bashrc
echo 'export https_proxy="http://kb314314.asuscomm.com:8007"' >> ~/.bashrc
echo 'export all_proxy="http://kb314314.asuscomm.com:8007"' >> ~/.bashrc
source ~/.bashrc

全部写进全局变量,默认都是用代理即可。
依然没解决, 不打算在代码当中下载大模型了,直接手动下载,代码当中指定就可以了。

mkdir -p /root/code/whisper_code/models/large-v3
cd /root/code/whisper_code/models/large-v3

# 使用镜像站,绕过代理,直接下载核心模型文件 (约 3GB)
wget https://hf-mirror.com/Systran/faster-whisper-large-v3/resolve/main/model.bin
wget https://hf-mirror.com/Systran/faster-whisper-large-v3/resolve/main/config.json
wget https://hf-mirror.com/Systran/faster-whisper-large-v3/resolve/main/tokenizer.json
wget https://hf-mirror.com/Systran/faster-whisper-large-v3/resolve/main/vocabulary.json

当然下载完毕之后,需要配置一个文件如下,需要手动指定新模型的维度,不然会报错:

cd /root/code/whisper_code/models/large-v3/

现在可以转化了,我发现还是很慢呀,即使现在有了显卡,我真是大失所望:

========================================
📊 转录任务完成!
🎵 音频总长度: 1324.33 秒
⚡ A100 处理耗时: 70.91 秒
🚀 效率倍数: 18.7x (比实时快 18.7 倍)
📂 结果已保存至: output/test.md

import os
import time
import torch
from faster_whisper import WhisperModel

# 1. 环境准备
torch.cuda.empty_cache()
input_file = "test.mp3"  # 你的音频文件名
output_dir = "output"
local_model_path = "/root/code/whisper_code/models/large-v3"

if not os.path.exists(output_dir):
    os.makedirs(output_dir)

# 获取不带后缀的文件名用于导出
base_name = os.path.splitext(os.path.basename(input_file))[0]
md_filename = os.path.join(output_dir, f"{base_name}.md")

# 2. 模型加载 (这部分不计入转录耗时)
print("🚀 正在加载模型...")
model = WhisperModel(
    local_model_path, 
    device="cuda", 
    device_index=0, 
    compute_type="float16"
)

# 3. 执行转录并计时
print(f"✅ 开始处理: {input_file}")
start_time = time.time()  # 记录开始时间

# transcribe 返回的是生成器,在遍历 segments 时才会真正触发 GPU 推理
segments, info = model.transcribe(input_file, beam_size=5)

# 准备 Markdown 内容
md_content = f"# 语音转录报告: {input_file}\n\n"
md_content += f"- **检测语言**: {info.language} ({info.language_probability:.2f})\n"
md_content += f"- **音频时长**: {info.duration:.2f} 秒\n\n"
md_content += "| 时间轴 | 转录内容 |\n| :--- | :--- |\n"

# 遍历结果
for segment in segments:
    line = f"| {segment.start:.2f}s -> {segment.end:.2f}s | {segment.text.strip()} |\n"
    md_content += line
    # 实时打印进度(可选)
    print(f"[{segment.start:>6.2f}s] {segment.text}")

end_time = time.time()  # 记录结束时间

# 4. 计算指标
processing_time = end_time - start_time
speed_ratio = info.duration / processing_time if processing_time > 0 else 0

# 5. 保存文件
with open(md_filename, "w", encoding="utf-8") as f:
    f.write(md_content)

# 6. 打印核心日志
print("\n" + "="*40)
print(f"📊 转录任务完成!")
print(f"🎵 音频总长度: {info.duration:.2f} 秒")
print(f"⚡ A100 处理耗时: {processing_time:.2f} 秒")
print(f"🚀 效率倍数: {speed_ratio:.1f}x (比实时快 {speed_ratio:.1f} 倍)")
print(f"📂 结果已保存至: {md_filename}")
print("="*40)

2、踩坑总结

坑一:Conda 25.11+ 版本服务条款限制

  • 现象:创建环境时报错 CondaToSNonInteractiveError,提示未接受条款。
  • 核心原因:新版 Conda 强化了对 Anaconda ToS 的显式确认要求。
  • 解决方法:需手动执行 conda tos accept --channel ... 授权后方可继续。

坑二:Hugging Face 境内网络连接阻塞

  • 现象:运行代码时卡在 WhisperModel 初始化阶段,报错 Network is unreachable 或长时间无响应。
  • 核心原因:境内服务器无法直连 Hugging Face 存储库,且 requests 库有时无法识别 bash 中的临时代理。
  • 一劳永逸法
    • 使用 HF-Mirror 镜像站:export HF_ENDPOINT=https://hf-mirror.com
    • 本地化加载:使用 huggingface-cli 提前下载模型,代码中改用绝对路径加载,彻底断开网络依赖。

坑三:Whisper v3 维度不匹配 (80 vs 128)

  • 现象:报错 ValueError: Invalid input features shape: expected (1, 128, 3000), but got (1, 80, 3000)
  • 核心原因:Whisper large-v3 将梅尔刻度(Mel bins)从 80 提升到了 128。如果模型文件夹中缺失 preprocessor_config.json,代码会降级使用旧版的 80 维处理音频。
  • 解决方法:手动补全该配置文件,并确保其中 n_mels 设置为 128。同时需保持 faster-whisperctranslate2 库为最新版本。

坑四:A100 显存溢出与多卡管理 (OOM)

  • 现象:报错 RuntimeError: CUDA failed with error out of memory
  • 核心原因:实验室服务器通常为多人共用。虽然 A100 显存巨大(80GB),但若默认的 GPU 1 已被占满,新进程将无法申请显存。
  • 解决方法
    • 通过 nvidia-smi 实时监控显存。
    • 在代码中显式指定空闲显卡:device_index=0
    • 必要时使用 int8_float16 量化进一步压缩显存占用。

坑五:代理环境配置的“瞬时性”

  • 现象:在 Shell 中开启代理后,Python 脚本有时仍提示连接失败。
  • 核心原因:临时环境变量仅对当前会话有效,且在 Conda 环境切换时可能失效。
  • 一劳永逸法
    • 利用 Conda 的 activate.d 脚本功能,实现 “进入环境即开启代理,退出环境即关闭” 的自动化配置。
    • 通过 ~/.bashrc 封装 proxy_on 函数,快速控制 Git 和全局网络。

3、API速度测试

groq是公认全球语言转文字最快的,他们的硬件加速做的非常好,现在我就尝试一下:

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
import os
from groq import Groq

client = Groq()
filename = os.path.dirname(__file__) + "/audio.m4a"

with open(filename, "rb") as file:
    transcription = client.audio.transcriptions.create(
      file=(filename, file.read()),
      model="whisper-large-v3-turbo",
      temperature=0,
      response_format="verbose_json",
    )
    print(transcription.text)

Grok,Xai,第二个API,适用于CLine,vscode配置,新出的模型上下文能力强,而且价格划算:
cc

xai-4wX1Mg8sL6xdVyXwjqPX4yelbC48rjz1qIE7ezxizaY84ekIH80cFGVH4qexLPO9e4uiTKjPeoCWlAAr

可以看到,现在世界上whisper最快的模型,做的最好的公司,在面对18min长度的音频,速度是6s,这个速度才是我非常满意的,当然这个应该是最贵的,额度最少的,我现在使用国内的最强配置看看效果是怎么样的,看看区别是怎么样的。

groq模型:
Processing time: 5.98 seconds
Efficiency: 3.35 words/second

据说,国产阿里的模型,sensevoicesmall的模型是性能最强的,对于中文的适配性是最好的,下面尝试一下:

模型名称 架构类型 速度倍数 (对比 Large-v3) 中文 CER (Aishell-1) 显存占用
SenseVoiceSmall 非自回归 (国产) 15x ~3.0% (中文/粤语领先) ~4GB
Whisper Turbo-zh 4层解码器 (微调) 6x 3.07% ~6GB
Whisper Large-v3 全量解码器 (原生) 1x (基准) 8.08% ~10GB

4、国产模型环境配置

# 1. 创建并进入目录
mkdir -p ~/code/SenseVoiceSmall
cd ~/code/SenseVoiceSmall

# 2. 创建新环境(建议 Python 3.10)
conda create -n sensevoice python=3.10 -y
conda activate sensevoice

# 3. 开启你配置好的代理(确保下载顺利)
proxy_on
# 1. 安装 PyTorch (针对你的 CUDA 12.4 驱动)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

# 2. 安装 FunASR 和模型下载工具 ModelScope
pip install funasr modelscope huggingface_hub

# 3. 安装音频处理插件
pip install librosa soundfile
# 创建模型存放目录
mkdir -p models
cd models

# 使用 python 脚本下载模型
python -c "from modelscope import snapshot_download; snapshot_download('iic/SenseVoiceSmall', local_dir='./iic/SenseVoiceSmall')"

cd ..
import os
import time
import torch
from funasr import AutoModel

# 1. 配置路径与环境
model_dir = "./models/iic/SenseVoiceSmall"
input_file = "test.mp3"  # 请确保目录下有此文件
output_dir = "output"

if not os.path.exists(output_dir):
    os.makedirs(output_dir)

# 2. 加载模型 (针对 A100 优化)
print("🚀 正在加载 SenseVoiceSmall 模型...")
model = AutoModel(
    model=model_dir,
    device="cuda:0",        # 使用 GPU 0
    disable_update=True     # 禁用自动更新检查
)

# 3. 执行推理与计时
print(f"✅ 开始处理: {input_file}")
start_time = time.time()

# SenseVoiceSmall 支持情感、内容、语种同时识别
res = model.generate(
    input=input_file,
    cache={},
    language="zh",          # 显式指定中文提高准确度
    use_itn=True,           # 开启 ITN (数字转写优化)
    batch_size_s=60, 
    merge_vad=True
)

end_time = time.time()

# 4. 解析结果并统计
processing_time = end_time - start_time
text_result = res[0]['text']

# 这里通过 librosa 获取音频时长用于计算倍速
import librosa
audio_duration = librosa.get_duration(path=input_file)
speed_ratio = audio_duration / processing_time

# 5. 导出 Markdown
base_name = os.path.splitext(os.path.basename(input_file))[0]
md_filename = os.path.join(output_dir, f"{base_name}_sensevoice.md")

md_content = f"# SenseVoiceSmall 转录报告\n\n"
md_content += f"- **音频时长**: {audio_duration:.2f} 秒\n"
md_content += f"- **处理耗时**: {processing_time:.2f} 秒\n"
md_content += f"- **效率倍数**: {speed_ratio:.1f}x\n\n"
md_content += "## 转录内容\n\n"
md_content += text_result

with open(md_filename, "w", encoding="utf-8") as f:
    f.write(md_content)

# 6. 打印日志
print("\n" + "="*40)
print(f"📊 SenseVoice 任务完成!")
print(f"🎵 音频时长: {audio_duration:.2f}s")
print(f"⚡ A100 耗时: {processing_time:.2f}s")
print(f"🚀 速度对比: 比实时快 {speed_ratio:.1f} 倍")
print(f"📂 结果保存至: {md_filename}")
print("="*40)

如果时间可以打到10s左右,我也是比较满意的状态了,超过的话,那对于没有耐心的朋友来说,就不太友好了。

========================================
📊 SenseVoice 任务完成!
🎵 音频时长: 1078.70s
⚡ A100 耗时: 20.79s
🚀 速度对比: 比实时快 51.9 倍

是刚才本地跑的whisper的速度的三倍,不过还是没能满足我的耐心,还是有些慢,现在尝试一下国产API的速度。

========================================
✨ DashScope API 任务完成!
🎵 音频时长: 1078.70s
⚡ API 总耗时 (含上传/排队/推理): 0.55s
🚀 效率倍数: 1949.2x
📝 文本预览: …

???,有猫腻,不正常。

到饭点了,明天再玩这个显卡。

音频格式转化简单记录一下,记住语法最好:

ffmpeg -i test.mp3 -ar 16000 -ac 1 -f s16le test.pcm

七、firecrawl本地Docker部署

1、部署教程

https://docs.firecrawl.dev/zh/contributing/guide

拉取镜像

git clone git@github.com:firecrawl/firecrawl.git

配置数据库

apps/nuq-postgres 目录下:

docker build -t nuq-postgres .

需要再终端开启代理,不然部署会失败。

docker run --name nuqdb -e POSTGRES_PASSWORD=postgres -p 5433:5432 -v nuq-data:/var/lib/postgresql/data -d nuq-postgres

环境变量配置

在 /apps/api/ 目录下的 .env 中设置环境变量


# ===== 必需的环境变量 ======
NUM_WORKERS_PER_QUEUE=8
PORT=3002
HOST=0.0.0.0
REDIS_URL=redis://localhost:6379
REDIS_RATE_LIMIT_URL=redis://localhost:6379

## 要启用数据库认证,你需要配置 Supabase。
USE_DB_AUTHENTICATION=false

## 使用 PostgreSQL 进行队列——如果凭据、主机或数据库不同,请修改
NUQ_DATABASE_URL=postgres://postgres:postgres@localhost:5433/postgres

# ===== 可选的环境变量 ======

# Supabase 配置(用于支持数据库认证、增强日志等)
SUPABASE_ANON_TOKEN=
SUPABASE_URL=
SUPABASE_SERVICE_TOKEN=

# 其他可选项
TEST_API_KEY= # 如果你已启用认证并想用真实 API 密钥进行测试,可在此填写
OPENAI_API_KEY= # 如需启用依赖 LLM 的功能(例如生成图片替代文本),请添加
BULL_AUTH_KEY= @
PLAYWRIGHT_MICROSERVICE_URL=  # 如需启用 Playwright 回退,请设置
LLAMAPARSE_API_KEY= # 如果你有 Llamaparse 密钥并想用于解析 PDF,请设置
SLACK_WEBHOOK_URL= # 如需发送 Slack 服务器健康状态消息,请设置
POSTHOG_API_KEY= # 如需发送 PostHog 事件(如作业日志),请设置
POSTHOG_HOST= # 如需发送 PostHog 事件(如作业日志),请设置

依赖项安装

# cd apps/api # 确认你在正确的目录
pnpm install
Pasted image 20260122202541

等待2min,如果没有pnpm的话,使用homebrew安装一下。

命令报错,原因是没有安装rust语言环境,使用如下指令安装:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

在当前终端生效:

source $HOME/.cargo/env

安装go的依赖工具,这个项目涉及到go,rust语言:

brew install go

再次pnpm install即可,现在没有报错,继续下一步。

三终端配置启动

终端一

redis-server
Pasted image 20260122203954

终端二

进入 apps/api/ 目录并运行:

pnpm start
# 如果你要使用 [llm-extract 功能](https://github.com/firecrawl/firecrawl/pull/586/),还需要导出 OPENAI_API_KEY=sk-______

报错如下:

ℹ Installing Go dependencies
> **go@install**     cd sharedLibs/go-html-to-md && go mod tidy
**go@install**     go: downloading github.com/firecrawl/html-to-markdown v0.0.0-20260103214238-c035ce0e6258
**go@install**     go: downloading github.com/PuerkitoBio/goquery v1.10.3
**go@install**     go: downloading golang.org/x/net v0.41.0
**go@install**     go: html-to-markdown.go imports
**go@install**     github.com/PuerkitoBio/goquery: github.com/PuerkitoBio/goquery@v1.10.3: Get "https://proxy.golang.org/github.com/%21puerkito%21bio/goquery/@v/v1.10.3.zip": dial tcp 142.250.77.17:443: i/o timeout
**go@install**     go: html-to-markdown.go imports
**go@install**     github.com/firecrawl/html-to-markdown: github.com/firecrawl/html-to-markdown@v0.0.0-20260103214238-c035ce0e6258: Get "https://proxy.golang.org/github.com/firecrawl/html-to-markdown/@v/v0.0.0-20260103214238-c035ce0e6258.zip": dial tcp 142.250.77.17:443: i/o timeout
**go@install**     go: html-to-markdown.go imports
**go@install**     github.com/firecrawl/html-to-markdown/plugin: github.com/firecrawl/html-to-markdown@v0.0.0-20260103214238-c035ce0e6258: Get "https://proxy.golang.org/github.com/firecrawl/html-to-markdown/@v/v0.0.0-20260103214238-c035ce0e6258.zip": dial tcp 142.250.77.17:443: i/o timeout
**go@install**     go: html-to-markdown.go imports
**go@install**     golang.org/x/net/html: golang.org/x/net@v0.41.0: Get "https://proxy.golang.org/golang.org/x/net/@v/v0.41.0.zip": dial tcp 142.250.77.17:443: i/o timeout
✗ **go@install**     30.6s (1)
✗ Fatal error occurred
Error: go@install failed with exit code 1
    at ChildProcess.<anonymous> (/Users/kipley/Documents/code/Docker/firecrawl/firecrawl/apps/api/dist/src/harness.js:262:24)
    at ChildProcess.emit (node:events:508:28)
    at maybeClose (node:internal/child_process:1085:16)
    at ChildProcess._handle.onexit (node:internal/child_process:304:5)
 ELIFECYCLE  Command failed with exit code 1.

经分析,是代理的问题,go的代理配置:

1、在终端运行以下命令(设置全局代理):

go env -w GOPROXY=https://goproxy.cn,direct

2、验证设置是否生效

go env | grep GOPROXY

如果输出 GOPROXY="https://goproxy.cn,direct",说明设置成功。

再次运行pnmp start,还是报错,错误是502报错

 reading https://goproxy.cn/github.com/sebdah/goldie/v2/@v/v2.5.3.zip: 502 Bad Gateway
✗ **go@install**     2m 31s (1)
✗ Fatal error occurred
Error: go@install failed with exit code 1
    at ChildProcess.<anonymous> (/Users/kipley/Documents/code/Docker/firecrawl/firecrawl/apps/api/dist/src/harness.js:262:24)
    at ChildProcess.emit (node:events:508:28)
    at maybeClose (node:internal/child_process:1085:16)
    at Socket.<anonymous> (node:internal/child_process:456:11)
    at Socket.emit (node:events:508:28)
    at Pipe.<anonymous> (node:net:346:12)
 ELIFECYCLE  Command failed with exit code 1.

是代理的问题,反正是要切换到稳定的 代理,阿里云和百度云都可以。

go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct

再次运行pnmp start,查看网络是否顺利,没有报错:

Pasted image 20260122205057

终端三

curl -X GET http://localhost:3002/test

最后使用curl测试的时候,显示的是:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /test</pre>
</body>
</html>

这里教程显示,这将返回响应“Hello, world!”。可能是代码更新了,这里的返回是没有问题的。

  • 如果服务器没启动,你会看到:curl: (7) Failed to connect to localhost port 3002: Connection refused
  • 现在收到了 Express 框架返回的 HTML 错误页面(Cannot GET /test),这证明 3002 端口是通的,且 API 程序正在响应你的请求。

测试连接

测试crawl端点:

curl -X POST http://localhost:3002/v1/crawl \
    -H 'Content-Type: application/json' \
    -d '{
      "url": "https://mendable.ai"
    }'

显示日志如下:

{"success":true,"id":"019be5c6-4dbd-7015-97ea-acd3ed5bf6ab","url":"http://localhost:3002/v1/crawl/019be5c6-4dbd-7015-97ea-acd3ed5bf6ab"}**%**

项目架构分工

当你解决完这个 Go 依赖问题后,Firecrawl 的整个链路就打通了。你可以参考下图确认你的本地环境是否已经“全副武装”:

  • Node.js: 负责 API 调度。
  • Rust (Cargo): 负责高性能爬取引擎。
  • Go: 负责将 HTML 转换为 Markdown(这就是你现在卡住的地方)。
  • Redis: 负责任务队列(确保你开了 redis-server)。
  • PostgreSQL: 负责数据存储(确保 Docker 容器在运行)。

2、关闭项目

  1. 关闭 API 服务 (终端二)

    • 操作: 切换到运行 pnpm start 的终端窗口。
    • 命令: 按下 Ctrl + C
    • 说明: 系统会提示你是否要终止批处理作业,输入 Y 并回车即可。这是最先要关闭的服务,因为它依赖于 Redis 和数据库。
  2. 关闭 Redis 服务 (终端一)

    • 操作: 切换到运行 redis-server 的终端窗口。
    • 命令: 按下 Ctrl + C
    • 说明: Redis 服务器会优雅地保存数据并退出。
  3. 关闭 PostgreSQL 数据库容器

    • 操作: 打开一个新的终端窗口,或者在任意一个空闲的终端窗口操作。
    • 命令:
docker stop nuqdb

说明: 这个命令会向名为 nuqdb 的 Docker 容器发送停止信号,让数据库安全关闭。它在后台运行,所以需要用 docker 命令来管理。

3、开启项目

下次需要继续工作时,请按照以下步骤启动,顺序为:依赖服务 -> 核心应用

  1. 启动 PostgreSQL 数据库容器
    • 操作: 打开一个终端。
    • 命令:
docker start nuqdb
  • 检查 (可选): 你可以运行 docker ps 来确认 nuqdb 容器是否处于 Up 状态。
  • 注意: 这里使用 docker start 而不是 docker run,因为容器已经创建好了,我们只是重新启动它。
  1. 启动 Redis 服务 (在新的终端窗口中)
    • 操作: 打开一个新的终端窗口(我们称之为 终端一)。
    • 命令:
redis-server

说明: 启动后,让这个终端窗口保持运行状态。
3. 启动 Firecrawl API 服务 (在另一个新的终端窗口中)

- **操作**: 打开第三个终端窗口(我们称之为 **终端二**)。
- **导航到目录**:
cd /Users/kipley/Documents/code/Docker/firecrawl/firecrawl/apps/api/

启动服务:

pnpm start

说明: 服务启动后,这个终端会持续输出日志,让它保持运行。

  1. 验证服务是否正常

    • 操作: 打开第四个终端窗口(或使用任意空闲终端)。
    • 命令: 运行你在笔记中记录的测试命令。
curl -X POST http://localhost:3002/v1/crawl \
	-H 'Content-Type: application/json' \
	-d '{
	  "url": "https://mendable.ai"
	}'

预期结果: 如果返回了类似 {"success":true,"id":"..."} 的 JSON 响应,说明整个服务链路已成功启动!

操作 命令 终端
启动
1. 启动数据库 docker start nuqdb 任意终端
2. 启动Redis redis-server 终端一
3. 启动API cd apps/api && pnpm start 终端二
关闭
1. 关闭API Ctrl + C 终端二
2. 关闭Redis Ctrl + C 终端一
3. 关闭数据库 docker stop nuqdb 任意终端
from firecrawl import FirecrawlApp
import os

# 1. 初始化(本地 URL 务必带上 /v1)

app = FirecrawlApp(api_key="any_string", api_url="http://localhost:3002/v1")

print("🚀 开始尝试本地抓取...")
try:
# 2 使用正确的属性名:scrape
# formats 直接作为参数传入 (v4.13.1 SDK)
url = 'https://huggingface.co/'
scrape_result = app.scrape(
url=url,
formats=['markdown']
)

# 3. 检查并打印结果 (Document object with .markdown attr)

if scrape_result:
print("✅ 抓取成功!")
markdown = scrape_result.markdown or ""
print(f"内容预览:\n{markdown[:300]}")
# 保存到 output 文件夹
os.makedirs('output', exist_ok=True)
domain = url.split('//')[-1].split('/')[0].replace('.', '_')
filename = f"output/{domain}.md"
with open(filename, 'w', encoding='utf-8') as f:
f.write(markdown)
print(f"✅ 已保存完整内容到 {filename}")
else:
print("⚠️ 未返回任何内容")
except Exception as e:
print(f"❌ 运行报错: {e}")

局限性:还是和大多数爬虫效果一样,爬取的内容只能是公共内容,如果是需要账号授权或者登录的依然不行。目前效果有限,可以和智能体的工作流结合一下,现在尝试Docker compose的配置:

4、Docker compose快速配置

一条指令搞定了,哎呀,这就凸显出Docker的重要性了,我本地慢慢配置环境,配置了半天,Docker一条指令就完成了。

cd /Users/kipley/Documents/code/Docker/firecrawl/firecrawl/apps/api
docker compose up
# ===== 必需的环境变量 ======
NUM_WORKERS_PER_QUEUE=8
PORT=3002
HOST=0.0.0.0
REDIS_URL=redis://redis:6379
REDIS_RATE_LIMIT_URL=redis://redis:6379

## 要启用数据库认证,你需要配置 Supabase。
USE_DB_AUTHENTICATION=false

## 使用 PostgreSQL 进行队列——如果凭据、主机或数据库不同,请修改
NUQ_DATABASE_URL=postgres://postgres:postgres@localhost:5433/postgres

# ===== 可选的环境变量 ======
# Supabase 配置(用于支持数据库认证、增强日志等)
SUPABASE_ANON_TOKEN=
SUPABASE_URL=
SUPABASE_SERVICE_TOKEN=

# 其他可选项
TEST_API_KEY= # 如果你已启用认证并想用真实 API 密钥进行测试,可在此填写
OPENAI_API_KEY= # 如需启用依赖 LLM 的功能(例如生成图片替代文本),请添加
BULL_AUTH_KEY= @
PLAYWRIGHT_MICROSERVICE_URL= # 如需启用 Playwright 回退,请设置
LLAMAPARSE_API_KEY= # 如果你有 Llamaparse 密钥并想用于解析 PDF,请设置
SLACK_WEBHOOK_URL= # 如需发送 Slack 服务器健康状态消息,请设置
POSTHOG_API_KEY= # 如需发送 PostHog 事件(如作业日志),请设置
POSTHOG_HOST= # 如需发送 PostHog 事件(如作业日志),请设置

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 kipleyarch@gmail.com
Obsidian