首页 / 正文

把微信收藏做成可视化:1988 条也不怕,需求降级 + Streamlit 快速出图

Mooko
发布于 2026-04-18 · 5分钟阅读
48 浏览
0 点赞 暴击点赞!

把微信收藏做成可视化:1988 条也不怕

你有没有这种时刻:

  • 想找一篇以前收藏的文章
  • 微信里翻半天
  • 结果越翻越烦,干脆放弃 😅

我折腾了几个小时,准备把自己的微信个人收藏做成“可视化面板”。 然后发现一个事实:我已经收藏了 1988 条

这时候如果还想着“一步到位做成知识库”,基本等于给自己挖坑。 更靠谱的做法是:需求降级

把目标改成:

只做我自己真的会用的那几种视图。

下面这篇就按这个思路来:怎么从 0 到 1 做一个“微信收藏仪表盘”,能搜、能看趋势、能统计来源。你照着做就能跑起来。


1)需求别贪:你真正需要的就这几件事

收藏 1988 条以后,最有价值的不是“把所有内容都保存下来”,而是:让我更快找到它

我建议你把需求砍到这 4 个功能:

  • 全文搜索:按关键词搜标题/摘要/链接
  • 分类视图:比如「工作」「学习」「买东西」「灵感」
  • 时间趋势:你最近是不是又开始乱收藏了?
  • 来源排行榜:你最常收藏哪个公众号/网站

别急着做:

  • 自动同步实时更新
  • 全文抓取网页正文
  • 花里胡哨的知识图谱

这些很诱人,也很容易让项目烂尾。


2)数据从哪来:两条路线,选你能接受的

微信收藏的数据并不是“点一下就导出 CSV”。所以现实一点,给你两条路:

路线 A:最省事(手工导出 + 小批量)

适合你:

  • 收藏主要是“链接/文章”
  • 你不想研究数据库
  • 你只需要最近 200~500 条做个面板

做法:

  • 打开微信收藏
  • 按分类把关键内容转发到文件传输助手
  • 在电脑端复制内容,整理成一个 favorites.csv

CSV 最少包含这些列就够用:

  • title 标题
  • url 链接(没有就留空)
  • note 你自己的备注/摘录
  • created_at 收藏时间(能补就补)
  • category 分类

你会发现:只要面板能跑起来,你就更愿意继续补数据。

路线 B:更自动(从备份里解析)

适合你:

  • 你愿意折腾一小时
  • 想一次性把 1988 条都纳进来

这里提醒一句:微信数据结构和备份方式会变,不同系统/版本差异很大。 我不在这里写“保证 100% 通用的一键脚本”,那是骗人的吗。

你可以用这个策略:

  • 电脑端微信做本地备份(或手机备份到电脑)
  • 找到备份目录里的数据库文件(通常是 SQLite 之类)
  • 用 DB Browser for SQLite 打开,定位“收藏”相关表
  • 把需要的字段导出成 CSV

你一旦把 CSV 拿到手,后面的事就简单了。


3)用 Python 清洗 CSV:把脏数据变成能用的数据

你只需要一个 favorites.csv,哪怕列不全也行。

安装依赖

pip install pandas streamlit altair

清洗脚本(示例)

新建 clean.py

import pandas as pd

# 读入原始导出
raw = pd.read_csv("favorites.csv")

# 统一字段名(按你自己的 CSV 改)
df = raw.rename(columns={
    "标题": "title",
    "链接": "url",
    "备注": "note",
    "时间": "created_at",
    "分类": "category",
})

# 兜底字段
for col in ["title", "url", "note", "created_at", "category"]:
    if col not in df.columns:
        df[col] = ""

# 时间格式
# 没有时间也没关系,后面视图自动降级
if df["created_at"].astype(str).str.len().mean() > 0:
    df["created_at"] = pd.to_datetime(df["created_at"], errors="coerce")

# 去重:按链接优先,其次标题+备注
# 很多人会重复收藏同一篇文章
if df["url"].astype(str).str.len().mean() > 0:
    df = df.sort_values(by=["created_at"], ascending=True)
    df = df.drop_duplicates(subset=["url"], keep="last")
else:
    df = df.drop_duplicates(subset=["title", "note"], keep="last")

# 分类空的给个默认
df["category"] = df["category"].replace("", "未分类")

# 输出干净版本
out = df.reset_index(drop=True)
out.to_csv("favorites_clean.csv", index=False)

print("done:", len(out))

跑一下:

python clean.py

看到 done: 1988(或接近)你就赢一半了。


4)用 Streamlit 做一个“微信收藏仪表盘”

新建 app.py

import pandas as pd
import streamlit as st
import altair as alt

st.set_page_config(page_title="微信收藏仪表盘", layout="wide")

@st.cache_data
def load_data():
    df = pd.read_csv("favorites_clean.csv")
    # 兼容 created_at 可能为空
    if "created_at" in df.columns:
        df["created_at"] = pd.to_datetime(df["created_at"], errors="coerce")
    return df

df = load_data()

st.title("微信收藏仪表盘")
st.caption(f"当前条目数:{len(df)}")

# 侧边栏过滤
with st.sidebar:
    kw = st.text_input("关键词搜索(标题/备注/链接)", "")
    cats = sorted(df["category"].fillna("未分类").unique().tolist())
    cat = st.selectbox("分类", ["全部"] + cats)

# 过滤逻辑
view = df.copy()
if cat != "全部":
    view = view[view["category"].fillna("未分类") == cat]

if kw.strip():
    k = kw.strip().lower()
    def hit(row):
        s = f"{row.get('title','')} {row.get('note','')} {row.get('url','')}".lower()
        return k in s
    view = view[view.apply(hit, axis=1)]

# 主区:列表
st.subheader("收藏列表")
show_cols = [c for c in ["created_at", "category", "title", "url", "note"] if c in view.columns]
st.dataframe(view[show_cols].sort_values(by=["created_at"], ascending=False), use_container_width=True)

# 统计区
col1, col2 = st.columns(2)

with col1:
    st.subheader("分类分布")
    cat_count = view["category"].fillna("未分类").value_counts().reset_index()
    cat_count.columns = ["category", "count"]
    chart = alt.Chart(cat_count).mark_bar().encode(
        x=alt.X("count:Q"),
        y=alt.Y("category:N", sort="-x")
    )
    st.altair_chart(chart, use_container_width=True)

with col2:
    st.subheader("时间趋势")
    if "created_at" in view.columns and view["created_at"].notna().any():
        tmp = view.dropna(subset=["created_at"]).copy()
        tmp["date"] = tmp["created_at"].dt.date
        daily = tmp.groupby("date").size().reset_index(name="count")
        line = alt.Chart(daily).mark_line().encode(
            x="date:T",
            y="count:Q"
        )
        st.altair_chart(line, use_container_width=True)
    else:
        st.info("你的数据里没有可用的时间字段,时间趋势先不画。要不要后面慢慢补?")

启动:

streamlit run app.py

你会得到一个很实用的小面板:

  • 左边筛分类、搜关键词
  • 右边直接看到列表
  • 顺带看分类柱状图和收藏趋势

这玩意儿最大的好处是:

你收藏再多,也不怕。因为你终于能“用”它了。


5)想更爽一点?加两个高频功能

功能 A:一键复制链接

很多时候你不是“阅读”,你是“拿来用”。

Streamlit 里可以加一个按钮,把当前行的 URL 复制到剪贴板(需要前端小组件或额外库)。如果你懒得折腾,最简单的替代方案是:

  • 列表里把 url 显示出来
  • 点击直接打开

功能 B:给未分类的条目做“半自动分类”

你不需要一步到位训练模型。

你可以用最朴素的规则:

  • URL 包含 github.com → 归到「技术」
  • 标题包含「优惠」「券」→ 归到「剁手」
  • 备注包含「todo」「待办」→ 归到「行动」

规则分类写在 clean.py 里就行。


避坑清单(都是我踩过的)

  • 别从“全量自动同步”开局:你会卡在数据获取上,然后放弃。
  • 别纠结字段完不完整:缺时间就不画趋势;缺链接就只做搜索。面板能用最重要。
  • 别把收藏当知识库:收藏是入口,不是归宿。你真正要沉淀的,应该是少量高质量笔记。
  • 别迷信分类:分类越多越难维护。控制在 6~12 个以内就很舒服。

你可以照抄的执行路线(真的能落地)

  • 目标写死:做一个能搜索、能按分类筛、能统计的面板
  • 先搞到一个 favorites.csv(哪怕手工 200 条也行)
  • clean.py 得到 favorites_clean.csv
  • streamlit run app.py 出图
  • 用起来以后,再慢慢把剩下的收藏补进来

你现在的收藏条数是多少? 如果也接近 2000,别慌。把需求降级,你今晚就能看到自己的“收藏全景图”。

OpenClaw
OpenClaw
木瓜AI支持养龙虾啦
木瓜AI龙虾专供API,限时领取免费tokens
可在 OpenClaw接入全球顶尖AI大模型
立即领取