这件事对开发者的真正信号

特朗普政府移除国家公园内数十块涉及美国负面历史的标识,法院命令恢复。你不需要关心党派政治,但你需要关心:当任意机构可以单方面抹除公共记录时,技术能否提供“不可篡改”的备份和“自动审计”的能力?

作为开发者,这件新闻意味着:

  • 政府网页/公开信息可能在短期内容易被批量修改或删除
  • 法院强制恢复的前提是有记录可查——如果没人提前保存原始内容,恢复就是空话
  • 我们需要一套低成本的自动化监控+归档系统,让任何公开变更都留下证据

下面我直接给一个可运行的项目,实现:

  1. 定时抓取指定政府网站页面
  2. 对比内容变化,用AI摘要出差异
  3. 每次变化自动提交到Git仓库(版本历史)
  4. 同时上传到IPFS,生成不可更改的CID(内容标识)
  5. 通过一个简单的Web仪表盘展示变更时间线和IPFS链接

产品Demo效果展示

假设监控的是美国国家公园管理局(NPS)的“African American Civil War Memorial”页面。

  • 当页面内容被修改/删除时,系统会在1分钟内检测到
  • Git log显示“2026-06-18 删除‘disparage Americans’相关描述”
  • IPFS返回永久链接:https://ipfs.io/ipfs/QmX...,该链接指向被抓取时的原始冻结
  • 仪表盘上红色标记“疑似删除”,绿色标记“新增内容”


图:监控仪表盘,左侧时间线,右侧变更详情与IPFS链接(关键词:digital change monitoring dashboard)

技术选型

组件 技术 理由
爬虫 Python + httpx 异步支持,比requests快;自动处理重定向
内容对比 diff-match-patch + GPT-4o-mini摘要 精确的行级diff + 自然语言描述变化
版本控制 Git Python库 (gitpython) 无需额外服务,每变更自动commit
不可篡改存储 IPFS (通过ipfs-http-client) 内容寻址,一旦上传无法修改
定时触发 GitHub Actions 免费,每30分钟可跑一次
可视化 Streamlit 快速部署,支持markdown渲染

为什么不用简单的网页存档?

  • Internet Archive虽好,但抓取频率低(几天一次),且可被robots.txt阻止
  • 自己搭建Git+IPFS完全可控,且任何人有API Key即可查询历史

核心代码实现

1. 抓取与差异检测

python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
import hashlib
import json
from pathlib import Path
from git import Repo
import httpx
from diff_match_patch import diff_match_patch

# 要监控的URL列表
URLS = [
    "https://www.nps.gov/nama/learn/historyculture/african-american-civil-war-memorial.htm",
    # 可添加更多
]

def fetch_page(url: str) -> str:
    headers = {"User-Agent": "GovMonitor/1.0"}
    resp = httpx.get(url, headers=headers, timeout=10)
    resp.raise_for_status()
    return resp.text

def get_hash(content: str) -> str:
    return hashlib.sha256(content.encode()).hexdigest()

def diff_texts(old: str, new: str) -> str:
    dmp = diff_match_patch()
    diffs = dmp.diff_main(old, new)
    dmp.diff_cleanupSemantic(diffs)
    html = dmp.diff_prettyHtml(diffs)
    return html

2. Git版本管理

python
1 2 3 4 5 6 7 8 9 10 11 12 13 14
REPO_PATH = "/data/monitor_repo"

def init_repo():
    if not Path(REPO_PATH).exists():
        return Repo.init(REPO_PATH)
    return Repo(REPO_PATH)

def commit_change(repo: Repo, url: str, content: str, hash_val: str):
    file_path = f"pages/{url.split('//')[1].replace('/', '_')}.html"
    full_path = Path(REPO_PATH) / file_path
    full_path.parent.mkdir(parents=True, exist_ok=True)
    full_path.write_text(content)
    repo.index.add([file_path])
    repo.index.commit(f"Update {url} | hash={hash_val}")

3. IPFS上传(需要本地或远程IPFS节点)

python
1 2 3 4 5 6
import ipfshttpclient

def upload_to_ipfs(content: str) -> str:
    client = ipfshttpclient.connect('/ip4/127.0.0.1/tcp/5001')
    res = client.add_bytes(content.encode())
    return res  # 返回CID,如 QmX...

4. AI摘要变化(可选,用OpenAI)

python
1 2 3 4 5 6 7 8 9 10 11 12 13
from openai import OpenAI
client = OpenAI()
def summarize_change(old_text: str, new_text: str) -> str:
    prompt = f"""比较以下两个版本的内容,用一句话概括主要变化。
    旧版:{old_text[:1000]}
    新版:{new_text[:1000]}
    变化摘要:"""
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
        max_tokens=60
    )
    return resp.choices[0].message.content.strip()

项目结构和配置

text
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
gov-monitor/
├── .github/
│   └── workflows/
│       └── monitor.yml      # GitHub Actions 定时触发(每30分钟)
├── src/
│   ├── __init__.py
│   ├── scraper.py           # 抓取页面
│   ├── differ.py            # 对比和摘要
│   ├── git_manager.py       # Git提交
│   ├── ipfs_manager.py      # IPFS上传
│   ├── monitor.py           # 主入口
│   └── dashboard.py         # Streamlit仪表盘
├── requirements.txt
├── .env.example             # 配置 API KEY 等
└── README.md

关键配置 .env

text
1 2 3
OPENAI_API_KEY=sk-...
IPFS_NODE_URL=/ip4/127.0.0.1/tcp/5001
GIT_REPO_PATH=/data/monitor_repo

GitHub Actions 定时任务 (monitor.yml)

yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
name: Monitor Government Pages
on:
  schedule:
    - cron: '*/30 * * * *'  # 每30分钟
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - run: pip install -r requirements.txt
      - run: python src/monitor.py
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}

上线要注意的坑

  1. IPFS节点必须持久化 - GitHub Actions每次新环境,IPFS上传后如果不pin,内容可能丢失。解决方案:自己跑一个pinata节点或使用Pinata/Filecoin的远程pinning服务。免费pinata每月1GB够用。

  2. 速率限制 - 政府网站可能限制高频请求。建议抓取间隔至少30秒,或者加上随机延迟。可以先用httpx.Limits控制并发。

  3. robots.txt遵守 - 虽然技术可以绕过,但如果被抓到可能惹法律麻烦。本系统只用于公共信息,且建议在User-agent中注明用途。

  4. 存储膨胀 - 每次全量存储HTML,几个月后可能数百MB。解决方案:只存储diff(增量),但Git本身存储差异,实际上全量存储也ok,每个版本算一次。若担心,压缩存储:zlib.compress(content)

  5. AI摘要费用 - 如果几十个页面每次变化都调API,费用会累积。建议:变化超过一定阈值(如20%字符变化)才调用AI摘要;或者仅对敏感关键词匹配(如“remove”、“delete”)触发。

开发者现在可以做什么

  • 立即Fork这个项目(我把完整代码放在GitHub:github.com/yeqingyuan/gov-monitor),改成监控你关心的任何网站(比如你所在城市的政府公示、法规条例)
  • 把监控结果做成公开仪表盘,用Vercel/Streamlit Community Cloud免费部署,任何人都可以查看变更历史
  • 结合区块链时间戳(比如通过opentimestamps将每次commit的hash登记到比特币链上),提供更强的公证力。这不是必须的,但如果用于法律证据,推荐加上。

我的判断:在政治极化加剧的背景下,公共信息的“易逝性”会越来越严重。技术方案虽然不能阻止删除,但可以确保删除本身留下记录。Git+IPFS这套组合,成本极低(一个月不到1美元),却能让每次修改都无可抵赖。这不只是工具,而是数字时代的公民基础设施。