问答
公众号文章链接里的 mid、idx、sn 是什么意思,为什么有两种链接格式?
简短回答
长链接里,__biz 是公众号,mid 是这个号的某一次群发,idx 是文章在这次群发里的位置(1 是头条),sn 是必须和前三个对得上的签名。mp.weixin.qq.com/s/ 短链指向同一篇文章,只是不显示这些参数。okdata 的文章详情两种链接都收,每次 $0.02,返回长链接,并以 sn 作为文章 id。
公众号文章链接有两种样子。长链接来自浏览器地址栏、公众号历史消息页或大多数爬虫,长这样:mp.weixin.qq.com/s?__biz=MzA5NTI3MjIwMA==&mid=2650412873&idx=2&sn=8c1f0e5a3d9b47e6a2c4f17b0d9e3a65&chksm=…&scene=21#wechat_redirect。短链接是 mp.weixin.qq.com/s/ 加一串短码,现在在微信里分享或复制链接,拿到的越来越多是这种。两种打开的是同一篇文章。麻烦出在一份数据里两种混用:同一篇文章被算两次,按链接关联对不上,RSS 阅读器因为链接换了形式又把旧文章推送一遍。
真正有用的四个参数
| 参数 | 例子 | 含义 |
|---|---|---|
__biz |
MzA5NTI3MjIwMA== |
公众号,见 __biz 是什么 |
mid |
2650412873 |
这个号的一次群发;在同一个号内唯一 |
idx |
2 |
文章在这次群发里的位置:1 是头条,2 是次条,依此类推 |
sn |
32 位十六进制 | 和前三个配套的签名;微信会校验,sn 缺失或被改动的链接通常打不开 |
__biz + mid + idx 确定一篇文章,sn 让链接有效。其余都是会话或追踪参数,可以删掉:chksm(校验值,每次抓取都不一样)、scene、sessionid、key、pass_ticket、#rd、#wechat_redirect。干净的长链接只留 __biz、mid、idx、sn 四个。
两个实际的坑
- **链接里的
&。**从 HTML 或 RSS 里抽出来的链接,参数之间常常是&,有时甚至是&。解析或发送之前先换回&。 - **离线换不了。**短码不抓一次文章,是换不出
mid、idx、sn的。抓一次,存下长链接或它的sn,按它去重。
接口怎么处理两种链接
公众号文章详情的 url 两种都收,返回全文、标题、公众号和发布时间,返回的 url 一般是长链接。文章的 id 在链接带 sn 时就是 sn,否则是 __biz、mid、idx 用下划线拼起来,所以不管从哪种链接开始,同一篇文章一般拿到的是同一个 id。历史文章返回的都是长链接,每篇的 idx 放在 ext.position。
| 任务 | 调用次数 | 费用 |
|---|---|---|
| 一条短链或长链换全文 | 1 | $0.02 |
| 表格里 400 条混合链接 | 400 | $8.00 |
| 1000 条链接 | 1000 | $20.00 |
示例:清洗、抓取、去重
import html, os, requests
from urllib.parse import urlparse, parse_qs, urlencode
def clean(link):
link = html.unescape(html.unescape(link)) # & -> &
q = parse_qs(urlparse(link).query)
keep = {k: q[k][0] for k in ("__biz", "mid", "idx", "sn") if k in q}
return "https://mp.weixin.qq.com/s?" + urlencode(keep) if len(keep) == 4 else link
seen = {}
for link in ["https://mp.weixin.qq.com/s/k3Vq8ZtYwLr2PxN0aHd5Fg",
"http://mp.weixin.qq.com/s?__biz=MzA5NTI3MjIwMA==&mid=2650412873&idx=2&sn=8c1f0e5a3d9b47e6a2c4f17b0d9e3a65&chksm=bc2f"]:
r = requests.get("https://api.okdata.online/v1/wechat_mp/articles/get",
headers={"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"},
params={"url": clean(link), "fields": "id,url,title,published_at"}, timeout=60)
item = r.json()["data"]["item"]
seen.setdefault(item["id"], item)
print(len(seen), "篇不重复的文章")
限制
- 已删除的文章,以及被投诉后删除的文章,返回
not_found,不扣费。 - 文章详情不含阅读数和点赞数,
metrics里的字段为 null,meta.unavailable里写明原因。 - 从文章链接取正文的更多细节,见用代码获取公众号文章全文。
资料来源
- V2EX:公众号文章由 biz + mid + idx 确定,mid 在同一账号内唯一
- ClearURLs rules: a WeChat article link only needs __biz, mid, idx and sn; the rest is tracking (issue #13)
- Same WeChat article pushed twice when a feed switches between long and short links (rss2telegram issue #18)
- WeChat link with & escaping fails to open from Python (Stack Overflow)
这个问题出现过的地方(读取于 2026-11-12)
更新于