草庐IT

利用正则表达式实现 B 站弹幕自定义屏蔽

初心不变_叶子 2023-09-30 原文

最近在 B 站看的技术视频比较多,也会偶尔看一些娱乐方面的内容。

技术视频本身关注度不高,于是我关掉了弹幕智能屏蔽,顺便吐槽一下这个屏蔽机制,其实用户的等级对弹幕是否被屏蔽还是有很大影响的。

但当我在关掉智能屏蔽的情况下打开一个娱乐视频时:

[图片上传失败...(image-f85b6a-1650531264911)]

这里为了演示我把弹幕显示范围改成了全屏,平时我只会开到四分之一屏幕,但就算这样弹幕也会被一堆重复内容堆满。

说到这里就要有人问了,弹幕屏蔽选项里有重复这一项啊,打开不就可以了?

然而重复弹幕屏蔽选项对不同长度的相同内容无效。

有一些油猴脚本可以对弹幕进行更精准的过滤操作,但它们只能在电脑网页端使用,我需要的是全平台的过滤。

所以我打算使用 B 站的自定义屏蔽规则功能解决这个问题。

在翻找设置项的时候,我无意间发现 B 站支持使用正则进行弹幕过滤。经过一番操作后,我看到的弹幕信息质量得到了很大的提升。

什么是正则表达式?

正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。

简单来说,正则表达式就是用来检索特定文本的规则

举个例子,很多网站在新用户注册的时候,使用正则表达式判断用户设置的密码是否足够安全。

正则表达式本身也是文本,其中包含一些有特定含义的符号。

例如,这是一个正则表达式:

.*

这也是一个正则表达式:

(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}

常见匹配符号

在正则表达式中,有些符号具有特定的语义。

我们先从简单的开始。

. 表示单个字符。

我们可以使用这个网站对正则表达式进行验证。打开这个网站后,输入一段正则表达式,下方匹配到的文本就会被高亮标记出来。

如果将 . 作为一条正则表达式,匹配结果如下:

[图片上传失败...(image-41313e-1650531264911)]

我们可以发现, 每一个字符都被单独匹配出来了。

? 代表其之前的规则可以重复出现一次以上,例如 .? 代表匹配出现一次以上的任意字符。

* 代表其之前的规则可以重复出现零次以上,例如 .* 代表匹配出现零次以上的任意字符。

{} 中的数字或者范围代表其之前的规则可以重复出现指定次数,以 .{3} 为例:

[图片上传失败...(image-49f735-1650531264912)]

每行文本以三个为一组被匹配出来。

如果我们将这条正则表达式更改为 .{8,10} 呢?

[图片上传失败...(image-a8383d-1650531264912)]

第二条文本由于长度为 4,不在 7-9 这一范围内,所以没有被匹配到。

第三条文本由于长度超过 10,因此只有前 10 个字符被匹配到。

{n,} 表示 n 次及以上。

这些规定了匹配规则的字符,我们叫做限定符

[] 中的字符或者范围代表只有其中的字符会被匹配到,例如 [abc] 代表只有字母 a、b 或 c 会被匹配到,而不是匹配 abc 这段字符

[a-z] 代表所有小写字母都会被匹配到。

[] 的开头加入 ^ 代表逻辑中的“非”关系,例如 [^a-z] 匹配除小写字母以外的字符。

\w 可以匹配大小写字母、数字及下划线,等价于 [A-Za-z0-9_]

这些对要匹配的内容做出规定的字符,叫做普通字符

在正则表达式的开头加入 ^,代表只匹配开头部分的字符串;加入 $,代表只匹配结尾部分的字符串。

例如 ^I.*\.$ 这条正则表达式:

[图片上传失败...(image-2062b-1650531264912)]

这条正则表达式匹配开头为 I,且以英文句点结尾的句子,因此只有“I am a writer.”被匹配到了。

了解了这些知识,我们就可以使用正则表达式对弹幕进行过滤了。

尝试过滤弹幕

首先,我们想要过滤掉任何只有“爱”字,且其出现次数超过五次的弹幕。

我们可以写出如下正则表达式:

^爱{5,}$

其匹配规则如下:

  • 后面的内容必须出现在开头
  • 匹配连续出现五次以上”爱“字的内容
  • 之后必须是结尾

将正则复制到测试工具里,写几行文本测试一下,效果符合预期:

[图片上传失败...(image-381841-1650531264912)]

之后,我们打开弹幕设置,选择”添加屏蔽词“,然后在”正则“选项卡中将我们的正则表达式粘贴进去:

[图片上传失败...(image-ef156-1650531264912)]

注意,添加正则时,需要将其用 / 包裹,否则依然会弹出添加成功的提示,但其不会在列表中出现,也不会生效,希望 B 站可以优化一下这个功能的体验。

再次打开开头的那个视频,可以发现右侧滚动弹幕上大片的”爱“字明显减少:

[图片上传失败...(image-837ecb-1650531264912)]

点击跳转到该视频的指定时点

(说右上角有一条没被屏蔽的小伙伴,认真看看,他发的是”受“)

效果不错,不如...再来个例子试试?

[图片上传失败...(image-1cf01d-1650531264912)]

注意上方弹幕的左侧,有一条弹幕是”两分钟“,中间还有一条”5分钟“。

一般来说,这些时间代表这个用户看到视频与该视频发布的时间差,用来表示对这位创作者的关注,但根据相关规则,这其实会影响大家的观看体验。

所以我们打算写一条正则表达式屏蔽这种弹幕。

我们的正则表达式是这样的:

^(\d|零|一|两|二|三|四|五|六|七|八|九|十)+(秒|分钟|小时)

匹配规则如下:

  • 后面的内容必须位于开头
  • 匹配所有阿拉伯数字和汉字数字,它们可以出现一次以上
  • 后面紧跟着”秒“、”分钟“或者”小时“

测试一下:

[图片上传失败...(image-7634f9-1650531264912)]

(这里漏掉了”两“,后面补上了)

将这条正则添加到屏蔽列表,再次打开视频:

[图片上传失败...(image-b3e64b-1650531264912)]

点击跳转到该视频的指定时点

满足屏蔽规则的弹幕消失了。

关于弹幕礼仪

作为一名技术从业者,我看的娱乐视频不算多,但我也许能提出一些建议:

  • 发弹幕的时候,先考虑一下这条弹幕对其他人有没有帮助
  • 弹幕字数尽量在 20 字以内,不然在默认设置下弹幕速度很快,无法阅读
  • 如果视频底部有字幕(指视频上的字幕,而不是作者提交的内嵌字幕),尽量不要发底部弹幕
  • 红色弹幕确实显眼,但表示赞同等不需要改颜色,这不会让你获得更多的赞
  • 对于没有字幕的歌曲,如果想要帮忙补上歌词,尽量发底部弹幕,保持颜色一致,并且避开已经有人补充的段落
  • 对于歌曲填词作品,如果想要发另一份填词,尽量在顶部发

也希望 B 站能把这些日常行为和社区信用体系关联起来,弹幕可以像视频一样选择点踩,并且根据弹幕被投票的情况对其内容进行复审。

后记

这篇文章只对正则表达式做了初步讲解,如果大家感兴趣,可以自学以下内容:

  • 匹配组(可以用来实现文本替换)
  • 贪婪匹配和非贪婪匹配
  • 不同编程语言种对正则表达式匹配的实现

正则表达式是一个强大的工具,也许在大家眼中,学习它的价值仅限于在 Word 里进行文本替换,但在专业领域,正则表达式的出场频率很高。

这些技能,可能会在之后的某个时刻为你节省大量的时间和精力,何不简单学学呢?

有关利用正则表达式实现 B 站弹幕自定义屏蔽的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  3. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  4. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  5. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  6. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  7. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  8. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  9. ruby - 如何在 Grape 中定义哈希数组? - 2

    我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>

  10. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

随机推荐