如何开发一个用户脚本系列——脚本1:视频跳过广告和 VIP 视频解析

在这篇文章中,我们一起学习脚本 视频跳过广告和 VIP 视频解析 的开发。这也是本系列文章的最后一篇,希望完成这个系列的学习之后,你能够掌握编写脚本的方法。在正式开始之前,先说一下我认为开发脚本应该遵循的两个准则:

  • 功能实现。当你决定要开发一个脚本的时候,你肯定清楚你的脚本要实现什么功能,只有你的脚本实现了你所描述的功能,才会有更多的人安装使用,才会有更多的人给你好评;
  • 样式实现。什么叫样式实现?就是你在目标网站中添加的元素,要尽量与原网站的配色,样式相一致。这一项是非必须的,但我认为是非常重要的。你想想,如果原网站整体是蓝色,而你添加的按钮是红色,那该有多突兀,有多丑,虽然你的按钮确实突出了,但别人一看就是山寨,看着会很不舒服。而如果你的按钮也用它网站的颜色,这样就会跟原网站已有的元素契合,整体特别自然,做到以假乱真的效果。你的脚本让别人用的舒服,别人才更愿意给你好评。

需求分析

我们在日常闲暇时间都会看点视频娱乐一下,而现在各大视频网站都推出了会员体系,一个视频网站的年费会员往往需要 200 块左右。然而我们想看的电视剧,电影,通常都不在一个平台上,导致我们就需要开通各个网站的会员。一个网站还好,但多个网站叠加起来,这笔钱也不少。所以有没有什么方法能够不需要开通各个网站的会员就可以看想看的视频呢?网上现在有一些免费公开的接口提供这种解析服务,只需要将视频播放页面的地址作为参数传给接口,接口就能完成解析,然后播放视频。但我们每次都复制视频播放地址给接口,也会很麻烦,这时候就可以写个脚本,在这些视频网站上添加一个按钮,当用户点击按钮的时候,自动获取到当前页面的播放地址,然后传给接口解析播放。HTML 中有个 iframe 标签,可以用来在当前页面中嵌入其他网页,所以使用 iframe 标签就能够实现在原视频网站站内解析播放视频,体验很好。在某视频网站上的效果如下图:
img

功能实现

视频的解析都是解析接口实现的,脚本本身并不进行视频解析。所以解析接口是否稳定,是否有较高的成功率是很关键的。现在网上有很多解析接口,本文只提供 思古解析(用于站内解析)和 1717yun解析(用于站外解析)作为示例,同时由于视频网站很多,所以本文只选择 腾讯视频 作为运行脚本的示例。腾讯视频某一个视频的具体播放地址形式为 https://v.qq.com/x/cover/xxx,用 @match 匹配。在脚本编写过程中会用到 jQuery,使用 @require 引入 jQuery 库。站外解析需要在新 tab 页中打开链接,所以需要脚本管理器的 GM_openInTab() 函数,我们用 @grant 声明(为了兼容 Greasemonkey,我们还要声明它的函数 GM.openInTab)。

1
2
3
4
Copy// @require           https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js
// @match *://v.qq.com/x/cover/*
// @grant GM_openInTab
// @grant GM.openInTab

通过观察原网站可知,功能菜单都是在视频播放窗口下面,当鼠标放在功能按钮上面时,会显示功能面板,当鼠标移出功能按钮时,功能面板隐藏。所以我们将解析按钮加到功能菜单里面,将各个接口添加到功能面板,这样就可以选择不同的接口进行解析,同时使用原网站的样式风格。我们使用一个数组保存接口信息,这样方便遍历添加。由于安全问题,以 https 开头的视频网站内部不能使用 http 开头的接口,所以我们利用接口类型字段来标识接口是用来进行站内解析还是站外解析,如果是站内解析,它应该以 https 开头,如果接口以 http 开头,只能用来站外解析。我们希望将所有的接口以一个列表的形式呈现,所以我们把它放在一个 <ul> 标签里,然后每一个接口放在一个 <li> 标签里面。我们创建一个 <div> 标签,在里面添加一个 <iframe> 标签,用来加载解析结果的网页。在后面进行站内解析的时候,我们用这个 <div> 替换原视频网站播放窗口里面的内容。

1
2
3
4
5
6
7
8
Copyvar originalInterfaceList = [{"name":"思古解析","type":"站内","url":"https://api.bbbbbb.me/jx/?url="},
{"name":"1717yun解析","type":"站外","url":"http://www.1717yun.com/jx/ty.php?url="}];
var parseList = "<ul>";
parseInterfaceList.forEach((item,index)=>{
parseList += "<li>" + item.name + "(" + item.type + ")</li>";
});
parseList += "</ul>";
var videoPlayer = $("<div id='iframe-div' style='width:100%;height:100%;z-index:2147483647;'><iframe id='iframe-player' frameborder='0' allowfullscreen='true' width='100%' height='100%'></iframe></div>");

准备好解析接口和要替换的内容之后,我们就要去原网站添加解析按钮,并添加点击事件,在点击事件里面,替换播放窗口的内容。通过 location.href 能拿到当前页面的 url,我们使用 indexOf() 方法查看 v.qq.com 的索引值,如果索引值大于 -1 说明当前匹配的网站是腾讯视频,我们再进行处理。我们使用 jQuery 获取到功能菜单的父元素,然后创建解析按钮元素,将解析按钮添加到功能菜单父元素。给解析按钮添加鼠标移入移出操作,来显示和隐藏接口列表的功能面板。在每一个解析接口上面添加点击操作,判断被点击的 <li> 标签的接口类型,如果是站内解析,则替换播放窗口的内容,如果是站外解析,则打开一个新的页面显示解析链接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Copyif(location.href.indexOf("v.qq.com") > -1){
var action_wrap = $(".action_wrap");
var qq_jiexi = $("<div id='qq-jiexi-btn' class='action_item action_jiexi' style='position:relative;'><a class='action_title fn-qq-jiexi-text'><span>解析</span></a><div class='mod_pop_action fn-qq-jiexi' style='background-color:#fff;width:120px;left:-50px;text-align:center;line-height:25px;'>" + parseList + "</div></div>");
action_wrap.append(qq_jiexi);
document.getElementById("qq-jiexi-btn").addEventListener("mouseover",()=>{
$(".action_jiexi").toggleClass("open");
});
document.getElementById("qq-jiexi-btn").addEventListener("mouseout",()=>{
$(".action_jiexi").toggleClass("open");
});
$(".fn-qq-jiexi li").each((index,item)=>{
item.addEventListener('click',()=>{
if(parseInterfaceList[index].type == "站内"){
if(document.getElementById("iframe-player") == null){
var txp_ad_skip_text = $(".txp_ad_inner .txp_ad_skip_text");
if(txp_ad_skip_text.text() === "VIP可关闭广告"){
txp_ad_skip_text.click();
mod_player = $("#mod_player");
mod_player.empty();
mod_player.append(videoPlayer);
}else if(txp_ad_skip_text.text() === "关闭广告"){
txp_ad_skip_text.click();
}else if(vipPage === true){
var txp_btn_play = $(".txp_left_controls .txp_btn_play");
if(txp_btn_play.attr("data-status") === "pause"){
txp_btn_play.click();
}
mod_player = $("#mod_player");
mod_player.empty();
mod_player.append(videoPlayer);
}
}
innerParse(parseInterfaceList[index].url + location.href);
}else{
GMopenInTab(parseInterfaceList[index].url + location.href,false);
}
});
});
}
function innerParse(url){ // 站内解析
$("#iframe-player").attr("src",url);
}
function GMopenInTab(url,open_in_background){ //站外解析
if(typeof GM_openInTab === "function"){ // Tampermonkey 和 Violentmonkey 调用 GM_openInTab
GM_openInTab(url,open_in_background);
}else{ // Greasemonkey GM.openInTab
GM.openInTab(url,open_in_background);
}
}

至此腾讯视频的解析差不多就完成了,还有些细节和用户体验方面的东西代码里面有写,这里就不再赘述了。其他视频网站的处理和腾讯视频的原理是一样的,都是添加解析按钮,然后给解析按钮添加点击事件,进行站内或站外解析。

LLQ wechat
扫一扫上面的二维码可以关注我哦
坚持技术分享,您的支持将鼓励我继续创作!