从零到一:手把手打造你的第一个微博视频下载油猴脚本
不知道你有没有过这样的经历:在微博上刷到一个特别有意思的短视频,想保存下来分享给朋友或者自己收藏,结果发现微博官方并没有提供下载按钮。这时候你可能会想到用各种第三方工具,或者打开开发者工具去网络请求里找视频链接,整个过程既繁琐又不够优雅。如果你也有类似的困扰,那么今天这篇文章就是为你准备的。
我最近在开发一些浏览器自动化工具时,重新审视了油猴脚本这个老朋友。说实话,虽然现在各种浏览器扩展层出不穷,但油猴脚本那种轻量、灵活、即写即用的特性,在很多场景下依然无可替代。特别是对于微博视频下载这种特定需求,写一个专属脚本往往比安装一个功能臃肿的扩展要高效得多。
这篇文章的目标读者是那些有一定JavaScript基础,但可能从未接触过油猴脚本开发的开发者。我会用一个完整的微博视频下载脚本作为案例,带你走过从环境配置、脚本结构分析、代码编写到调试发布的完整流程。整个过程不需要复杂的开发环境,只需要一个浏览器和文本编辑器就能开始。
1. 油猴脚本开发环境搭建与核心概念
1.1 选择合适的脚本管理器
在开始编写油猴脚本之前,我们需要先安装一个脚本管理器。目前主流的浏览器脚本管理器有几个选择,每个都有其特点。我个人的选择标准是:开源、活跃维护、功能完整。
Tampermonkey 是目前最流行的选择,支持Chrome、Firefox、Safari等几乎所有主流浏览器。它的优势在于生态完善,有大量的用户脚本库可以直接安装使用。不过它的免费版本功能就足够我们开发使用了。
Violentmonkey 是另一个优秀的选择,完全开源且跨平台。我更喜欢它的简洁界面和更快的更新响应速度。对于开发者来说,它的调试工具也更加友好。
安装过程非常简单,以Chrome浏览器为例:
- 打开Chrome网上应用店
- 搜索"Tampermonkey"或"Violentmonkey"
- 点击"添加到Chrome"
安装完成后,你会在浏览器右上角看到脚本管理器的图标。点击图标,选择"管理面板",就能进入脚本管理界面。
注意:有些浏览器可能无法直接访问应用商店,这时候可以考虑从GitHub下载crx文件进行手动安装。不过对于大多数用户来说,直接通过应用商店安装是最简单安全的方式。
1.2 理解油猴脚本的基本结构
油猴脚本本质上是一段JavaScript代码,但它有一个特殊的元数据块(Metadata Block),这个块告诉脚本管理器这个脚本的基本信息。让我们先来看一个最简单的脚本结构:
// ==UserScript==
// @name 我的第一个脚本
// @namespace http://example.com/
// @version 1.0
// @description 这是一个示例脚本
// @author 你的名字
// @match https://www.example.com/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
// 你的代码从这里开始
console.log('脚本已加载!');
})();
这个元数据块包含了几个关键信息:
- @name: 脚本的名称,会显示在脚本管理器中
- @namespace: 命名空间,通常使用你的域名或邮箱,用于避免脚本名称冲突
- @match: 指定脚本在哪些网址上运行,支持通配符
- @grant: 声明脚本需要使用的特殊API权限
在实际开发中,我们还需要了解一些更高级的元数据标签。下面这个表格整理了常用的元数据标签及其用途:
| 标签 | 用途 | 示例 |
|---|---|---|
| @require | 引入外部JavaScript库 | @require https://code.jquery.com/jquery-3.6.0.min.js |
| @resource | 引入外部资源文件 | @resource icon http://example.com/icon.png |
| @connect | 允许跨域请求的域名 | @connect api.weibo.com |
| @run-at | 脚本执行时机 | @run-at document-end |
| @updateURL | 脚本更新地址 | @updateURL https://example.com/script.meta.js |
理解这些元数据标签是编写高质量油猴脚本的第一步。它们不仅决定了脚本的基本行为,也影响了脚本的安全性和兼容性。
1.3 开发工具与调试技巧
油猴脚本的开发不需要复杂的IDE,一个文本编辑器加上浏览器的开发者工具就足够了。但我推荐使用一些专门的工具来提高开发效率。
Visual Studio Code 是我首选的编辑器,它有很好的JavaScript支持,而且可以通过安装扩展来增强油猴脚本的开发体验。我常用的扩展包括:
- ESLint:代码质量检查
- Prettier:代码自动格式化
- UserScript Snippets:油猴脚本代码片段
在调试方面,油猴脚本管理器通常都提供了内置的调试功能。以Tampermonkey为例:
- 点击浏览器右上角的Tampermonkey图标
- 选择"管理面板"
- 找到你的脚本,点击"编辑"
- 在编辑器中修改代码后保存
- 刷新目标页面即可看到修改效果
更高级的调试可以使用浏览器的开发者工具。在控制台中,你可以直接访问脚本中定义的变量和函数,这对于调试复杂逻辑非常有帮助。
// 在脚本中添加调试输出
console.log('视频URL:', videoUrl);
console.log('按钮元素:', downloadBtn);
// 使用debugger语句设置断点
if (videoUrl) {
debugger; // 执行到这里时会暂停
startDownload(videoUrl);
}
2. 微博视频页面结构与分析
2.1 深入理解微博视频页面的DOM结构
要编写一个有效的下载脚本,我们首先需要了解微博视频页面的HTML结构。打开一个微博视频页面(比如 https://weibo.com/tv/v/视频ID),按F12打开开发者工具,让我们一起来探索一下。
微博的视频播放器通常使用HTML5的<video>标签。你可以通过以下方式找到它:
// 方法1:通过标签名查找
const videoElement = document.querySelector('video');
// 方法2:通过类名查找(微博特定的类名可能会变化)
const videoElement = document.querySelector('.weibo-video-player video');
// 方法3:通过属性查找
const videoElement = document.querySelector('[data-node="video"]');
在实际操作中,我发现最可靠的方法是结合多种选择器:
function findVideoElement() {
// 尝试多种选择器
const selectors = [
'video',
'.weibo-video-player video',
'.video-player video',
'[data-node="video"]',
'div[class*="video"] video'
];
for (const selector of selectors) {
const element = document.querySelector(selector);
if (element && element.src) {
return element;
}
}
return null;
}
微博页面的DOM结构相对复杂,而且可能会随着版本更新而变化。因此,我们的脚本需要有一定的容错能力。下面这个表格总结了我分析过的几种常见视频页面结构:
| 页面类型 | 视频元素位置 | 特征 |
|---|---|---|
| 单视频页面 | 通常只有一个video标签 | 结构简单,容易定位 |
| 信息流中的视频 | 可能有多个video标签 | 需要根据上下文判断哪个是目标视频 |
| 全屏播放模式 | video标签可能被动态创建 | 需要监听DOM变化 |
2.2 视频URL的获取策略
找到video元素只是第一步,更重要的是获取到视频的真实URL。在微博中,视频URL可能有多种形式:
- 直接MP4链接:最理想的情况,可以直接下载
- M3U8流媒体:需要特殊处理
- 加密或带参数的链接:可能需要额外的处理
让我们写一个函数来获取视频URL:
function getVideoUrl(videoElement) {
if (!videoElement) {
console.warn('未找到video元素');
return null;
}
// 尝试获取src属性
let videoUrl = videoElement.src;
// 如果src为空,尝试currentSrc
if (!videoUrl) {
videoUrl = videoElement.currentSrc;
}
// 检查是否是有效的视频URL
if (videoUrl && isVideoUrl(videoUrl)) {
return videoUrl;
}
// 如果以上方法都失败,尝试从子元素中查找
const sourceElements = videoElement.querySelectorAll('source');
for (const source of sourceElements) {
if (source.src && isVideoUrl(source.src)) {
return source.src;
}
}
return null;
}
function isVideoUrl(url) {
const videoExtensions = ['.mp4', '.webm', '.ogg', '.m3u8'];
return videoExtensions.some(ext => url.includes(e

&spm=1001.2101.3001.5002&articleId=154171998&d=1&t=3&u=ee7aae4549a046d69c9f353d188a34b2)
387

被折叠的 条评论
为什么被折叠?



