给 AI

操作指南

微博 API Python 教程:关键词搜索、用户资料和热搜(2026)

三个接口:微博搜索、按 UID 取微博账号信息、微博热搜,每个都是带 API key 的普通 GET 请求,不用申请 OAuth 应用,也不用登录 Cookie。下面的示例一共 9 次调用,花费 $0.018;失败的调用不扣费。

更新于

微博有开放 API,但它是围着“授权你应用的那个用户”设计的。open.weibo.com 上的接口列表都走 OAuth 2.0:读授权用户的资料、他自己发的微博、他的首页时间线、某条微博的评论,外加分享链接、发评论这几个写入接口。标了“高级权限”的接口要另外申请。关键词搜索不在常规列表里。最接近的 search/topics 是高级接口,只能搜某个 #话题# 下的微博(关键词必须是两个 # 之间的话题),而且只返回最新的 200 条。更大范围的数据要走微博的商业数据接口,那是另一套订阅条款。

所以大多数用 Python 抓微博的脚本,都是带着登录 Cookie 去爬网页,不用 Cookie 怎么按关键词搜微博里讲过这条路的麻烦。这篇既不用申请 OAuth 应用,也不用 Cookie:每次调用就是一个带 API key 的 HTTPS GET,依赖只有 requests。最后得到一个微博内容 CSV、一个发帖账号 CSV,以及和热搜榜的对照结果。

分步操作

先设好 key:export OKDATA_API_KEY=okd_...。每次返回都有 code(成功为 "ok");列表结果在 data.items,翻页信息在 page;单个对象在 data.item。

第一步:按关键词搜微博

微博搜索的 query 按你在微博搜索框里的输入来填,sort 可选 hot(默认,热门)或 latest(实时,最新在前)。一次调用返回约 10 条微博,每次 $0.002。每条有 id、url、text、published_at、images、hashtags,以及 metrics.likes、metrics.comments 和 metrics.reposts;视频微博在 metrics.views 里还有播放数。作者信息包括 author.id(UID)、author.name、author.followers 和 author.verified。

curl -G "https://api.okdata.online/v1/weibo/posts/search" -H "Authorization: Bearer $OKDATA_API_KEY" \
  --data-urlencode 'query=预制菜' --data-urlencode 'sort=latest'

从第二页起,把 page.next_cursor 原样作为 cursor 传回去;page.has_more 为 false 时停下。加上 view=full,ext.region 是微博显示的“发布于”地点,ext.source 是发帖客户端,ext.is_long_text 标出在搜索里被截断的长微博。

第二步:查发帖账号

微博账号信息的 id 填数字 UID,也就是搜索结果里的 author.id,或者 weibo.com/u/5730129846 里的那串数字。每次 $0.002,返回 name、bio、followers、following、posts 和 verified;加上 view=full,ext 里还有 verified_reason、ip_location、location 和 gender。主页用了个性域名、不知道 UID 的,看怎么按 UID 查微博用户资料。

curl -G "https://api.okdata.online/v1/weibo/users/get" -H "Authorization: Bearer $OKDATA_API_KEY" \
  --data-urlencode 'id=5730129846' --data-urlencode 'view=full'

第三步:读热搜榜

微博热搜没有参数。一次调用返回当前的榜单,约 50 行,每次 $0.002:rank、name(热搜词)、heat(热度)和 url(这个话题的搜索页)。榜单里的广告位已经去掉。

curl -G "https://api.okdata.online/v1/weibo/trends/list" -H "Authorization: Bearer $OKDATA_API_KEY"

第四步:完整脚本

辅助函数检查 body["code"],账号已注销或被封时返回 None,遇到限流或上游繁忙就用同一个 Idempotency-Key 重试,重试不会重复扣费。MAX_PAGES 控制搜索的页数。

import csv
import os
import time
import uuid

import requests

API = "https://api.okdata.online"
KEY = os.environ["OKDATA_API_KEY"]
QUERY = "预制菜"
MAX_PAGES = 3     # 搜几页;每页一次调用
TOP_AUTHORS = 5   # 查几个账号


def call(path, **params):
    headers = {"Authorization": f"Bearer {KEY}", "Idempotency-Key": str(uuid.uuid4())}
    for attempt in range(4):
        body = requests.get(API + path, headers=headers, params=params, timeout=60).json()
        if body["code"] == "ok":
            return body
        if body["code"] == "not_found":
            return None  # 已删除、被封或不公开:不扣费
        if body.get("retry") in ("yes", "same_key"):
            time.sleep(body.get("retry_after_seconds") or 2 ** attempt)
            continue
        raise RuntimeError(f"{body['code']}: {body['message']} (request {body['request_id']})")
    raise RuntimeError(f"{path}: 重试 4 次仍然失败")


def search(query, max_pages):
    cursor = None
    for _ in range(max_pages):
        body = call("/v1/weibo/posts/search", query=query, sort="latest", view="full",
                    **({"cursor": cursor} if cursor else {}))
        yield from body["data"]["items"]
        if not body["page"]["has_more"]:
            return
        cursor = body["page"]["next_cursor"]


posts = list(search(QUERY, MAX_PAGES))
with open("weibo_posts.csv", "w", newline="", encoding="utf-8-sig") as f:
    out = csv.writer(f)
    out.writerow(["post_id", "published_at", "uid", "author", "text", "likes", "comments", "reposts", "region", "url"])
    for p in posts:
        m = p["metrics"]
        out.writerow([p["id"], p["published_at"], p["author"]["id"], p["author"]["name"], p["text"],
                      m["likes"], m["comments"], m["reposts"], p["ext"].get("region"), p["url"]])

authors = {p["author"]["id"]: p["author"] for p in posts}
biggest = sorted(authors.values(), key=lambda a: a["followers"] or 0, reverse=True)[:TOP_AUTHORS]
with open("weibo_authors.csv", "w", newline="", encoding="utf-8-sig") as f:
    out = csv.writer(f)
    out.writerow(["uid", "name", "followers", "following", "posts", "verified", "verified_reason", "ip_location"])
    for a in biggest:
        body = call("/v1/weibo/users/get", id=a["id"], view="full")
        if body:
            u = body["data"]["item"]
            out.writerow([u["id"], u["name"], u["followers"], u["following"], u["posts"], u["verified"],
                          u["ext"].get("verified_reason"), u["ext"].get("ip_location")])

board = call("/v1/weibo/trends/list")["data"]["items"]
on_board = [t for t in board if QUERY in t["name"]]
print(f"{len(posts)} 条微博,{len(biggest)} 个账号;", "在热搜上:" if on_board else "不在热搜上",
      ",".join(f"第 {t['rank']} 名 {t['name']}" for t in on_board))

跑一遍就是上面的示例:3 页搜索、5 次账号查询、1 次热搜,共 9 次调用。每天跑一次、跑满一个月(每天同样 9 次),是 $0.54。

注意事项

  • 搜得到什么。 结果就是微博自己的搜索能给的;被微博从搜索里隐藏的内容不会出现,翻页深度也跟微博搜索一样有上限。
  • 长微博。 搜索结果里的长微博可能被截断。看 ext.is_long_text(需要 view=full),全文在 url 指向的微博页面上。
  • null 字段。 微博不展示分享数和收藏数,所以 metrics 里这两项是 null;账号的累计获赞也是 null。每个 null 字段都在 meta.unavailable 里注明。
  • 目录里没有的。 评论楼和账号自己的微博列表目前不覆盖;能用的是搜索、账号资料和热搜。
  • UID。 账号信息只认数字 UID,不认昵称或链接。
  • 不收钱的情况。 已注销或被封的账号返回 not_found,不扣费,限流和其他错误也一样。24 小时内同样的请求配同样的 Idempotency-Key,会拿回存下的结果,meta.replayed 为 true。

只想盯着榜单看,打开微博热搜工具。要长期跟踪大家怎么评价一个品牌,可以看口碑分析。

示例花费

按最新搜 3 页“预制菜”,查粉丝最多的 5 个发帖账号,再读一次热搜榜

接口调用次数单价小计
微博搜索3$0.002$0.006
微博账号信息5$0.002$0.01
微博热搜1$0.002$0.002
合计9$0.018

按本页生成时的价格计算。失败的调用不扣费。

在你的 AI 里用(MCP)

先接好 MCP 服务,然后直接说你要什么。智能体会自己找到这些接口、看清价格,再用你的余额调用。

可以这样说在微博按最新搜“预制菜”,读三页。找出粉丝最多的 5 个作者,给我他们的资料,再告诉我这个话题现在在不在热搜上。

智能体第一次调用 call 工具时发送的内容
{
  "endpoint": "weibo.posts.search",
  "params": {
    "query": "新品发布"
  },
  "idempotency_key": "<新的 UUID>"
}

配置 MCP 服务 →

资料来源

  1. 微博开放平台:微博API(接口列表)open.weibo.com · 读取于
  2. 微博开放平台:2/search/topicsopen.weibo.com · 读取于

接上一次,以后直接问 AI。

新 key 自带 $0.10 试用额度。贴一句话,就能接进你的智能体。

免费开始
一句话接进你的 AI

把这句话发给你的智能体

读一下 https://okdata.online/zh/agents.md,帮我把 okdata 配好;我的 key 在环境变量 OKDATA_API_KEY 里。

Claude Code、Cursor、Codex 等能打开网址的智能体,读完会自己配好。

MCP 地址https://api.okdata.online/mcp