B 站 item_search_video 接口开发,搭建生产级视频搜索服务

「 技术、数据、接口、系统问题欢迎留言私信获取系统演示和API调用 」

B 站item_search_video是目前开发者获取平台公开视频数据最稳定、合规的核心接口,支持关键词检索、分区筛选、时间范围、排序规则等精细化查询,返回视频基础信息、互动数据、UP 主信息等完整字段,广泛用于内容聚合、选题分析、行业数据监测、舆情监控等场景。

相比爬虫抓取,官方 / 合规服务商提供的接口无风控、无封禁、数据实时、支持高并发,是企业级应用的唯一合规选择。本文不讲空话,全程基于真实生产环境开发经验,补充签名机制、异常处理、生产优化、日志规范等专业内容,代码可直接上生产环境使用。

一、接口核心能力与应用场景

1. 接口定位

item_search_video是 B 站批量视频列表检索标准接口,支持多关键词组合检索,可按分区、发布时间、播放量、原创 / 转载、UP 主类型筛选,数据实时同步,新视频收录延迟仅 5-10 分钟,覆盖全品类公开视频数据。

2. 核心特性(生产环境必备)

  • 多关键词逻辑:空格 = AND(同时包含),|=OR(包含任一)
  • 排序支持:相关度、播放量、发布时间、点赞、弹幕、收藏
  • 数据完整性:直接返回播放 / 点赞 / 弹幕 / 收藏,无需二次请求
  • 合规性:仅返回公开数据,不涉及隐私、版权视频源文件
  • 稳定性:企业级支持 30 次 / 分钟,个人 5 次 / 分钟,带缓存机制

3. 典型落地场景

  • 垂直内容平台:聚合游戏、知识、美食等专区视频
  • UP 主选题工具:分析同类视频热度、标签、互动数据
  • 行业数据分析:统计领域视频趋势、用户偏好
  • 舆情监控:实时监控品牌 / 事件相关视频数据变化

二、前置准备:权限申请 + 开发环境

1. 接口权限获取(唯一合规路径)

B 站不开放免费公共接口,只能通过两种方式接入:

  • B 站开放平台(官方):企业认证、申请接口权限、审核 3-7 天,数据最全、合规性最高
  • 合规第三方服务商:10 分钟开通、即用即买、调试友好,适合快速上线

严禁使用爬虫,违反《网络安全法》与 B 站用户协议,会导致法律风险与账号封禁。

2. 开发环境配置

  • 协议:HTTPS 强制
  • 语言:Python(推荐,数据处理最强)
  • 核心依赖:requests hashlib pandas logging
  • 生产工具:Redis(缓存)、Postman(接口调试)

三、核心规则:B 站接口签名机制(必懂)

所有请求必须带签名sign,否则直接返回 401,标准签名流程

  1. 排除sign字段
  2. 所有参数按ASCII 升序排序
  3. 拼接成key=value&key=value格式
  4. 末尾拼接&secret=xxx
  5. MD5 加密 → 32 位大写字符串

签名是接口对接 90% 报错的根源,必须严格遵守。

四、生产级 Python 代码实现(可直接上线)

1. 安装依赖

复制代码
pip install requests pandas openpyxl
# API测试、系统演示控制台:http://console.open.onebound.cn/console/?i=Rookie
  1. 完整代码(含签名、日志、标准化、批量抓取、去重保存)

    import requests
    import hashlib
    import time
    import json
    import logging
    import pandas as pd
    from urllib.parse import urlencode

    ===================== 生产环境配置(建议放入环境变量,不要硬编码)=====================

    CONFIG = {
    "appkey": "你自己的appkey",
    "secret": "你自己的secret",
    "api_url": "https://api.open.onebound.cn/bilibili/item_search_video",
    "save_file": "bilibili_video_result.xlsx",
    "timeout": 15,
    "request_interval": 12, # 个人账号12s,企业账号2s
    }

    ===================== 日志配置(生产必备)=====================

    logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    handlers=[
    logging.FileHandler("bilibili_api.log", encoding="utf-8"),
    logging.StreamHandler()
    ]
    )

    ===================== 1. 签名生成函数(标准实现)=====================

    def make_sign(params: dict, secret: str) -> str:
    params_copy = {k: v for k, v in params.items() if v is not None and k != "sign"}
    sorted_items = sorted(params_copy.items(), key=lambda x: x[0])
    param_str = urlencode(sorted_items, encoding="utf-8")
    final_str = param_str + f"&secret={secret}"
    md5 = hashlib.md5()
    md5.update(final_str.encode("utf-8"))
    return md5.hexdigest().upper()

    ===================== 2. 数据标准化(统一格式,方便入库)=====================

    def format_video_data(item: dict, keyword: str) -> dict:
    pub_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(item.get("pubdate", 0)))
    duration = item.get("duration", 0)
    duration_str = f"{duration//60}:{duration%60:02d}"

    复制代码
     return {
         "关键词": keyword,
         "BV号": item.get("bvid", ""),
         "标题": item.get("title", ""),
         "封面": item.get("cover_url", ""),
         "时长": duration_str,
         "发布时间": pub_time,
         "分区": item.get("category", ""),
         "标签": ",".join(item.get("tags", [])),
         "版权": "原创" if item.get("copyright") == 1 else "转载",
         "近30天播放": item.get("view", 0),
         "点赞": item.get("like", 0),
         "弹幕": item.get("danmaku", 0),
         "收藏": item.get("favorite", 0),
         "投币": item.get("coin", 0),
         "UP主ID": item.get("up_id", ""),
         "UP主名称": item.get("up_name", ""),
         "UP主类型": item.get("up_type", ""),
     }

    ===================== 3. 单页接口请求 =====================

    def video_search(keyword, **kwargs):
    params = {
    "appkey": CONFIG["appkey"],
    "keyword": keyword,
    "time_range": kwargs.get("time_range", "all"),
    "sort_type": kwargs.get("sort_type", "relevance"),
    "page_no": kwargs.get("page_no", 1),
    "page_size": kwargs.get("page_size", 20),
    "timestamp": int(time.time() * 1000),
    }

    复制代码
     if kwargs.get("category"):
         params["category"] = kwargs["category"]
     if kwargs.get("up_type"):
         params["up_type"] = kwargs["up_type"]
     if kwargs.get("copyright"):
         params["copyright"] = kwargs["copyright"]
     if kwargs.get("time_range") == "custom":
         params["start_date"] = kwargs.get("start_date")
         params["end_date"] = kwargs.get("end_date")
    
     # 生成签名
     params["sign"] = make_sign(params, CONFIG["secret"])
    
     try:
         resp = requests.post(
             CONFIG["api_url"],
             data=json.dumps(params),
             headers={"Content-Type": "application/json"},
             timeout=CONFIG["timeout"]
         )
         resp.raise_for_status()
         result = resp.json()
    
         if result.get("code") != 0:
             logging.error(f"接口失败:{result.get('msg')}")
             return []
    
         items = result.get("data", {}).get("item_list", [])
         return [format_video_data(i, keyword) for i in items]
    
     except Exception as e:
         logging.error(f"请求异常:{str(e)}")
         return []

    ===================== 4. 批量多页抓取(带频率控制)=====================

    def batch_search(keyword, max_page=5, **kwargs):
    all_data = []
    for page in range(1, max_page + 1):
    logging.info(f"正在抓取第{page}页:{keyword}")
    data = video_search(keyword, page_no=page, **kwargs)
    if not data:
    break
    all_data.extend(data)
    time.sleep(CONFIG["request_interval"])
    return all_data

    ===================== 5. 保存Excel(自动去重、增量保存)=====================

    def save_to_excel(data):
    if not data:
    logging.warning("无数据可保存")
    return
    df_new = pd.DataFrame(data)
    try:
    df_old = pd.read_excel(CONFIG["save_file"])
    df = pd.concat([df_old, df_new], ignore_index=True)
    except:
    df = df_new
    df = df.drop_duplicates(subset=["BV号"])
    df.to_excel(CONFIG["save_file"], index=False)
    logging.info(f"保存成功,共{len(df)}条数据")

    ===================== 测试调用 =====================

    if name == "main":
    # 搜索关键词:Python教程,知识分区,30天内,按播放量排序
    video_list = batch_search(
    keyword="Python教程 零基础",
    category="knowledge",
    time_range="30days",
    sort_type="play",
    max_page=3
    )
    save_to_excel(video_list)

五、高频错误排查表(开发必备)

表格

错误码 问题原因 解决方案
401 签名错误 /secret 错误 检查参数排序、编码、密钥
403 无权限 / 频率超限 申请接口权限、延长请求间隔
400 参数非法 检查分区名、日期格式
无数据 筛选过严 / 关键词过偏 放宽条件、简化关键词
时间戳过期 本地时间不准 同步网络时间

六、生产环境优化方案(企业级标准)

1. 接口性能优化

  • Redis 缓存:相同关键词缓存 30 分钟,大幅减少请求量
  • 异步请求 :使用aiohttp并发抓取,效率提升 5 倍
  • 智能停止:无数据自动停止翻页

2. 数据质量优化

  • BV号全局去重
  • 过滤下架 / 0 播放无效视频
  • 自动清洗标签、标题冗余字符

3. 合规安全规范

  • appkey/secret 不硬编码,使用环境变量
  • 每 3 个月轮换一次密钥
  • 数据仅自用,不倒卖、不侵权
  • 必须标注 "数据来源:哔哩哔哩"

4. 扩展功能(行业常用)

  • 联动item_get_video获取视频详情、字幕、分 P
  • 构建爆款评分模型:播放完成率、点赞率、弹幕密度
  • 定时监控:APScheduler 定时抓取 + 异常告警

七、总结

item_search_video是 B 站生态最实用的批量视频数据接口,合规、稳定、功能完整,是内容平台、数据分析、舆情监控的底层支撑。

本文提供的代码完全生产可用,包含签名、日志、异常捕获、标准化、批量抓取、去重保存,新手可直接运行,企业可直接集成上线,彻底解决接口对接难、调试复杂、上线不稳定的问题。

相关推荐
EnCi Zheng2 小时前
03ab-PyTorch安装教程 [特殊字符]
人工智能·pytorch·python
SmartBrain2 小时前
从Prompt工程到Harness工程:AI Agent落地之路
人工智能·python·华为·aigc
科技小花9 小时前
全球化深水区,数据治理成为企业出海 “核心竞争力”
大数据·数据库·人工智能·数据治理·数据中台·全球化
X566110 小时前
如何在 Laravel 中正确保存嵌套动态表单数据(主服务与子服务)
jvm·数据库·python
weixin_3709763510 小时前
AI的终极赛跑:进入AGI,还是泡沫破灭?
大数据·人工智能·agi
ZhengEnCi10 小时前
03ab-PyTorch安装教程 📚
python
狐狐生风11 小时前
LangChain 向量存储:Chroma、FAISS
人工智能·python·学习·langchain·faiss·agentai
狐狐生风11 小时前
LangChain RAG 基础
人工智能·python·学习·langchain·rag·agentai
老前端的功夫12 小时前
【Java从入门到入土】28:Stream API:告别for循环的新时代
java·开发语言·python