灵猴市集Linghou Market

搜索哔哩哔哩视频

哔哩哔哩bilibili-video-search

用途 搜索哔哩哔哩公开视频或用户,返回适合继续打开详情页或用户主页的简明结果。 执行前提 需要在 bilibili.com 页面执行。脚本通过页面环境请求公开接口,接口可能因为风控、频率、地域或权限限制返回失败。 参数 query:必填,搜索关键词。 type:可选,video 或 user,默认 video。 page:可选,页码,默认 1,范围 1 到…

视频搜索用户
版本1.0.0
扫描passed
更新2026-06-28
超时30000ms

匹配范围

*://*.bilibili.com/*

排除范围

未声明

能力声明

dom.read

代码

源码已展开
1const input = (typeof params === "object" && params !== null) ? params : {};2const host = String(location.hostname || "").toLowerCase();3 4if (!/(^|\.)bilibili\.com$/.test(host)) {5  throw new Error("请在 bilibili.com 页面执行。");6}7 8function readQuery(value) {9  if (typeof value !== "string") {10    throw new Error("query 为必填字符串。");11  }12  const text = value.trim();13  if (!text) {14    throw new Error("query 不能为空。");15  }16  return text;17}18 19function parseType(value) {20  if (value === undefined || value === null || value === "") return "video";21  if (value !== "video" && value !== "user") {22    throw new Error("type 只能是 video 或 user。");23  }24  return value;25}26 27function parseInteger(value, field, defaultValue, min, max) {28  if (value === undefined || value === null || value === "") return defaultValue;29  const number = Number(value);30  if (!Number.isInteger(number) || number < min || number > max) {31    throw new Error(field + " 必须是 " + min + " 到 " + max + " 之间的整数。");32  }33  return number;34}35 36function cleanText(value) {37  return String(value ?? "")38    .replace(/<[^>]*>/g, "")39    .replace(/&nbsp;/g, " ")40    .replace(/&amp;/g, "&")41    .replace(/&quot;/g, '"')42    .replace(/&#39;/g, "'")43    .replace(/&lt;/g, "<")44    .replace(/&gt;/g, ">")45    .replace(/&#(\d+);/g, (_, code) => String.fromCharCode(Number(code)))46    .replace(/&#x([0-9a-fA-F]+);/g, (_, code) => String.fromCharCode(parseInt(code, 16)))47    .replace(/\s+/g, " ")48    .trim();49}50 51function extractBvid(value) {52  const match = String(value || "").match(/(?:\/video\/)?(BV[0-9A-Za-z]{10,})/);53  return match ? match[1] : "";54}55 56const query = readQuery(input.query);57const type = parseType(input.type);58const page = parseInteger(input.page, "page", 1, 1, 20);59const limit = parseInteger(input.limit, "limit", 20, 1, 50);60const searchType = type === "user" ? "bili_user" : "video";61const apiUrl = "https://api.bilibili.com/x/web-interface/wbi/search/type"62  + "?search_type=" + encodeURIComponent(searchType)63  + "&keyword=" + encodeURIComponent(query)64  + "&page=" + encodeURIComponent(String(page));65const response = await fetch(apiUrl, { credentials: "include" });66 67if (!response.ok) {68  throw new Error("搜索失败,接口状态码:" + response.status + "。");69}70 71const payload = await response.json();72 73if (!payload || payload.code !== 0 || !payload.data) {74  const message = payload && payload.message ? payload.message : "未知错误";75  throw new Error("搜索失败:" + message + "。");76}77 78const result = Array.isArray(payload.data.result) ? payload.data.result : [];79 80if (type === "user") {81  return result.slice(0, limit).map((item, index) => {82    const mid = item.mid ?? item.id ?? null;83    return {84      rank: index + 1,85      name: cleanText(item.uname ?? item.name ?? ""),86      sign: cleanText(item.usign ?? item.sign ?? ""),87      fans: item.fans ?? item.fans_count ?? 0,88      mid,89      url: mid ? "https://space.bilibili.com/" + mid : ""90    };91  });92}93 94return result.slice(0, limit).map((item, index) => {95  const bvid = item.bvid || extractBvid(item.arcurl);96  return {97    rank: index + 1,98    title: cleanText(item.title || ""),99    author: cleanText(item.author || item.uname || ""),100    play: item.play ?? 0,101    duration: item.duration || "",102    bvid,103    url: bvid ? "https://www.bilibili.com/video/" + bvid : (item.arcurl || "")104  };105});