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、部署到服务器,解放笔记本(推迟,等到规则确定之后再说)
- 1、修改代码修改模型接口、修改提示词 Tongyi-Zhiwen/QwenLong-L1-32B
- dify工作流配置,实现一个好玩的效果 –未全部完成
- 实现效果: 你输入一个 B 站视频链接,Dify 自动抓取字幕,生成一份“太长不看”的摘要,甚至帮你把内容改写成一篇小红书/推特风格的笔记。 –未完成
- 1、视频链接解析agent,导出音频或者文字内容
- 需要API接口(服务器)对视频进行解析服务,我打算使用实验室服务器 –已完成
- 需要whisper本地音频解析,会快很多,我打算配置实验室显卡。 –完成
- 2、内容总结按照提示词模板,总结内容agent
- 1、视频链接解析agent,导出音频或者文字内容
- 实现效果: 你输入一个 B 站视频链接,Dify 自动抓取字幕,生成一份“太长不看”的摘要,甚至帮你把内容改写成一篇小红书/推特风格的笔记。 –未完成
- 关于记忆承载公众号文章批量导出的顺序标号–按照时间顺序导出而不是混乱的顺序。 –有思路
- 因为导出的时候,是没有顺序的,现在我可以导出为Excel表格,时间和标题一一对应的方式,这样的话,我就可以通过程序,搜索Excel和markdown文件的标题,从而批量修改文章的标题。从而对文章批量命名, 达成我的文章顺序按照发布时间来的效果。 –明天在干,今天拉满了没力气了。
- firecrawl 配置完成 –好用的爬虫工具
- Docker形式的配置
- 分别安装包进行配置
二、今日感悟
- 核心业务数据:
- 实验室要求的数据导出技术模型替换,并且使用操作系统的思路,异步处理,两个AI的API异步工作,从而实现并行的效果,效率大幅提高,未来需要1000+数据的话,直接让其在服务器上跑一天,肯定数量达标了。
- 今日工作总结:
- 学习技术还是要看官方的文档,今天完成firecrawl的时候,用了csdn 的方法走弯路了,之后找到官方资料,直接手把手教,顺利的很
- 爬虫还是遇到用户登录的问题,效果一般,可以覆盖的范围还是小了点。所以,花钱能解决的还是建议花钱,自己琢磨技术非常困难,必要时候拿来主义。
- 明日工作计划:
- 学习一下师兄让我了解诶的两个技术和术语,不需要太深入。
- 使用自己部署的crawl服务,让我的dify工作流访问。
- dify打通一下B站字幕总结的问题,whisper本地模型导出速度凑合,
- 今日学习成长:
- 耐心很重要啊,实验室研三师兄旁边的机械键盘咔哧咔哧,还在打游戏听的我心慌,然后晚上回到寝室,室友双排英雄联盟,一直在说话,我也可以静下来来慢慢调试,我相信自己内心的平静可以战神一切噪音
- 还有,感觉室友这样放假之后每天打游戏好没有一丝,我这样的生活搞个一星期就受不了,我的基因里面就是折腾,一成不变的,没有输入没有思考没有成果的生活,才不是我想要的。
三、备注
- 无
四、实验室服务器whisper和 pytorch配置
1、本地部署
显卡型号
- 显卡: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)}')"
现在运行刚才的示例代码网络不通,即使我开启了代理,并且可以访问到谷歌:
python -c "import os; print(f'HTTP:', os.environ.get('http_proxy')); print(f'HTTPS:', os.environ.get('https_proxy'))"
现在直接在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)"
为了以后使用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提前下载模型,代码中改用绝对路径加载,彻底断开网络依赖。
- 使用 HF-Mirror 镜像站:
坑三: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-whisper和ctranslate2库为最新版本。
坑四: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 和全局网络。
- 利用 Conda 的
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
等待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
终端二
进入 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,查看网络是否顺利,没有报错:
终端三
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、关闭项目
关闭 API 服务 (终端二)
- 操作: 切换到运行
pnpm start的终端窗口。 - 命令: 按下
Ctrl + C。 - 说明: 系统会提示你是否要终止批处理作业,输入
Y并回车即可。这是最先要关闭的服务,因为它依赖于 Redis 和数据库。
- 操作: 切换到运行
关闭 Redis 服务 (终端一)
- 操作: 切换到运行
redis-server的终端窗口。 - 命令: 按下
Ctrl + C。 - 说明: Redis 服务器会优雅地保存数据并退出。
- 操作: 切换到运行
关闭 PostgreSQL 数据库容器
- 操作: 打开一个新的终端窗口,或者在任意一个空闲的终端窗口操作。
- 命令:
docker stop nuqdb
说明: 这个命令会向名为 nuqdb 的 Docker 容器发送停止信号,让数据库安全关闭。它在后台运行,所以需要用 docker 命令来管理。
3、开启项目
下次需要继续工作时,请按照以下步骤启动,顺序为:依赖服务 -> 核心应用。
- 启动 PostgreSQL 数据库容器
- 操作: 打开一个终端。
- 命令:
docker start nuqdb
- 检查 (可选): 你可以运行
docker ps来确认nuqdb容器是否处于Up状态。 - 注意: 这里使用
docker start而不是docker run,因为容器已经创建好了,我们只是重新启动它。
- 启动 Redis 服务 (在新的终端窗口中)
- 操作: 打开一个新的终端窗口(我们称之为 终端一)。
- 命令:
redis-server
说明: 启动后,让这个终端窗口保持运行状态。
3. 启动 Firecrawl API 服务 (在另一个新的终端窗口中)
- **操作**: 打开第三个终端窗口(我们称之为 **终端二**)。
- **导航到目录**:
cd /Users/kipley/Documents/code/Docker/firecrawl/firecrawl/apps/api/
启动服务:
pnpm start
说明: 服务启动后,这个终端会持续输出日志,让它保持运行。
验证服务是否正常
- 操作: 打开第四个终端窗口(或使用任意空闲终端)。
- 命令: 运行你在笔记中记录的测试命令。
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