手机+Claude Code周末搭建iNaturalist观察记录展示工具全流程

Simon Willison用手机和Claude Code搭建了iNaturalist观察记录展示工具,展示AI辅助移动端开发新范式。
Simon Willison在露营期间,仅用手机和Claude Code,构建了一套完整的iNaturalist自然观察记录展示工具。项目采用三层架构:Python CLI工具进行数据抓取与时空聚类,Git Scraping实现零成本自动化数据更新,Claude Code生成前端单页应用。该项目展示了AI辅助编程在移动端的可行性,以及用免费GitHub基础设施组合实现个人数据工具的高效开发范式。
背景
Simon Willison——知名开源开发者、Datasette 作者——最近分享了一个有趣的周末项目:他在露营期间,完全使用手机和 Claude Code,搭建了一个用于展示 iNaturalist 自然观察记录的 Web 工具。这个项目不仅展示了 AI 辅助编程在移动端的可行性,也体现了一套优雅的数据管道设计思路。
Simon Willison 在开源社区有着深厚的影响力。他是 Django 框架的联合创始人之一,后来创建了 Datasette——一个将 SQLite 数据库即时转化为可交互 API 和 Web 界面的工具。Datasette 的设计哲学强调"数据即发布",即任何结构化数据都应该能以最低成本变成可浏览、可查询的 Web 服务。理解这一背景,有助于我们理解他在这个项目中做出的一系列架构选择——它们都指向同一个目标:用最轻量的方式将数据变成可用的产品。
为什么要做这个项目
iNaturalist 是全球最大的公民科学平台之一,用户可以上传自己在野外观察到的动植物照片,由社区协助鉴定物种。截至 2024 年,该平台已积累超过 2 亿条观察记录,覆盖超过 40 万个物种,拥有数百万活跃用户。iNaturalist 的物种鉴定采用了一套独特的"社区共识"机制:当多位用户对同一观察记录的物种鉴定达成一致时,该记录会被标记为"研究级别"(Research Grade),这些高质量数据会被同步到全球生物多样性信息网络(GBIF)等科研数据库中,真正实现了公民科学对专业研究的贡献。iNaturalist 提供了相当开放的 RESTful API,支持按用户、地点、物种分类等多种维度查询观察记录,每条记录包含照片 URL、GPS 坐标、时间戳、物种分类信息等丰富的结构化数据。
Simon 拥有两个 iNaturalist 账号,他希望将两个账号的观察记录合并在一起,并按照时间和地点进行分组展示。
这个需求看似简单,但 iNaturalist 官方并没有提供跨账号的聚合视图功能。于是 Simon 决定自己动手,用一个周末的时间从零搭建整套工具链。
技术架构:三层数据管道设计
整个项目由三个层次组成,每一层都解决一个具体问题,组合起来形成了一条完整的数据流水线。
Python CLI 工具:数据抓取与时空聚类
Simon 首先构建了一个名为 inaturalist-clumper 的 Python 命令行工具。这个工具的核心功能是从 iNaturalist API 拉取观察记录,然后按照时空邻近度进行"聚类"(clumping)——默认规则是将 2 小时内、5 公里范围内的观察记录归为同一组。
时空聚类(spatiotemporal clustering)是地理信息科学中的一个经典问题。传统的聚类算法如 K-Means 只考虑空间距离,而时空聚类需要同时在空间维度和时间维度上衡量数据点之间的"邻近度"。常见的做法包括使用 DBSCAN(基于密度的空间聚类)算法的时空扩展版本,或者像 Simon 这里采用的更简单直观的阈值方法——设定时间窗口和空间半径,将满足双重条件的记录归为一组。Simon 选择的 2 小时 / 5 公里阈值是一个经验值,它大致对应了一次步行或短途驾车的自然观察活动范围。这种基于规则的聚类方法虽然不如机器学习算法灵活,但胜在可解释性强、实现简单,非常适合这类个人项目场景。
这种聚类策略非常实用:当你在某个地点进行一次自然观察活动时,通常会在短时间内拍摄多个物种,将它们归为一组正好对应一次"出行"的概念。
Git Scraping:零成本自动化数据更新
数据抓取工具有了,但如何让数据保持更新?Simon 采用了他自己推广的 "Git Scraping" 技术——通过 GitHub Actions 定时运行脚本,将结果提交到 Git 仓库中。
Git Scraping 的核心思想是将 Git 版本控制系统"滥用"为一个时序数据库。GitHub Actions 是 GitHub 提供的免费 CI/CD 服务,支持通过 cron 表达式设定定时触发规则(例如每小时、每天执行一次)。每次执行时,脚本从外部 API 拉取最新数据并写入仓库中的文件,然后通过 git commit 和 git push 提交变更。由于 Git 天然记录每次提交的完整差异(diff),你不仅拥有最新的数据快照,还自动获得了完整的历史变更记录——这在追踪数据变化趋势时极为有用。Simon 在 2020 年首次系统性地提出这一模式后,社区已经涌现出数百个 Git Scraping 项目,涵盖从疫情数据追踪到政府公开数据监控等各种场景。
具体来说,他创建了 simonw/inaturalist-clumps 仓库,定期执行 clumper 工具,将聚类结果写入 clumps.json 文件。由于 GitHub 的原始文件(Raw)支持 CORS 跨域访问,这个 JSON 文件天然就是一个免费的、自动更新的 API 端点。
CORS(Cross-Origin Resource Sharing,跨源资源共享)是浏览器的一项安全机制。默认情况下,网页中的 JavaScript 只能向同源(相同协议、域名、端口)的服务器发起请求。如果前端页面托管在 simonw.github.io,而数据文件位于 raw.githubusercontent.com,浏览器会因为跨域限制而阻止请求——除非服务器在响应头中包含 Access-Control-Allow-Origin 字段。GitHub 的 Raw 文件服务恰好设置了允许跨域访问的响应头,这意味着任何网页都可以直接通过 fetch() 请求读取仓库中的文件内容,无需搭建中间代理服务器。
这种模式的精妙之处在于:零成本托管、自带版本历史、无需维护服务器。Git 仓库本身就是数据库,GitHub Actions 就是调度器,GitHub Raw 就是 CDN。
前端展示:Claude Code 生成单页应用
最后一步是构建前端页面。Simon 在手机上使用 Claude Code,向他的 simonw/tools 仓库发送了一段 prompt:
Build inat-sightings.html - an app that does a fetch() against the clumps.json and then displays all of the observations on one page using the small.jpg URLs for the thumbnails - with loading=lazy - but when a thumbnail is clicked showing the large.jpg in an HTML modal.
Claude Code 是 Anthropic 推出的一款基于终端的 AI 编程代理工具,它可以直接在命令行环境中理解自然语言指令,读取项目上下文,生成代码并执行文件操作。与传统的代码补全工具不同,Claude Code 具备完整的项目感知能力——它能浏览目录结构、读取已有文件、理解项目约定,然后生成与现有代码风格一致的新文件。由于它运行在终端中,理论上任何支持终端模拟器的设备都可以使用,包括手机上的 Termux(Android)或通过 SSH 连接远程服务器。这正是 Simon 能在手机上完成开发的技术基础。
这段 prompt 简洁而完整,包含了关键的技术细节:数据源 URL、缩略图策略(lazy loading)、交互模式(点击放大的模态框)、以及内容要求(显示物种通用名)。其中 loading=lazy 是 HTML 原生的延迟加载属性,它告诉浏览器只有当图片即将进入可视区域时才开始加载,这对于包含大量图片的页面至关重要——iNaturalist 的观察记录可能包含数百张缩略图,如果一次性全部加载会严重影响页面性能和用户的流量消耗。Claude Code 据此生成了完整的单页应用。
这个项目的几个亮点
手机端 AI 编程已经可行
整个项目是在露营期间用手机完成的,这说明 Claude Code 已经具备了足够的能力来处理中等复杂度的开发任务。对于开发者来说,这意味着灵感来了随时可以动手,不必等到回到电脑前。
这一点的意义比表面看起来更深远。传统的软件开发高度依赖大屏幕、物理键盘和复杂的 IDE 环境,手机端编程长期以来被视为"不切实际"的想法。但 AI 编程代理改变了这个等式:当你不再需要逐行敲代码,而是用自然语言描述需求,手机的小屏幕和触摸键盘就不再是瓶颈。开发者的角色从"代码编写者"转变为"意图表达者",而表达意图并不需要 IDE——一个终端窗口就够了。Simon 的这次实践可以看作是这种范式转变的一个早期信号。
Git Scraping 依然是个人项目利器
Git Scraping 是 Simon 在 2020 年提出的概念,几年过去了,这种模式依然展现出强大的生命力。它特别适合个人项目和小规模数据采集场景——不需要数据库、不需要服务器、不需要运维,只需要一个 GitHub 仓库和一个定时任务。
值得一提的是,Git Scraping 的"免费"并非没有边界。GitHub Actions 对免费账户提供每月 2000 分钟的执行时间,对于大多数个人数据采集项目来说绑绑有余,但如果脚本执行频率过高或单次运行时间过长,可能会触及限制。此外,GitHub 仓库对单个文件大小有 100MB 的限制,对仓库总大小建议不超过 1GB,这意味着 Git Scraping 更适合中小规模的结构化数据(如 JSON、CSV),而不适合存储大量二进制文件或海量数据集。在这些约束范围内,它几乎是个人开发者能找到的最低摩擦力的数据管道方案。
好的 Prompt 就是产品规格说明
Simon 给 Claude Code 的 prompt 本质上就是一份简洁的产品规格说明。它没有指定具体的实现方式(用什么框架、什么 CSS 方案),而是聚焦于功能需求和用户体验。这种"声明式编程"的方式,正在成为 AI 辅助开发的最佳实践。
"声明式"与"命令式"是编程范式中的一对经典概念。命令式编程告诉计算机"怎么做"——一步步描述具体操作;声明式编程则告诉计算机"做什么"——只描述期望的结果,由系统自行决定实现路径。SQL 是声明式的(你描述想要什么数据,数据库引擎决定如何查询),而大多数通用编程语言是命令式的。AI 辅助编程正在将这种声明式理念推向新的高度:开发者用自然语言声明需求,AI 代理负责选择技术栈、设计代码结构、处理边界情况。Simon 的 prompt 之所以有效,恰恰是因为它在正确的抽象层级上描述了需求——既不过于笼统("做一个网页"),也不过于具体("用 React 创建一个组件"),而是精准地传达了数据流、交互模式和性能要求这些真正重要的产品决策。
总结
这个项目虽然规模不大,但它展示了一种高效的现代开发范式:用 AI 快速生成代码,用 Git Scraping 实现零成本数据管道,用 GitHub 基础设施完成托管和自动化。对于想要快速构建个人数据工具的开发者来说,这套组合拳值得借鉴。
从更宏观的视角来看,这个项目体现了一种正在成型的"个人基础设施"理念:个人开发者不再需要模仿企业级架构来构建自己的工具,而是可以巧妙地组合免费的云服务(GitHub Actions 做调度、GitHub Pages 做托管、GitHub Raw 做 API)和 AI 编程代理,以极低的成本和极快的速度将想法变成可用的产品。这种模式降低了软件开发的门槛,让更多人能够为自己的特定需求定制工具,而不是被迫适应通用软件的功能边界。
相关推荐
教程攻略Cursor+Codex双IDE协同:开源项目二开实战方法论
基于实战经验总结的开源项目二次开发完整方法论,详解Cursor+Codex双IDE协同工作流,涵盖二开七环节、MVP验证、AI读源码技巧,帮助开发者三天跑通项目、两周完成业务集成。
教程攻略Cursor多Agent实战:50分钟搭建Next.js全栈博客
使用Cursor IDE多Agent协作模式,50分钟内从零搭建全栈博客。涵盖Next.js、Clerk认证、Supabase数据库集成,详解4个AI Agent分阶段开发流程与关键避坑经验。
教程攻略从零搭建AI软件工厂:Cursor工程师的多Agent协作实战经验
Cursor工程师Eric分享AI软件工厂构建实战:从自动化六层级、护栏设计、并行Agent管理到规模化扩展,详解如何用多Agent协作实现7×24小时高效软件开发。