从市场调研到 MVP:宝可梦问答小程序的数据管线与题库工程

我做前端快十年,待过猫眼、新东方、完美世界,也自己创过业。最近在软通动力做美团小程序和鸿蒙外包的间隙,想做一个能写进简历、也能真实跑起来的小程序作品——一款宝可梦百科问答小程序。这篇复盘那天从调研到 MVP 的完整链路。

先调研,再动手

很多人做小程序一上来就写页面,我先花了一天调研。结论很直接:图鉴查询类小程序已经饱和,但"猜宝可梦 / 百科问答"这个类目在国内小程序端几乎是空白,海外有 Squirdle、Pokequizz 这类产品验证过需求。版权上我避开官方立绘,只用纯文字数据(中文图鉴描述、属性、种族值),类目也不走"游戏"标签。这一步把后面最危险的合规坑提前排掉了——比写十版页面都值钱。

数据管线:稳定抓全 1025 条

数据源是 PokeAPI 公开数据。我用 Node 原生 fetch 并发 16 路抓取 species 与 pokemon 各 1025 条,36 秒抓完、零失败,输出单文件 pokemon.json(约 636K)。关键实现是用滑动批次控制并发,而不是一次性 Promise.all 上千请求:

const concurrency = 16;
async function fetchAll(ids) {
  const results = [];
  for (let i = 0; i < ids.length; i += concurrency) {
    const batch = ids.slice(i, i + concurrency);
    const part = await Promise.all(batch.map(fetchOne));
    results.push(...part.filter(Boolean));
  }
  return results;
}

两个细节容易踩:语言标签是小写 zh-hans,写成 zh-Hans 会返回空;九世代新宠多没有中文图鉴描述,必须按"有描述"过滤,实际只有 722 只进入图鉴描述题池。另外描述文本含全角空格与全角数字("1400米"),出题清洗时要归一化为半角,否则题干展示会乱。

题库生成:可复现才是硬道理

题库用固定随机种子(20260904)生成,保证每次结果一致、能审计。最终 1212 题:图鉴描述猜 800、之最排行 240、属性克制 172。第一版干扰项太直白,用户试做后说"一眼看出答案"。我重做了相似度打分:同主属性加 4 分、同副属性加 2 分、同世代加 2 分、老世代人气加 1 分、体型接近加 1 分,使 94% 的干扰项与主答案同主属性;之最题干扰项数值控制在答案的 82% 以上;去重键取"题干 + 选项集合",避免同日重复出题。

小程序架构与服务端判分

原生微信小程序加云开发,四个页面(今日挑战、答题、成绩、战绩)加两个云函数:getDailyQuiz 按日期种子取当日题,submitResult 服务端判分、连胜、百分位。安全设计是重点:答案不下发客户端,只收当日提交并去重,同日题干去重防止"攻击种族值最高"出现两道重复题,判分全在服务端完成,前端拿不到正确答案,作弊没有意义。

方法论沉淀

回过头看,做一款小程序真正的难点不在写页面,而在"调研 → 数据 → 题库 → 架构 → 安全"这条链路。需求与版权排查前置,能避免后期返工;数据管线与题库生成用固定种子保证可复现,是后续审计与质量把控的基础。需求验证比技术实现更值钱——如果一开始没做版权和类目排查,后面可能白做。

更多细节可以看仓库里同主题的技术复盘,也欢迎在评论区聊聊你做小程序是先调研还是先写代码。