从 0 到 1 打造一个"会自己查数据"的电商 AI 助手:视频热点采集 + 评论分析 + 对话式问答全链路实战

作为一名电商从业者,我每天最关心三件事:同行在卖什么爆款、用户在评论区骂什么问什么、对标账号又发了什么新视频。人工刷抖音效率太低,市面上的数据工具又贵又不灵活。于是我花了一天时间,基于开源爬虫 + SQLite + DeepSeek 大模型,从零搭了一个"放开双手"的 AI 数据助手:它每天自动采集热点视频和评论入库,我随时打开网页就能用自然语言问它问题——问的话题库里没数据?它当场自己去抖音采完再回答我

本文完整记录从架构设计、核心代码实现到三个关键 Bug 修复的全过程,全部真实代码、真实数据,建议收藏。


一、先想清楚:我到底要什么?

动手之前先把需求拆清楚。电商场景下,一个"真正解放双手"的助手至少要满足四点:

需求 具体含义 技术对应
热点追踪 我品类下的爆款视频、上升趋势 定时关键词搜索采集
评论分析 用户在骂什么、问什么、想买什么 评论入库 + LLM 聚类分析
对标监控 竞对账号发新视频、粉丝变化 账号作品轮询 + 快照对比
随时可问 不用等日报,想问就问 对话式 Web 界面 + LLM

最关键的是第四点的升级版体验:我随口问一个它没见过的话题,它应该自己去查数据再回答我,而不是两手一摊说"我不知道",更不能一本正经地瞎编(后面会讲,LLM 真的会瞎编,而且编得很像真的)。

二、技术选型:够用就好,拒绝过度设计

模块 选型 理由
数据采集 Evil0ctal/Douyin_TikTok_Download_API 开源、自带 X-Bogus/A-Bogus 签名、支持搜索/评论/主页/解析全套接口,本地 Docker 部署
存储 SQLite 单机数据量不大,零运维,一个文件就是一个库
后端脚本 Python 3.13(纯标准库) 数据采集、HTTP 服务全用 urllib/sqlite3/http.server 实现,零第三方依赖,不用配 venv
LLM DeepSeek API(OpenAI 兼容协议) 国内直连、便宜、deepseek-v4-flash 约 9 秒响应
前端 单 HTML 文件 深色主题聊天页,直接由 Python 的 http.server 托管

整个项目不到 800 行代码,跑起来只需要:Docker 容器(爬虫 API)+ 一个 Python 进程(助手服务)

三、整体架构:四层闭环

┌─────────────────────────────────────────────────────────┐
│  交互层   Web 聊天页 (localhost:8000)  + 定时日报         │
├─────────────────────────────────────────────────────────┤
│  分析层   DeepSeek LLM(评论聚类/选品建议/防编造约束)      │
├─────────────────────────────────────────────────────────┤
│  存储层   SQLite 四表(videos/comments/accounts/runs)    │
├─────────────────────────────────────────────────────────┤
│  采集层   Python 采集器 → 本地爬虫 API (localhost:8081)   │
│           ├─ 定时任务:每天 08:00 / 20:00 自动跑一轮       │
│           └─ 实时触发:对话中检测到缺数据时当场采集         │
└─────────────────────────────────────────────────────────┘

亮点在于采集层有两条通路:定时任务负责"日常巡逻",对话中的实时采集负责"随问随查"——这是实现"放开双手 + 随时可问"的关键设计。

四、核心模块实现

4.1 存储层:四张表撑起全部数据

db.py 里定义了 videos / comments / account_snapshots / collection_runs 四张表。两个设计细节值得说:

  • videos 表用 INSERT ... ON CONFLICT DO UPDATE:重复采到同一条视频时只更新点赞数等动态字段,first_seen/last_seen 天然支持"这条视频数据涨了多少"的趋势分析;
  • comments 表用 INSERT OR IGNOREcomment_id 唯一约束直接物理去重,返回 rowcount 就知道是不是新评论。
def upsert_video(self, v: dict) -> None:
    self.conn.execute(
        """
        INSERT INTO videos (aweme_id, source_type, source_keyword, title,
                            author_name, digg_count, comment_count, ...)
        VALUES (?,?,?,?,?,?,?,...)
        ON CONFLICT(aweme_id) DO UPDATE SET
            digg_count=excluded.digg_count,
            comment_count=excluded.comment_count,
            last_seen=excluded.last_seen   -- 数据会"长大",趋势就是这么来的
        """, (...))

4.2 采集层:限流是保命符

抖音风控敏感,采集器的核心不是"抓得快",而是"活得久"。api_client.py 里强制每次请求间隔 3 秒 + 失败指数退避重试:

def _get(self, path: str, params: dict) -> dict:
    # 频率控制:风控敏感,宁可慢不要停
    wait = self.interval - (time.time() - self._last_call)
    if wait > 0:
        time.sleep(wait)
    ...
    for attempt in range(self.retries + 1):
        try:
            with urllib.request.urlopen(req, timeout=self.timeout) as resp:
                payload = json.loads(resp.read().decode("utf-8"))
            if payload.get("code") != 200:
                raise ApiError(...)
            return payload["data"]
        except Exception as e:
            last_err = e
            time.sleep(self.interval * (attempt + 1))   # 退避

Cookie 过期是爬虫的家常便饭,项目里用了一个 Chrome 扩展自动嗅探新 Cookie 并 Webhook 回推给 API 容器,基本实现了 Cookie 保鲜自动化。

4.3 对话层:一次提问的完整旅程

这是整个系统的心脏。用户问"分析一下宝宝辅食的抖音热点趋势",后端发生的事情:

def do_POST(self):
    question = payload.get("message").strip()
    tokens = _tokens(question)                      # ① 拆关键词

    collect_info = auto_collect(question, tokens)   # ② 库不够就当场采

    # ③ 把刚用的搜索词传给检索层(关键修复,见后文)
    force_keyword = collect_info.get("query", "") \
        if collect_info.get("collected") else ""
    context = build_context(question, force_keyword)

    reply = llm_reply(question, history, context)   # ④ 组装上下文送 LLM

auto_collect 的逻辑:先查库里有没有 ≥3 条相关视频,没有就提取搜索词 → 调搜索接口 → 入视频库 → 给 TOP3 视频采评论 → 采账号快照 → 返回采集报告。前端收到 collected 字段后会弹出提示:“📡 刚刚实时采集了 7 条视频 + 13 条评论”。

4.4 LLM 集成:防编造是第一要务

直接把检索结果丢给 LLM 是危险的——它发现库里没数据时,会凭训练记忆给你编一份栩栩如生的假数据(真实踩坑,下文细说)。System Prompt 里必须上硬约束:

SYSTEM_PROMPT = """你是用户的「电商数据助手」……

【最高纪律——绝不允许编造数据】
1. 所有账号信息、视频标题、点赞数、评论内容等具体事实,只能来自下方<数据>区。
2. 如果<数据>里确实没有用户问的内容,必须直接说"这个内容我还没有采集到数据",
   绝对禁止凭印象编造任何具体数字。
3. 推测性建议可以有,但必须明确标注"(推测)"或"(建议)",与真实数据严格区分。

以下是助手为你实时检索/采集的相关真实数据:
<数据>
{context}
</数据>"""

再加一道保险:LLM 调用 45 秒超时后自动降级,直接把真实数据原文返回给用户并注明"AI 解读暂不可用"——宁可少一层解读,不让用户干等或拿到超时错误。

五、三个真实踩坑实录(本文最有价值的部分)

坑一:LLM 面不改色地编造数据

现象:我问"分析一下招生办这个账号",它流畅地返回了粉丝数、视频列表、高赞评论——格式完美,内容全假。因为那个账号的数据根本没采过。

根因:提示词只说了"基于数据回答",没有禁止编造的约束。LLM 的天性就是"必须给出答案"。

修复:上面的【最高纪律】prompt。修复后同样的问题再问一个没采过的账号,它会明确回答"我还没有采集到该账号的数据,不会凭印象编造"。做数据类 AI 应用,防幻觉 prompt 不是可选项,是生命线。

坑二:检索失效——长句被当成一个关键词

现象:账号明明已入库,问它却检索不到。

根因:初版 _tokens 把整个中文长句当一个 token,SQL 里执行的是 LIKE '%分析商洛学院招生办公室这个账号%',当然零匹配。

修复:改成 2~4 字滑窗 + 停用词过滤:

def _tokens(text: str) -> list[str]:
    cn_segs = re.findall(r"[一-鿿]+", text)
    tokens = []
    for seg in cn_segs:
        for n in (4, 3, 2):                      # 4字→3字→2字滑窗
            for i in range(len(seg) - n + 1):
                w = seg[i:i+n]
                if w not in _STOPWORDS:
                    tokens.append(w)
    return [w for w in dict.fromkeys(tokens)][:8]

同时检索范围从只搜 title 扩展到 author_name + account_snapshots.nickname——用户问"某某账号"时,名字往往出现在作者字段而不是标题里。

坑三:采集了数据,LLM 却"看不到"(最隐蔽)

现象:问"分析美食探店",系统确实自动采了 7 条视频入库,但 LLM 回答"这批数据的具体内容没有同步到我这边"。采集成功、检索失败,非常诡异。

根因:采集和检索是两条互不相干的路径——

采集路径:搜索词"美食探店热点" → 视频入库(打上 source_keyword 标签)
检索路径:问题拆 token ["美食","探店","热点"] → LIKE 模糊匹配视频标题

token 模糊匹配完全可能命中旧数据、漏掉刚采的新数据。两条路径之间没有任何关联保证。

修复:给 build_context 增加 force_keyword 参数,把采集时用的搜索词直接传进去,source_keyword 精确取回刚采的那批数据,彻底绕过脆弱的 token 匹配:

def build_context(question: str, force_keyword: str = "") -> str:
    parts = []
    if force_keyword:
        # 精确路径:刚采集的数据必须进上下文,一条都不许丢
        fresh = conn.execute(
            "SELECT * FROM videos "
            "WHERE source_keyword=? AND source_type='chat_realtime' "
            "ORDER BY digg_count DESC LIMIT 10", (force_keyword,)).fetchall()
        parts.append("【刚刚实时采集的数据】——请基于这些分析:")
        _include_video_batch(conn, parts, fresh, "实时采集")
    # ……然后才是常规的 token 模糊检索(作为补充)

经验:数据管道里,"写入"和"读取"必须用同一个键。用模糊匹配做读取键,早晚出事。

六、实战效果

定时巡逻

自动化任务每天 08:00 / 20:00 各跑一轮:检查爬虫容器 → 跑采集 → 导出评论摘要 → 生成五段式洞察报告(购买意向 / 用户痛点 / 价格关注 / 内容反馈 / 行动建议)存入 reports/ 目录。

首份真实报告就挖到了值钱信息:某厨房好物视频(115 万赞)的评论区里,"求链接"类评论密度极高且无一人回复——种草流量在评论区白白流失;有用户明确提出"圆形蒸碟夹"这个市面上没有的产品空白。

随问随查

问"分析宝宝辅食的抖音热点趋势",系统当场采集 7 视频 + 13 评论后回答:

  • 采集到的辅食视频点赞均在 27 赞以下——低竞争、高转化的蓝海细分,大博主尚未垄断
  • "安排/给孩子安排上"出现 6 次,零负面零比价——决策路径极短,适合直接带货型内容
  • 高频词指向"分月龄整套解决方案"比单品推荐更有吸引力

所有数字、账号名、评论原文全部来自刚采的真实数据,可逐条回查数据库。

七、成本与边界

  • 金钱成本:DeepSeek API 按 token 计费,一天几毛钱的量级;其余全部本地运行,零费用。
  • 风控边界:3 秒/请求的保守限流下连续运行稳定;搜索接口偶发风控时采集器会如实记录失败原因,不会疯狂重试把自己作死。
  • 能力边界:目前是"采集 + 分析 + 问答",视频剪辑拆解(下载 → ffmpeg 抽帧 → Whisper 转写 → 多模态拆脚本)是下一步的方向。

八、总结

回头看,这个项目的复杂度不在任何单一技术点,而在把"采集 → 存储 → 检索 → LLM"这条链路焊死

  1. 数据类 AI 应用,防幻觉 prompt 是生命线——先说清"不许编",再谈"怎么答";
  2. 写入和读取用同一个键——source_keyword 精确关联,别信模糊匹配;
  3. 零依赖不是炫技,是可移植性——纯标准库意味着任何装了 Python 的机器 python chat_server.py 就能跑;
  4. 小步快跑胜过一步到位——先让"定时采集 + 报告"跑起来,再加对话,再加实时采集,每一步都独立见效。

如果你也是电商/内容从业者,这套"开源爬虫 + SQLite + 国产大模型"的组合拳,一个周末就能复刻一个属于你自己品类的版本。源码结构、prompt 模板、踩坑记录都在文中了,欢迎交流。


技术栈:Python 3.13(纯标准库) / SQLite / FastAPI 爬虫服务 / DeepSeek API / Docker

Logo

电商企业物流数字化转型必备!快递鸟 API 接口,72 小时快速完成物流系统集成。全流程实战1V1指导,营造开放的API技术生态圈。

更多推荐