5 分钟开发浏览器脚本 防止儿子沉迷动画片

101 天前
 hillerliao

最近让大模型帮忙开发了一个浏览器脚本(油猴脚本),实现控制 B 站动画片播放进度的目的。

缘起

最近儿子晚上洗澡后会闹着要看动画片才愿意上床睡觉。好说歹说,终于同意看一集就睡觉。

考虑到视力保护和观看体验,我没有选择手机,而是选择电脑播放 B 站的动画片。屏幕大,而且无需担心出现可能不适合儿童的片头广告,体验非常友好。

但动画片有长有短,太长的视频如果中途掐掉,会导致小孩愤怒和哭泣。所以只能每次拖动进度条到大概最后四分钟的位置。

但每次都要操作还是显得麻烦,而且小孩以后说不定发现我在骗他,那就不太好了。

既然是浏览器,何不借助大模型快速写个扩展脚本试试自动化操作?

借助 Claude.ai 写脚本,进度控制有严重问题

一开始我尝试用最近很火的 claude.ai ,写出来的油猴脚本能跳转到最后四分钟,但一播放就会反复回到最后四分钟位置,尝试两次修复,但给出的代码问题依旧。问句如下:

开发一个针对 bilibili 站点视频播放控制的油猴脚本,我希望在播放视频时能够自动跳转到最后四分钟的位置开始播放。

改用 kimi 重写,第一版核心功能非常完美

也许是外国人的大模型也许对 b 站的代码结构不太熟悉?那就试试到处在发推广的 kimi 吧。

我将差不多的问题发给 Kimi ,没想到包含核心功能的第一版代码顺利运行。

// ==UserScript==
// @name         Bilibili Auto Skip to Last Four Minutes
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Automatically skip to the last four minutes of a Bilibili video
// @author       Your Name
// @match        *://*.bilibili.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 等待视频元素加载
    window.addEventListener('load', function() {
        // 获取视频播放器
        var player = document.querySelector('video');
        if (player) {
            // 检查视频时长
            player.addEventListener('loadedmetadata', function() {
                var duration = player.duration;
                // 计算跳转时间点,确保不超过视频总时长
                var skipTime = Math.max(duration - 4 * 60, 0);
                // 跳转到指定时间点
                player.currentTime = skipTime;
            });
        }
    });
})();

小幅优化 兼顾小孩和大人需求

事情到此算是解决了。不过有个小问题,脚本默认针对所有视频,如果是我自己要看 B 站的长视频,就得将进度条拖回起始位置,略显麻烦。

为此,需要给脚本增加一个判断,只针对动画片自动跳转进度。 我尝试让 kimi 自己判断,它没法准确判断当前视频是否为动画片,只是提供了正确的思路,比如根据视频标签等进行判断,实际给的代码无效。

如果视频标签标注了视频属于动画片,那么通过标签来判断就比较准确。稍微看了几个视频详情页的 HTML 源代码,里面确实有视频的标签信息,动画片的话一般会带上“动画片”这个标签。

继续问 Kimi:

判断是否为动画片的规则如下,

比如读取视频详情页的源代码,https://www.bilibili.com/video/BV1nA411x7gT/?spm_id_from=333.788.recommend_more_video.3&vd_source=8b616b33732cab00e369c8f78a43bb13   找到 `[{"tag_id":26517,"tag_name":"动画短片","music_id":"","tag_type":"old_channel","jump_url":"","showDetail":false,"showReport":false,"timeOut":null},{"tag_id":42837,"tag_name":"益智","music_id":"","tag_type":"old_channel","jump_url":"","showDetail":false,"showReport":false,"timeOut":null},{"tag_id":285829,"tag_name":"早教","music_id":"","tag_type":"old_channel","jump_url":"","showDetail":false,"showReport":false,"timeOut":null},{"tag_id":17205837,"tag_name":"11 月打卡挑战 W2","music_id":"","tag_type":"old_channel","jump_url":"","showDetail":false,"showReport":false,"timeOut":null}]`

这段代码,看看 tag_name 有没有 “动画”,如果有,判定为动画片

返回的脚本为:

// ==UserScript==
// @name         Bilibili Auto Skip to Last Four Minutes for Animation
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Automatically skip to the last four minutes of a Bilibili animation video
// @author       Kimi + 廖智海
// @match        *://*.bilibili.com/video/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 等待页面加载
    window.addEventListener('load', function() {
        // 模拟发送请求获取视频标签信息
        fetch('/api/view?id=' + BV_ID).then(response => response.json()).then(data => {
            // 检查是否存在 "动画" 标签
            const isAnimation = data.tags.some(tag => tag.tag_name.includes('动画'));
            if (isAnimation) {
                // 获取视频播放器
                var player = document.querySelector('video');
                if (player) {
                    // 检查视频时长
                    player.addEventListener('loadedmetadata', function() {
                        var duration = player.duration;
                        // 计算跳转时间点,确保不超过视频总时长
                        var skipTime = Math.max(duration - 4 * 60, 0);
                        // 跳转到指定时间点
                        player.currentTime = skipTime;
                    });
                }
            }
        }).catch(error => {
            console.error('Error fetching video tags:', error);
        });
    });

    // 获取 BV 号
    function BV_ID() {
        const urlParams = new URLSearchParams(window.location.search);
        return urlParams.get('bvid');
    }
})();

过了几天,发现脚本针对有些视频不生效。重新看了下源代码,不同视频可以依据不同的条件来判断是否为动画片。问句里加了一句:

增加一个判断方法,如果 html 源代码里面有 <div class="firstchannel-tag" data-v-000c5325=""><a href="//www.bilibili.com/v/douga/" class="tag-link">动画</a></div>,div 包含一个链接文字为‘动画’或者‘动画片’的页面,则认定为动画片。

得到的代码把之前的判定方法替换了。于是又稍作说明:

我指的是这个判定方法和之前那个 tag 名称的判定方法并存。

更新代码如下:

// ==UserScript==
// @name         Bilibili Auto Skip to Last Four Minutes for Anime Videos
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Automatically skip to the last four minutes of a Bilibili video if it is tagged as an anime or contains a specific tag link
// @author       Your Name
// @match        *://*.bilibili.com/video/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 等待页面加载
    window.addEventListener('load', function() {
        // 检查 script 标签内容中是否包含"动画"标签
        var scriptTags = document.getElementsByTagName('script');
        var isAnimeByTag = false;
        for (var i = 0; i < scriptTags.length; i++) {
            var scriptContent = scriptTags[i].textContent;
            if (scriptContent.includes('"tag_name":"动画短片"') || scriptContent.includes('"tag_name":"动画"')) {
                isAnimeByTag = true;
                break;
            }
        }

        // 检查页面中是否存在特定的 div 元素
        var isAnimeByLink = document.querySelector('div.firstchannel-tag a.tag-link[href*="douga/"]').textContent === '动画' || document.querySelector('div.firstchannel-tag a.tag-link[href*="douga/"]').textContent === '动画片';

        // 如果任一条件满足,则跳转到视频的最后四分钟
        if (isAnimeByTag || isAnimeByLink) {
            var player = document.querySelector('video');
            if (player) {
                player.addEventListener('loadedmetadata', function() {
                    var duration = player.duration;
                    var skipTime = Math.max(duration - 4 * 60, 0);
                    player.currentTime = skipTime;
                });
            }
        }
    });
})();

小孩更大以后,能够识破父亲的诡计,这一招应该会失灵,不过那是以后的事情,以后再说,先解决已知问题即可,无需过度优化。

结语

有了生成式 AI ,不会前端技术,只需描述清楚自己的需求,稍微知道一点原理,就能快速获得能够运行的简单脚本,给工作和生活带来便利。

如果你有类似需求或体验,欢迎交流探讨。

4005 次点击
所在节点    分享创造
65 条回复
zdw189803631
101 天前
有点逆天
DXpro
101 天前
分裂人的孩子 🤣
vsitebon
101 天前
其实比起这个,我还是觉得海外的这个用 NFC 变现允许且限制小孩看电影的方案显得更有趣一点: https://simplyexplained.com/blog/how-i-built-an-nfc-movie-library-for-my-kids/ 。而时长是直接约定好,或者直接限制在 NFC 卡片上
sdwill
101 天前
堵不如疏。我现在都是对崽说:你想要可以,但是必须答应几个条件(比如只有 xx 分钟,时间到了就停)或者做个什么事(比如收拾玩具),要不就没有。你可以自行选择。如果是大哭大闹,那是绝对没有的,甚至还会惹我生气(生气就是一都比,哈哈哈)。

经过几次后,慢慢的就养成默契了。想看动画片或者想玩会 switch 就会好好说,时间到了,就乖乖关了机器。偶尔几次恋恋不舍超时间也无伤大雅。
joyhub2140
101 天前
哈哈,我告诉你我怎么对付这情况,小孩子熬夜看动画是吧,我周末专门陪小孩子看动画,我有手机边玩变监督,论熬夜爷们没输过谁,不准睡觉,让他看通宵,只准做这一件事,看动画,最后小孩子看腻了,想睡觉了,行,我说明晚继续,他就怕了,再也不敢熬夜看了。

玩 switch 也一样,我暑假用同样招数给他玩 switch ,最后他玩吐了。

现在对动画片和 switch 都没兴趣了,偶尔带同学过来一起玩 switch 。
victorkk
101 天前
@calmlyman #20 呃...楼主用心是肯定的,这个话题先不谈。你居然感叹的是想要有个聪明的爹...这句话有点怪怪的。
qwertty01
101 天前
好好好,不能看动画片,只能看抖音短视频了
calmlyman
101 天前
@victorkk 有什么问题呢,我爹确实教育程度很低,60 年代的人哪有什么好的教育呀
SkywalkerJi
101 天前
你自己看视频也看阉割版吗?
wildmaker
101 天前
@victorkk 我们一定看过同一本教育的书
JinBin
101 天前
30 年后,5 分钟开发呼吸机脚本,保持心跳但父亲防止苏醒
iOCZS
101 天前
写得很好,下辈子别写了
tyrantZhao
101 天前
孩子太可怜了。
SvenWong
101 天前
那些 diss 的 OP 的不知道有几个是有孩子的,我只能说理解并同情你,但不是很认同你的做法,你可以尝试,改变睡前习惯,比如看看绘本不要看电子产品,或者选择小猪佩奇、拉布拉多警长这种短小的动画片,你也没说一定要控制在 4 分钟有什么原因,这些短小的一集在 3-8 分钟,最长也不会超过 10 分钟,这样就不会突然打断。
victorkk
101 天前
@wildmaker #30 咳,做个好父母说起来容易做起来难,时常感觉自己做的还不好,有时控制不住真的会崩溃发火,太难了。
Messmer
101 天前
孩子这辈子有了
xing7673
101 天前
v 站没小孩的用户比例是真的大
op 这已经是比较好的了
小学前的小孩基本上懂不了啥
fgwmlhdkkkw
101 天前
一秒钟拔管,防止父亲沉迷地球 online 。哈哈哈
yuzuhi
101 天前
你小孩投胎到你家真是倒了大霉
qwertyzzz
101 天前
@andytao 你也就现在嘴上说说 小时候你试试?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1072157

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX