通过解析b站api.bilibili.com/x/player/的返回数据,获得当前视频的,基本信息、用户信息、IP地址信息、等级信息和媒体信息,可以获取到当前字幕的链接、背景音乐链接等等
效果展示:
油猴代码:
// ==UserScript==
// @name Bilibili API 信息展示
// @namespace http://tampermonkey.net/
// @version 1.2
// @description 多栏布局美化展示 Bilibili API 返回的精简信息
// @author TheGreat
// @match *://api.bilibili.com/x/player/**
// @grant none
// ==/UserScript==
(function() {
'use strict';
// 字段分组配置
const fieldGroups = {
basicInfo: {
title: '基本信息',
fields: ['aid', 'bvid', 'allow_bp', 'no_share', 'cid', 'max_limit', 'page_no', 'has_next']
},
userInfo: {
title: '用户信息',
fields: ['login_mid', 'login_mid_hash', 'is_owner', 'name', 'permission']
},
ipInfo: {
title: 'IP信息',
fields: ['ip_info']
},
levelInfo: {
title: '等级信息',
fields: ['level_info']
},
mediaInfo: {
title: '媒体信息',
fields: ['subtitle', 'bgm_info']
}
};
// 需要显示的字段及其中文翻译(保持原有的翻译配置)
const displayFields = {
'aid': '视频ID',
'bvid': 'BV号',
'allow_bp': '允许充电',
'no_share': '禁止分享',
'cid': '分P ID',
'max_limit': '最大限制',
'page_no': '页码',
'has_next': '是否有下一页',
'ip_info': {
label: 'IP信息',
fields: {
'ip': 'IP地址',
'zone_ip': '区域IP',
'zone_id': '区域ID',
'country': '国家',
'province': '省份',
'city': '城市'
}
},
'login_mid': '登录用户ID',
'login_mid_hash': '用户ID哈希',
'is_owner': '是否所有者',
'name': '用户名',
'permission': '权限',
'level_info': {
label: '等级信息',
fields: {
'current_level': '当前等级',
'current_min': '当前最小值',
'current_exp': '当前经验',
'next_exp': '下一级经验',
'level_up': '升级时间'
}
},
'subtitle': {
label: '字幕信息',
fields: {
'subtitles': {
label: '字幕列表',
arrayFields: {
'id': 'ID',
'lan': '语言',
'lan_doc': '语言说明',
'is_lock': '是否锁定',
'subtitle_url': '字幕链接',
'id_str': 'ID字符串',
'ai_type': 'AI类型',
'ai_status': 'AI状态'
}
}
}
},
'bgm_info': {
label: '背景音乐信息',
fields: {
'music_id': '背景音乐ID',
'music_title': '背景音乐标题',
'jump_url': '背景音乐链接'
}
}
};
// 创建样式
const style = document.createElement('style');
style.textContent = `
.json-container {
font-family: Arial, sans-serif;
padding: 20px;
background: #fff;
max-width: 1200px;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
.group-container {
background: #f8f9fa;
border-radius: 8px;
padding: 15px;
}
.group-title {
font-size: 16px;
font-weight: bold;
color: #1565C0;
margin-bottom: 10px;
padding-bottom: 5px;
border-bottom: 2px solid #1565C0;
}
.json-item {
margin: 5px 0;
padding: 5px 10px;
background: #fff;
border-radius: 4px;
border: 1px solid #e0e0e0;
}
.json-key {
font-weight: 600;
color: #2196F3;
margin-right: 10px;
}
.json-value {
color: #333;
}
.json-object {
margin-left: 15px;
}
.open-link-btn {
display: inline-block;
margin-left: 10px;
padding: 2px 8px;
background: #2196F3;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
text-decoration: none;
font-size: 12px;
}
.open-link-btn:hover {
background: #1976D2;
}
/* 媒体信息组占据整行 */
.group-container.media-info {
grid-column: 1 / -1;
}
/* 响应式布局 */
@media (max-width: 768px) {
.json-container {
grid-template-columns: 1fr;
}
}
`;
document.head.appendChild(style);
function createLinkButton(url) {
const btn = document.createElement('a');
btn.href = url;
btn.className = 'open-link-btn';
btn.textContent = '打开链接';
btn.target = '_blank';
return btn;
}
function renderValue(key, value, translations, level = 0) {
const item = document.createElement('div');
item.className = 'json-item';
item.style.marginLeft = `${level * 15}px`;
const keySpan = document.createElement('span');
keySpan.className = 'json-key';
keySpan.textContent = translations.label || translations;
const valueSpan = document.createElement('span');
valueSpan.className = 'json-value';
if (value === null) {
valueSpan.textContent = 'null';
} else if (typeof value === 'object') {
if (Array.isArray(value)) {
value.forEach((v, i) => {
if (translations.arrayFields) {
const arrayItem = document.createElement('div');
arrayItem.style.marginLeft = '15px';
Object.entries(translations.arrayFields).forEach(([fieldKey, fieldLabel]) => {
if (v[fieldKey] !== undefined) {
const field = renderValue(fieldKey, v[fieldKey], fieldLabel, level + 1);
arrayItem.appendChild(field);
if (fieldKey === 'subtitle_url' || fieldKey === 'subtitle_url_v2') {
const button = createLinkButton(v[fieldKey]);
field.appendChild(button);
}
}
});
item.appendChild(arrayItem);
}
});
return item;
} else if (translations.fields) {
Object.entries(translations.fields).forEach(([fieldKey, fieldTranslation]) => {
if (value[fieldKey] !== undefined) {
const field = renderValue(fieldKey, value[fieldKey], fieldTranslation, level + 1);
item.appendChild(field);
if (fieldKey === 'jump_url') {
const button = createLinkButton(value[fieldKey]);
field.appendChild(button);
}
}
});
return item;
}
} else {
valueSpan.textContent = value.toString();
}
item.appendChild(keySpan);
item.appendChild(valueSpan);
return item;
}
function createGroup(title, className = '') {
const group = document.createElement('div');
group.className = `group-container ${className}`;
const titleElement = document.createElement('div');
titleElement.className = 'group-title';
titleElement.textContent = title;
group.appendChild(titleElement);
return group;
}
function parseAndDisplay() {
const pre = document.querySelector('pre');
if (!pre) return;
try {
const jsonData = JSON.parse(pre.textContent);
const container = document.createElement('div');
container.className = 'json-container';
const data = jsonData.data;
if (data) {
// 将媒体信息组放在最前面
const mediaGroup = createGroup(fieldGroups.mediaInfo.title, 'media-info');
fieldGroups.mediaInfo.fields.forEach(fieldKey => {
if (data[fieldKey] !== undefined && displayFields[fieldKey]) {
mediaGroup.appendChild(renderValue(fieldKey, data[fieldKey], displayFields[fieldKey]));
}
});
container.appendChild(mediaGroup);
// 根据分组创建布局(跳过媒体信息组)
Object.entries(fieldGroups).forEach(([groupKey, groupInfo]) => {
if (groupKey !== 'mediaInfo') {
const group = createGroup(groupInfo.title, '');
groupInfo.fields.forEach(fieldKey => {
if (data[fieldKey] !== undefined && displayFields[fieldKey]) {
group.appendChild(renderValue(fieldKey, data[fieldKey], displayFields[fieldKey]));
}
});
container.appendChild(group);
}
});
}
document.body.innerHTML = '';
document.body.appendChild(container);
} catch (e) {
console.error('JSON解析错误:', e);
}
}
// 页面加载完成后执行
window.addEventListener('load', parseAndDisplay);
})();
视频的api可以通过以下脚本获得:
// ==UserScript==
// @name B站API请求捕获
// @namespace http://tampermonkey.net/
// @version 0.2
// @description 捕获B站视频API请求
// @author TheGreat
// @match https://www.bilibili.com/video/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
// 创建UI容器
const createUI = () => {
const div = document.createElement('div');
div.id = 'api-capture';
div.style.cssText = `
position: fixed;
top: 50px;
right: 30px;
background: #f9f9f9;
padding: 0px;
border: 1px solid #ccc;
border-radius: 4px;
z-index: 9999;
max-width: 400px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
font-size: 12px;
display: flex;
flex-direction: column;
overflow: hidden;
`;
const toggleButton = document.createElement('button');
toggleButton.textContent = '展开/折叠';
toggleButton.style.cssText = `
background: #4CAF50;
color: white;
border: none;
border-radius: 4px;
padding: 5px;
cursor: pointer;
margin-bottom: 0px;
`;
toggleButton.onclick = () => {
const content = document.getElementById('api-content');
content.style.display = content.style.display === 'none' ? 'block' : 'none';
toggleButton.textContent = content.style.display === 'none' ? '展开' : '折叠';
};
const contentDiv = document.createElement('div');
contentDiv.id = 'api-content';
contentDiv.style.display = 'none'; // 默认折叠
div.appendChild(toggleButton);
div.appendChild(contentDiv);
document.body.appendChild(div);
return contentDiv;
};
const contentDiv = createUI();
// 添加复制和打开按钮
const addButtons = (url) => {
const buttonContainer = document.createElement('div');
buttonContainer.style.marginBottom = '10px';
const copyButton = document.createElement('button');
copyButton.textContent = '复制';
copyButton.style.cssText = `
background: #008CBA;
color: white;
border: none;
border-radius: 4px;
padding: 5px;
cursor: pointer;
margin-right: 5px;
`;
copyButton.onclick = () => {
navigator.clipboard.writeText(url)
.then(() => alert('已复制到剪贴板!'))
.catch(err => console.error('复制失败:', err));
};
const openButton = document.createElement('button');
openButton.textContent = '打开';
openButton.style.cssText = `
background: #FF5722;
color: white;
border: none;
border-radius: 4px;
padding: 5px;
cursor: pointer;
`;
openButton.onclick = () => {
window.open(url, '_blank');
};
buttonContainer.appendChild(copyButton);
buttonContainer.appendChild(openButton);
contentDiv.appendChild(buttonContainer);
};
// 拦截XMLHttpRequest
const XHR = XMLHttpRequest.prototype;
const open = XHR.open;
const send = XHR.send;
XHR.open = function(method, url) {
this._url = url;
return open.apply(this, arguments);
};
XHR.send = function() {
if (this._url.includes('api.bilibili.com/x/player/wbi/v2')) {
const urlDiv = document.createElement('div');
urlDiv.style.marginBottom = '10px';
urlDiv.textContent = this._url;
contentDiv.insertBefore(urlDiv, contentDiv.firstChild);
addButtons(this._url);
// 只保留最近的5条记录
while (contentDiv.children.length > 5) {
contentDiv.removeChild(contentDiv.lastChild);
}
}
return send.apply(this, arguments);
};
})();
这个脚本可以在你网页访问b站的时,在右上角创建一个按钮,用于获取当前视频的api信息