为什么所有营养应用开发者都会撞上同一堵墙?Open Food Facts 明明是一座金矿——几百万真实的条形码产品数据,免费开放——可一打开就傻眼:重复条目满天飞,单位乱到让人崩溃,一半的字段空着,甚至能看到一块饼干每 100 克标注 6000 千卡的离谱数值。
我花了几个月时间一头扎进清洗工作,踩遍了坑,最终把这堆野生的众包数据驯服成了 DietlyAPI:背后 420 万种食品,一次典型搜索 40 毫秒左右返回结果。这篇文章就说清楚清洗究竟干了什么,因为大部分脏活在一开始完全超出我的预料。
8 成的时间在归一化
Open Food Facts 里每个数据源对“一份”都有自己的定义。同一个产品,有的报每 100 克营养,有的报每份,有的按整包给数值;能量值可能是千焦也可能是千卡,重量单位一会儿是克,一会儿又是毫克,有时单位直接混在文本串里。我的做法是统一转换:全部落到以“克”为基本单位的“每份”规范行上,同时保留原始分量描述,前端该怎么展示怎么展示。
更阴险的问题是:单独看每个值好像都说得过去,可加在一起就彻底不合理。蛋白质、碳水、脂肪的总重量超过了一份的净重;用 4/4/9 法则倒推,卡路里跟宏量营养素分解根本对不上。于是每一行数据都要过一道合理性检查,没通过的就尝试从其他字段修复——比如从千焦反推千卡,或者从每百克值换算到每份——实在修不了的,直接丢弃。
去重之后,按置信度排序
同一种酸奶在 Open Food Facts 里可能出现五次,每次条形码差一位,完整度也高低不等。我没有在导入时强行选一个“胜者”,而是给每个条目算一个置信度分数:数据完整度、来源可信度、有没有图片、合理性检查结果,全打进去。搜索时按分数从高到低排,那些乱糟糟的重复项还在,只是永远不会排到前面。
这一个设计后来成了最大的体验升级。搜“香蕉”,排第一的是一根真正香蕉的照片和营养数据,而不是某个批发商上传的“香蕉味浓缩糖浆”。让真实、高品质的数据自然上浮,远比反复删除垃圾条目更可持续。
一顿饭的成本跑起整个服务
整套系统跑在一台 4GB 内存的 Hetzner 云主机上:FastAPI + Postgres,借力三元组索引和全文索引,前面套上 Cloudflare 加速,再预渲染 85 万个静态页面供浏览。每周通过 systemd 定时任务做一次增量重建,完全没有复杂的基础设施。我还做了一个公开状态页,实时显示探测到的延迟,这样“快”不是口号,是能查到的数字。
直接用,零门槛
免费层不需要绑卡,即领一个 API 密钥,每分钟 30 次请求,对多数 demo 和小项目足够:
curl "https://api.getdietly.com/search?q=greek+yogurt&limit=3"产品信息、OpenAPI 规范全公开在 getdietly.com 上。底层数据来自 Open Food Facts,采用 ODbL 许可,如果你对外展示,记得标明来源——本来也应该标,没有这群贡献者就没有这一切。有什么关于数据清洗管线的问题,欢迎在评论区直接问。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.