起点是一个很具体的痛点:在上海租房,看完一圈房子,脑子里全是「这套阳台不行那套厨房太小」,刚看完五套,过两分钟后全忘了,而且也想不清楚到底哪套离地铁更近,那套性价比更好。
这个项目是为了成为你的租房临时大脑 dumper,把临时记忆容量给腾出来。

仓库:https://github.com/Clemmie-Chen/home-rentor


一句话

候选房源散落在贝壳、小红书、中介微信里,信息对不齐、通勤靠脑补。
于是做了个工具:把所有候选房源录到一张带地铁线的地图上,标面积/月租/小区、自动算通勤、记看房后的状态和备注,最后在地图上直观判断哪套值得租。

为什么自己做

现成的租房 App 解决的是「找房源」,但我真正的痛点是看房之后的决策

  • 同一个小区不同中介报价不一样,得自己并排比;
  • 通勤不是「离地铁多远」,而是「到地铁站、实际工作地要多久」,以及合租时要考虑到两个人的工作地点差不多久;
  • 在软件上看完房,脑子里全是具体的装修和照片,没法横向、全面比较真正的房子质量。

这个工具可以帮你

  • 在地图上一眼看清,一套房子最关键的信息,实现一眼比较。信息包括
    • 价格、面积、户型、楼层等基础房源信息
    • 前后4站地铁;离最近的地铁站的距离
    • 自己的备注

几个真正花了时间的技术点

1. 坐标系是个隐形大坑

中国地图有两套坐标:高德 API 返回 GCJ-02(国测局加密),而 OSM 底图 / Leaflet 用国际标准 WGS-84。两者差 300–600 米——足够把一套房子标到隔壁小区

解法:

  • 入库时 eviltransform.gcj2wgs():高德坐标 → 存储/上图
  • 算通勤时再 wgs2gcj() 转回去喂给高德路线 API
  • 地铁数据来自 OSM,本身就是 WGS-84,不用转

这种「转换错了不报错、只是悄悄偏移」的 bug 最折磨人,最后专门在文档里写死了规则。

2. POI 搜索会「张冠李戴」

搜「平吉二村」,高德第一个返回的可能是隔壁的「莲花新城」。所以选 POI 时优先取名字里包含查询词的那个,而不是无脑取第一名。tooltip 标题也做了优先级:小区字段 > 用户输入地址 > 高德 POI 名,并在卡片上单独留一行「定位」展示高德实际命中的 POI 供我核对。

3. 自然语言录入,但解析逻辑有两份

我想要的录入体验是一句话:
梧桐花园 90平 8000/月 两室两厅 电梯 朝南 → 自动拆成字段 + 地理编码上图。

但录入有两个入口:网页(parseInput)和飞书机器人(bridge.pyparse_text)。两份解析器必须保持同步,改一处就得改另一处。这是有意的取舍——为了让飞书那条链路不依赖前端——但代价是每次改规则都要提醒自己「两边都改」。

还有个设计:原文是唯一数据源。每条房源都存了录入的原始文本,前端每次启动用当前解析器重新解析所有原文。这样解析器升级后,老房源会自动补全新字段,不用做数据迁移。

4. 家用宽带没有公网 IP,怎么手机访问

想在外面用手机看,但家庭宽带没有公网 IPv4。方案:Mac mini 上 server.py 由 launchd 常驻(开机自启、崩溃自拉起),再用 Cloudflare Tunnel 出站打洞,把自己的域名指到 localhost:8765。不依赖公网 IP,也不用端口转发。

踩的坑:不能用 brew services start cloudflared——它裸跑 cloudflared 不带参数,起不了隧道。得自己写 launchd plist 指定 config 和 tunnel 名。


如果重来会改什么

  • 服务端目前无鉴权,拿到 URL 就能读写。个人用够了,但要长期公网跑得加 Cloudflare Access。
  • 「两份解析器」是债,理想状态是抽成一份能被前后端共用的逻辑。
  • 「最后写入者赢」的同步在多设备同时编辑时会丢数据,目前靠「就我一个人用」规避。

技术栈速查

选型理由
地图Leaflet + CartoDB Positron轻、免费、底图素净不抢房源标记
坐标转换eviltransform中国地图 GCJ-02 ↔ WGS-84 必需
后端Python 标准库 http.server零依赖、单文件、够用
地理/通勤高德 Web 服务 API国内数据准,免费额度 ~5000/日
录入自然语言解析(自写正则)一句话录入,懒是第一生产力
部署Mac mini + launchd + Cloudflare Tunnel家用宽带无公网 IP 的出站方案
持久化localStorage + 服务端 data.json单用户多设备,简单同步

Repo: https://github.com/Clemmie-Chen/home-rentor