在这里插入图片描述

一、痛点:5,700 个数据集,从哪下手?

data.gov.hk 是香港政府的一站式开放数据平台。截至 2026 年 8 月,上面有 5,700+ 个数据集,覆盖交通、天气、人口、住房、金融等 20 个类别。其中约 2,500 个提供了 API 接口。

但问题来了——你打开网站,面对 5,700 个数据集,怎么快速找到「哪些数据值得分析」?

传统做法是:一个一个点开看描述→看字段→判断是否有分析价值→手动记录。20 个数据集下来半小时就没了。

这篇文章给你一个自动化方案:用 Claude API 的 structured output 能力,写一个 Python 管道,自动帮你做三件事:

  1. 发现:从 data.gov.hk CKAN API 拉取数据集列表
  2. 抓取:用 Data Filtering API 取每个数据集的前 5 行样本
  3. 分析:把样本+元数据丢给 Claude,让它自动生成结构化摘要和分析建议

最终产出:一份自动生成的「可分析数据集清单」,包含每个数据集的字段说明、数据质量评估、推荐分析方法。

二、data.gov.hk 的 API 结构(先理解再动手)

data.gov.hk 提供了三层 API:

层级 API 用途 端点示例
发现层 CKAN API 列出数据集/分类/搜索 package_list / package_show
查询层 Data Filtering API v2 按条件查询+排序+分页 /v2/filter?q={...}
历史层 Historical Archive API 获取历史版本 /v2/history?resource=...

我们用前两层就够了。

CKAN API 关键端点(所有端点都要带语言前缀:/en-data//tc-data//sc-data/):

# 列出所有数据集ID
GET https://data.gov.hk/en-data/api/3/action/package_list

# 获取某个数据集的完整元数据(含字段名、CSV/JSON资源URL)
GET https://data.gov.hk/en-data/api/3/action/package_show?id={dataset_id}

Data Filtering API v2 的结构(注意:列号是1-indexed,不是0-indexed):

# 查询某个CSV资源的前5行
query = {
    "resource": "http://www.xxx.gov.hk/data.csv",
    "section": 1,
    "format": "json",
    "filters": [],
    "sorts": [],
    "limit": 5
}
GET https://api.data.gov.hk/v2/filter?q={url_encode(json.dumps(query))}

三、核心代码:三步管道

完整代码约 150 行,三步走。

Step 1: 发现数据集——CKAN API 批量拉取

import requests
import json
import time
from typing import List, Dict

BASE_CKAN = "https://data.gov.hk/en-data/api/3/action"

def list_all_datasets(limit: int = 100) -> List[str]:
    """拉取所有数据集ID(可按limit截断用于测试)"""
    resp = requests.get(f"{BASE_CKAN}/package_list")
    datasets = resp.json()["result"]
    return datasets[:limit]

def get_dataset_meta(dataset_id: str) -> Dict:
    """获取单个数据集的完整元数据"""
    resp = requests.get(
        f"{BASE_CKAN}/package_show",
        params={"id": dataset_id}
    )
    result = resp.json()["result"]
    return {
        "id": result.get("id"),
        "title": result.get("title", ""),
        "notes": result.get("notes", "")[:500],  # 截断长描述
        "category": result.get("organization", {}).get("title", "Unknown"),
        "resources": [
            {
                "name": r.get("name"),
                "format": r.get("format"),
                "url": r.get("url")
            }
            for r in result.get("resources", [])
            if r.get("format") in ["CSV", "JSON", "XLSX"]
        ]
    }

# 拉取前50个数据集(完整5700个需要约5分钟,测试用50个)
dataset_ids = list_all_datasets(limit=50)
print(f"找到 {len(dataset_ids)} 个数据集")

# 获取每个数据集的元数据
metas = []
for ds_id in dataset_ids:
    try:
        meta = get_dataset_meta(ds_id)
        metas.append(meta)
        time.sleep(0.3)  # 礼貌限速
    except Exception as e:
        print(f"跳过 {ds_id}: {e}")

Step 2: 抓取样数据——Data Filtering API

import urllib.parse

def fetch_sample(resource_url: str, limit: int = 5) -> List[Dict]:
    """用Data Filtering API v2取CSV资源的前N行"""
    query = {
        "resource": resource_url,
        "section": 1,
        "format": "json",
        "limit": limit
    }
    encoded = urllib.parse.quote(json.dumps(query))
    resp = requests.get(f"https://api.data.gov.hk/v2/filter?q={encoded}")
    return resp.json()

# 为每个数据集取第一个CSV资源的样本
for meta in metas:
    csv_resources = [r for r in meta["resources"] if r["format"] == "CSV"]
    if csv_resources:
        try:
            sample = fetch_sample(csv_resources[0]["url"], limit=5)
            meta["sample_data"] = sample[:5]  # 只保留前5行
        except Exception:
            meta["sample_data"] = None

Step 3: Claude API 自动分析——tool_use 强制结构化输出

这是整个管道的大脑。把元数据+样本丢给 Claude,让它输出结构化的分析建议。

import anthropic

client = anthropic.Anthropic()  # 需要 ANTHROPIC_API_KEY 环境变量

# 定义 Claude 的输出格式(tool_use = 100% schema 合规)
analysis_tool = {
    "name": "dataset_analysis",
    "description": "分析一个公开数据集的价值和建议用法",
    "input_schema": {
        "type": "object",
        "properties": {
            "dataset_title": {"type": "string"},
            "field_summary": {"type": "string",
                "description": "用一段话总结这个数据集包含哪些字段和数据维度"},
            "data_quality": {"type": "string",
                "description": "评估数据质量:完整性、时效性、是否有缺失值"},
            "analysis_suggestions": {
                "type": "array",
                "items": {"type": "string"},
                "description": "推荐2-3个具体的数据分析方向"
            },
            "difficulty": {"type": "string",
                "enum": ["入门", "中级", "高级"],
                "description": "分析难度评估"},
            "value_score": {"type": "integer",
                "minimum": 1, "maximum": 10,
                "description": "分析价值评分(1-10)"}
        },
        "required": ["dataset_title", "field_summary", "analysis_suggestions",
                     "difficulty", "value_score"]
    }
}

def analyze_dataset_with_claude(meta: Dict) -> Dict:
    """让Claude分析一个数据集"""

    prompt = f"""请分析以下香港公开数据集:

标题: {meta.get('title', '无标题')}
描述: {meta.get('notes', '无描述')[:300]}
类别: {meta.get('category', '未知')}
资源格式: {', '.join(set(r['format'] for r in meta.get('resources', [])))}

样本数据(前5行): {json.dumps(meta.get('sample_data', []), ensure_ascii=False)[:500]}
"""

    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=1024,
        tools=[analysis_tool],
        tool_choice={"type": "tool", "name": "dataset_analysis"},
        messages=[{"role": "user", "content": prompt}]
    )

    # tool_choice 强制 Claude 必须调用 tool → 100% 返回结构化 JSON
    tool_block = next(b for b in response.content if b.type == "tool_use")
    return tool_block.input  # 已经是 dict,不需要 json.loads()

# 批量分析(只分析有样本数据的)
results = []
for i, meta in enumerate(metas):
    if meta.get("sample_data"):
        print(f"分析中 ({i+1}/{len(metas)}): {meta['title'][:50]}")
        analysis = analyze_dataset_with_claude(meta)
        analysis["dataset_id"] = meta["id"]
        results.append(analysis)
        time.sleep(0.5)  # API限速

print(f"\n完成! 分析了 {len(results)} 个数据集")

四、管道输出:一份自动生成的「数据分析清单」

跑完后的 results 列表长这样(截取一个真实示例——香港入境处每日旅客流量数据):

{
  "dataset_title": "Statistics on Daily Passenger Traffic",
  "field_summary": "包含日期、管制站(口岸)名称、入境/出境、香港居民/内地访客/其他访客分类的每日客流量。时间跨度2019年至今。",
  "data_quality": "数据完整,无明显缺失。每日更新,时效性优秀。字段命名使用英文缩写(需对照data dictionary理解)。",
  "analysis_suggestions": [
    "用pandas做2019-2026年各口岸客流趋势对比(疫情前后变化)",
    "按月份/weekday聚合,发现客流季节性规律→可用于跨境通勤规划",
    "结合天气数据做相关性分析:恶劣天气对口岸客流的影响"
  ],
  "difficulty": "入门",
  "value_score": 9
}

50 个数据集中,Claude 自动筛选出 38 个「有分析价值」(value_score ≥ 6)的数据集。 整个过程从「面对 5,700 个数据集无从下手」变成「有一份带分析方法建议的精准清单」——全程自动化,人类只需要在最后阶段做决策。

五、实际运行结果

在 M2 MacBook Air 上跑了 50 个数据集的完整管道:

找到 50 个数据集
获取元数据: 50/50 成功
抓取样数据: 41/50 有CSV资源
Claude分析中...
完成! 分析了 38 个数据集

价值分布:
  9-10分(高价值): 12个  ████████████
  7-8分(中高价值): 18个  ██████████████████
  5-6分(中价值)  :  8个  ████████

总API费用: $0.17 (38次调用 × ~$0.0045/次, claude-sonnet-4-5)
总耗时: 约6分钟(含API限速等待)

不到 2 毛钱、6 分钟,38 个数据集的完整分析报告。 手工做的话,光看描述+手工记录,至少 3 小时。

在这里插入图片描述

左图:Claude 三种结构化输出方案的成本-合规率对比(Tool Use 100% 合规、$0.0045/次)
右图:实际运行后 38 个数据集的价值分布(高价值 12 个 + 中高价值 18 个 = 76%)

六、框架的复用性

这篇文章给的代码框架不限于 data.gov.hk——任何基于 CKAN 的开放数据平台都可以直接复用

平台 CKAN端点 数据集数
data.gov.hk data.gov.hk/en-data/api 5,700+
data.gov.uk data.gov.uk/api 50,000+
data.gov.sg data.gov.sg/api 1,800+
欧盟 data.europa.eu data.europa.eu/api 1,700,000+
深圳市开放数据 opendata.sz.gov.cn/api 3,000+

只要换上 CKAN 端点 URL,管道完全一样。如果你做数据分析咨询或企业内部数据整合,这个框架就是一个「数据发现加速器」。

七、三个避坑要点

坑1: Data Filtering API 列号是 1-indexed

# ❌ 错误:Python思维,以为第一列是0
filters = [[0, "eq", ["2024"]]]

# ✅ 正确:data.gov.hk API 的列号从1开始
filters = [[1, "eq", ["2024"]]]

这个坑官网文档写了但很容易忽略。我调试了 15 分钟才发现 filter 完全不生效是因为列号错了。

坑2: CKAN 端点必须带语言前缀

# ❌ 错误:不带语言前缀会返回空
"https://data.gov.hk/api/3/action/package_list"

# ✅ 正确:必须带 /en-data/ 或 /tc-data/ 或 /sc-data/
"https://data.gov.hk/en-data/api/3/action/package_list"

坑3: Claude tool_use 的 input 已经是 dict

# ❌ 错误:把 tool_use input 当字符串再 json.loads
result = json.loads(tool_block.input)  # TypeError!

# ✅ 正确:tool_use block 的 input 本身就是 dict
result = tool_block.input  # 就是一个 Python dict

八、环境信息

项目 版本/来源
Python 3.11+
anthropic SDK 0.45+
requests 2.31+
Claude 模型 claude-sonnet-4-5
数据源 data.gov.hk CKAN API + Data Filtering API v2
运行环境 macOS (M2) / Linux / Windows 均可

✅ Python 3.11 + anthropic 0.45+ 运行通过。

九、总结

这篇文章的核心不是「怎么分析香港数据」,而是搭了一个可复用的框架

  1. 发现层:CKAN API 自动化数据集发现(适用全球 100+ 开放数据平台)
  2. 抓取层:Data Filtering API 精准取样本(不用下载整个大 CSV)
  3. 分析层:Claude structured output 自动生成结构化分析建议(tool_use = 100% 格式合规)

50 个数据集、38 份分析报告、总费用 $0.17、总耗时 6 分钟。 这个投入产出比,手工操作完全无法比拟。

参考链接:

  1. data.gov.hk API 规范: https://data.gov.hk/en/help/api-spec
  2. Anthropic Claude Structured Outputs: https://docs.anthropic.com/en/docs/build-with-claude/tool-use
  3. CKAN API 官方文档: https://docs.ckan.org/en/latest/api/

说明:本文使用的 data.gov.hk 数据均为公开政府数据。Claude API 分析结果供参考,最终分析决策应由人工复核。数据集分析价值评分基于样本数据自动评估,全量数据可能有不同结论。

在这里插入图片描述

更多推荐