AGENTUPDATE 技术博客

1000usdinchina.com开发总结(3)-旅行数据 ETL 管线:4.5GB 原始数据 → 干净城市 JSON

1000usdinchina.com开发总结(3)-旅行数据 ETL 管线:4.5GB 原始数据 → 干净城市 JSON
目录

1000usdinchina.com 里的数字,好坏全看背后的数据。100 城的背后 是一条旅行数据 ETL 管线,吞进约 4.5GB 原始源 —— 约 443K 酒店、60 城餐饮数据、57 城地铁 几何、全国景区、高铁和航班 —— 每城输出一个干净、合规的 JSON。

这是系列第 3 篇。

目录

原始数据长啥样

原始旅行数据又大、又脏、又不一致:

  • 单个约 443K 行的酒店表。
  • 60 城合计 4–5GB 的餐饮 CSV。
  • 57 城的地铁站点/线路几何 CSV。
  • 全国景区,加高铁、航班表。

没有一份是即插即用的。编码各异、列在漂移、价格缺失、同一座城有三种拼写。管线的活就是把它变得 枯燥而统一。

flowchart LR
    subgraph Raw[原始源 ~4.5GB]
      H[酒店 .xlsx ~443K]
      F[餐饮 CSV 60 城]
      M[地铁几何 57 城]
      A[景区 / 高铁 / 航班]
    end
    Raw --> X[抽取]
    X --> C[清洗 / 归一化]
    C --> G[聚合]
    G --> O[(data/cities/{slug}/*.json)]
    O --> V[etl-validate]
    V -->|失败| C
    V -->|通过| Ship[入 git]

管线分阶段

  1. 抽取 —— 读每种源格式(xlsx/csv),只取产品需要的字段。
  2. 清洗 / 归一化 —— 统一城市 slug、修编码、把价格强转数字、丢掉无可用信号的行。
  3. 聚合 —— 把每城几千行压成一小撮汇总值:餐费中位数、住宿档位、交通成本。
  4. 输出 —— 写 data/cities/{slug}/*.json(和一个交通矩阵)。这些聚合产物入 git; 原始源数据集永不入 —— 既为合规,也因为几个 GB 不该进仓库。

一个关键细节:原始数据集被显式 git-ignore,只有聚合产物 ship。仓库保持小巧,不含任何 有许可负担的内容。

合规红线

整条管线最重要的规则,是关于输出什么。餐饮数据文件(food.json)只输出聚合 —— 餐费区间、菜系风格、招牌菜。它被严禁含任何店级字段:没有店名、shopid、电话、评分、评论数、 图片、店内 url。

保留(聚合) 剔除(店级)
meal_budget_cnymeal_mid_cnymeal_high_cny 店名
cuisine_styles shopid / 电话
signature_dishes 评分 / 评论数
图片 / 店内 url

这不是锦上添花。聚合正是让数据可用、可分享、又不必转发别人店级清单的关键。它是数据产品爬来的副本之间的分界线。

验证闭环

因为这条红线在重构时太容易不小心越过,管线以一个每次 ETL 改动都跑的验证步骤收尾。它检查 输出 schema,并且关键地断言 food.json 里永不出现任何被禁的店级字段。验证不过,数据就不 ship。 改 ETL 和跑验证是分不开的 —— 你没法跳过自检。

诚实处理数据缺口

真实数据集有窟窿,假装没有就会算出错误预算:

  • 少数城市(如香港、澳门、台湾)餐费缺失,保留 null,导出步骤直接跳过,而不是编数字。
  • 个别城市餐饮覆盖薄,用对标城市的参照倍率补,明确建模,而不是行内瞎猜。
  • 景点票价缺失被当成真风险:null 价会被悄悄计成 ¥0,低估预算,所以把价格核准并打补丁, 而不是任由它把总额悄悄拉低。

把缺口暴露出来 —— 而不是糊过去 —— 才是估算诚实的根本。

要点

  • 旅行数据 ETL 把几个 GB 的脏源,变成小而统一的每城 JSON。
  • 入 git 的是聚合产物,绝不是原始数据集 —— 为合规也为仓库整洁。
  • 只输出聚合(无店级字段)是让数据成为可分享产品的规则,由自动验证步骤强制。
  • 显式建模数据缺口;一个被读成 ¥0 的静默 null 会悄悄污染预算。

常见问题

什么是旅行数据 ETL 管线? 一个把原始旅行源(酒店、餐饮、交通)抽取出来、通过清洗和聚合转换、再加载成干净格式的过程 —— 这里是每城一个 JSON。

为什么聚合而不存原始行? 聚合让数据可用且合规:它回答「这里一顿饭多少钱」,而不必转发单个餐厅的店名、评分或联系方式。

缺失价格怎么处理? 保留 null 并在导出时跳过,或用明确建模的参照倍率补 —— 绝不静默当成 0,那会低估预算。


下一篇 → 手画一张交互式 100 城中国 SVG 地图