← 博客

不用浏览器、不用地图API密钥,我做出了一叠中文行程地图

AI/LLM 工程 旅行

计划一趟四天的香港行程,我想要的东西很简单:每个要去的地方都有一张清楚的地图,标注用的是简体中文。不是标着一个图钉的英文地图,也不是一堆链接。十二个地点——酒店、博物馆、海洋公园、山顶缆车、机场——每个都做成一张干净的截图,好放进一本能打印的小册子。

于是我让运行在沙盒网页会话里的Claude Code来做。本以为是个五分钟的小差事,结果却变成一次小小的巡礼,让我看清"一张中文的香港地图"为什么没那么简单——其中还包括一套专门为了让这种事更难而存在的坐标系统。

没有浏览器,没有API密钥

最直接的办法——打开地图网站、把语言切成中文、给每个地点截图——这条路被堵了两次。这个会话没有可以操控的浏览器,而那些干净利落的静态地图API都要一个会计费的密钥。这次被迫改道,其实是好事而非坏事。谷歌和OpenStreetMap给香港的标注是双语或英文优先;想要真正的中文标注,你需要一个中国的地图服务商。答案是高德(AutoNavi)地图瓦片,它把香港渲染成简体中文地名——海洋公园、太平山顶、尖沙咀——正是落地后在路牌和手机上会看到的那些名字。计划是这样:拉取原始的256×256地图瓦片,用Python的Pillow把每张图手工拼起来。

没人会提醒你的坐标系统

这里有个吃掉我一个小时的小坑。中国的地图服务商在法律上必须使用GCJ-02——一套被混淆过的坐标系统,俗称"火星坐标"——它对真实的WGS-84经纬度施加一个刻意的、非线性的偏移。把一个真实GPS坐标直接画到中国底图上,你的图钉就会落到几百米开外:街对面的楼里,或者干脆掉进海港。这个偏移本身就是目的——一道由国家强制设置、用来对抗精确地理数据的减速带。

所以每个坐标在做任何瓦片运算之前,都得先过一遍标准的WGS-84 → GCJ-02变换:把中心点平移到火星坐标,围着这个平移后的点取瓦片,再把标记放在正中央,让它和平移后的底图对齐。弄错了,每张地图都会错得不动声色却又信誓旦旦;弄对了,没人会注意到——而这恰恰是一张地图全部的本分。

画地图

坐标问题一旦解决,剩下的就是图像的水管活。对每个地点:算出哪些瓦片覆盖了这片区域,把它们拉下来拼到一张760像素宽的卡片上,在正中央放一个水滴形图钉,上面压一条标题栏,写上中文地名、一个序号和当天日期。中文文字需要一款支持CJK的字体;沙盒里正好带了文泉驿正黑,够用了。

我最喜欢的是验证那一步。手敲的坐标恰恰是那种"看着对、其实未必"的东西,所以渲染完之后,Claude Code把自己输出的图片又读了回来,逐个把图钉和它下面标注的地物对一对——科学馆的图钉到底落在香港科学馆上,还是偏北了一个街区?有几个图钉被挪了挪;天星小轮、山顶缆车总站、机场都稳稳落在点上。一个"先做出来、再回头看一眼"的循环——当那个负责"看"的东西和负责"做"的东西是同一个时,这件事到现在仍然有点新鲜。

本地化不是翻译

地图是容易的部分。围着地图的那些字,才是带人情味的地方。目标读者读的是内地普通话,而行程小册子悄悄滑进了香港粤语的腔调。我本来把酒店写成"地铁站上盖"——"上盖"是地道的香港地产用语,意思是"盖在车站正上方",对内地读者却几乎不知所云。它被改成了"就在地铁站楼上"。接着是"离港"→"返程","手信"→"伴手礼",还有"有得逛"(一个粤语的语法结构)→"能逛"。

吃的则需要反过来处理。烧味饭、炖奶、滑蛋是粤语菜名,但它们是真实菜单上真实的名字,"纠正"了反而会出错。于是这些保留原名,改为加上普通话注解——烧味饭(即烧腊饭:叉烧、烧鹅、烧肉饭)。至于餐厅本身,在一轮反馈之后,干脆取消了它们各自的地图页:你不会像导航去海洋公园那样导航去吃晚饭,所以它们以文字形式留在每天的安排里,从地图索引上退了场。这些都不是词典意义上的翻译。这是语域、是方言,是知道一个词什么时候是该改的地方话、什么时候是该留着的专有名词。

我的收获

这件事落到了我反复落到的地方:在有限而可核验的任务上,活儿推进得最快。拼瓦片、套用一个已知的坐标变换、确认图钉压在它的标注上——每一步都有一个你能靠眼睛核实的正确答案,这呼应了我在安全扫查和合规工具上的体会。GCJ-02那段弯路,正是那种"发现起来麻烦、一旦知道就微不足道"的领域冷知识——恰恰是值得外包出去的东西。

判断仍然留在我这里:哪十二个地方算"主要"地点,餐厅不需要地图,读惯内地普通话的人不该被迫去琢磨"上盖"。最后这本小册子——十二张中文地图、一份逐日安排、一个能打印的PDF——出自一个没有浏览器、没有API密钥的沙盒。一年前,我可不会猜到这居然是更容易的那个版本。

esc