diff --git a/README.md b/README.md index d95e6b9..6fdeada 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,17 @@ * **读取弹幕本直播间有粉丝牌的粉丝弹幕** -* **设置屏蔽词(完全匹配)** +* **设置屏蔽词** * 参照b站up资深小狐狸直播时的需要设计 * 自动追赶机制:帮助你直击最新弹幕(PUSH4 发布后) * 绝对的排外政策:可调节读取所需要的牌子等级(默认1级),只要不是自己直播间的牌子多少级都不读(PUSH4 发布后) * 没有阀门制度:跳过弹幕时不看等级,一视同仁(PUSH5 发布后) - * 预设屏蔽词:符合狐宝直播需要,包含 。/ 赞 / ? 和所有个位数字(PUSH5 发布后) + * 预设屏蔽词:符合狐宝直播需要,包含 。/ 赞 和所有个位数字(PUSH5 发布后) * 当消息仅包含中英文常用符号时,拒绝加入消息队列(PUSH5发布后) - * 自动储存字符长度3以下的字符串(PUSH5发布后) + * 正则表达式匹配(PUSH7 发布后) + * 基于pyttsx3 @@ -43,9 +44,60 @@ **** **使用方法:** -* py文件 +* py文件(推荐)(需要库:bilibili-api-python、pyttsx3) * 直接运行main.py即可根据提示操作 * 由于未知bug,需要在启动后手动启动reader.py * release * 直接运行main.exe即可根据提示操作,如果reader没有自动打开,可以手动启动 + +***** +**配置说明** +* 打开main文件后,选择c.查看可以看到ban文件和settigns文件,选择即可打开文件,之后保存并关闭文件即可进一步操作 + + +* ban_words: + * 你可以在文件后面添加词或句子以达到匹配屏蔽 + * '$'(美元)符号开头的句子被认为是注释 + * '-'开头的句子被认为是匹配词(注意-后不要有空格,除非你需要空格加入匹配词) + + +* settings + * 目前包含rid和min_level选项 + * rid代表接入直播间的直播间id, minlevel表示读取弹幕所需的最小本直播间粉丝牌等级 + * 由于api问题(没有牌子的直播徽章返回值是None而不是0),所以没有专门做所有人可阅读的设置,如有需要联系作者(github或b站均可) + + +***** +**机制说明** +* 弹幕追赶机制 + * 机制保证在队列有50个以上词时,清空队列 + * 机制保证在队列有40个以上词时,每5个词只读1个词,并在保持40个以上词5次读取后清理10个词 + * 机制保证在队列有30个以上词时,每4个词只读1个词,并在保持30个以上词10次读取后清理10个词 + * 机制保证在队列有20个以上词时,每3个词只读1个词,并在保持20个以上词15次读取后清理10个词 + * 机制保证在队列有10个以上词时,每2个词只读1个词,并在保持10个以上词20次读取后清理5个词 + * 机制保证在队列有5个以上词时,每3个词只读2个词。 + + +***** +**其他说明(Q&A)** + +* Q:为什么没有做重置弹幕机制? + * A:已经有弹幕追赶机制了,不用重置也会一直保持在最新弹幕(追赶机制可以完全保证在大多数时间内在读最新弹幕) + + +* Q:我该怎么知道这些机制都正常运行了? + * A:在reader界面,每个机制的每次运行都会发送运行消息,该界面是重要的调试界面,如果你无意调试,可以无视这个界面的输出。 + + +* Q:为什么没有做界面?为什么需要打开两个窗口才能运行? + * A:很简单,因为作者不会,没学过。 + + +* Q:作者怎么连这么简单的东西都不会? + * A:因为这是计算机的活,作者是做通信的,不会很正常。 + + +* Q:我该怎么帮助狐宝或者作者? + * A:你可以访问本项目的github页面提issue或者在b站联系:吾名喵喵之翼。作者只要闲着看到就会回复你(大概会在每天的23点后) + * 仓库地址:https://github.com/MeowDWing/DanmakuReader \ No newline at end of file diff --git a/initial.py b/initial.py index 083981b..8cb0e9f 100644 --- a/initial.py +++ b/initial.py @@ -26,11 +26,15 @@ def _initial(): except FileNotFoundError: print('正在初始化屏蔽词文件') with open('ban_word.txt', mode='w', encoding='utf-8') as f: - f.write('$在该文件下写入的所有词会被屏蔽,每行只写一个词,只屏蔽完全一致的弹幕\n' - '$本文件中$(美元)符号开头的句子会被视为注释\n' - '$更改屏蔽词需要重启应用\n' + f.write('$ 在该文件下写入的所有词会被屏蔽,每行只写一个词,只屏蔽完全一致的弹幕\n' + '$ 本文件中$(美元)符号开头的句子会被视为注释\n' + '$ 更改屏蔽词需要重启应用(如果已经启动的话)' + '$ 更多操作请参看README.MD文件(可以直接以文本形式打开)\n' '。\n' '赞\n' + "$ '-'(减号)开头的会作为匹配词屏蔽。" + "$ 系统会屏蔽所有包含匹配词的弹幕,请谨慎选择\n" + '-红包\n' ) try: diff --git a/main.py b/main.py index 564a1f7..da136c0 100644 --- a/main.py +++ b/main.py @@ -1,15 +1,23 @@ import os - import iosetting as ios import liveget as lg import initial +__VERSION__ = 'v1.4-demo-PUSH7' + + def caseA(): - file_clearer('./files') - if os.path.exists('ban_word.txt'): - os.remove('ban_word.txt') - initial.initial() + + ios.print_set('执行初始化将重置所有文件,你确定要继续吗(Y/y)?', tag='WARNING', end='') + key = input("").strip().upper() + if key == 'Y': + file_clearer('./files') + if os.path.exists('ban_word.txt'): + os.remove('ban_word.txt') + initial.initial() + else: + return def file_clearer(path): @@ -48,7 +56,7 @@ def caseC(): os.system('cls') print('|*===================================================================*|\n' '|*| DANMAKU READER |*|\n' - '|*| main -> 查看 DEMO 1.3 |*|\n' + f'|*| main -> 查看 {__VERSION__} |*|\n' '|*===================================================================*|\n' '|*| |*|\n' '|*| B(b).禁读词列表 S(s).设置文件 |*|\n' @@ -77,15 +85,13 @@ def caseC(): def settings(): settings_dict = { - 'API_KEY': None, - 'SECRET_KEY': None, - 'cuid': None, 'rid': None, - 'min_level': None + 'min_level': None, } - have = set() + with open('./files/settings.txt', mode='r', encoding='utf-8') as f: lines = f.readlines() + for line in lines: line = line.strip().split('=') if line[0] in settings_dict: @@ -154,7 +160,7 @@ def main(): os.system('cls') print('|*===================================================================*|\n' '|*| DANMAKU READER |*|\n' - '|*| DEMO 1.3 |*|\n' + f'|*| {__VERSION__} |*|\n' '|*===================================================================*|\n' '|*| |*|\n' '|*| A(a).初始化 B(b).启动 C(c).查看 |*|\n' @@ -165,6 +171,12 @@ def main(): '|*===================================================================*|') ios.print_set('Tips:如果你想直接修改文件,只需在c.查看中打开对应文件并直接修改,本程序中的所有改动会在重启后生效', tag='CTRL') + ios.print_set('Tips:作者是搞机器学习的不会写QT不会搞协程,如果想帮助作者或者up,' + '欢迎来:https://github.com/MeowDWing/DanmakuReader' + ',或者b站私信:吾名喵喵之翼', + tag='CTRL') + ios.print_set('Tips:设置的内容还没做好,建议所有更改现在查看里看', + tag='CTRL') print('>>>', end='') get = input() diff --git a/project_picture/testresult.png b/project_picture/testresult.png deleted file mode 100644 index 7e07712..0000000 Binary files a/project_picture/testresult.png and /dev/null differ diff --git a/reader.py b/reader.py index 559db4d..5dfaef4 100644 --- a/reader.py +++ b/reader.py @@ -1,7 +1,9 @@ +import os import time from collections import deque import iosetting as ios import pyttsx3 +import re class Reader: @@ -18,6 +20,7 @@ def __init__(self): self.force_reset_limit = 50 self.ban_word_set = set("1234567890") + self.re_ban_str = '' self.ban_word_set_initial() self.symbol_set = set("~!@#$%^&*()_+=-`[]\\|}{;':\",./<>?~!@#¥%……&*()——+=-|}{【】、|‘’;:“”《》?,。、") ios.print_set('本项目基于bilibili_api, 如有任何需要,请联系作者,与狐宝同在\n' @@ -36,8 +39,15 @@ def ban_word_set_initial(self): for line in lines: line = line.strip() if line[0] != '$': - self.ban_word_set.add(line) + if line[0] == '-': + line = line[1:] + self.re_ban_str = self.re_ban_str + line + '|' + else: + self.ban_word_set.add(line) + + self.re_ban_str = self.re_ban_str[:-1] ios.print_set(f'屏蔽词列表{str(self.ban_word_set)}', tag='UP') + ios.print_set(f"屏蔽匹配词列表{self.re_ban_str.split('|')}", tag='UP') def reader(self): former = '' @@ -59,14 +69,18 @@ def reader(self): for line in lines: line = line.strip() - if line not in self.ban_word_set: - line_set = set(line) - if len(line_set - self.symbol_set) > 0: - self.danmaku_queue.append(line) - self.danmaku_len += 1 - ios.print_set(line+':加入了待读队列', tag='SPECIAL', head='QUEUE', special_color='#50FF50') - else: - ios.print_set(f'检测到{line}中仅包含符号,拒绝加入队列') + re_flag = re.search(self.re_ban_str, line) + if re_flag is None: + if line not in self.ban_word_set: + line_set = set(line) + if len(line_set - self.symbol_set) > 0: + self.danmaku_queue.append(line) + self.danmaku_len += 1 + ios.print_set(line+':加入了待读队列', tag='SPECIAL', head='QUEUE', special_color='#50FF50') + else: + ios.print_set(f'检测到{line}中仅包含符号,拒绝加入队列') + else: + ios.print_set(f'屏蔽{line}由于其中含有{re_flag.group()}') # 追赶机制 if self.danmaku_len > self.force_reset_limit: @@ -78,6 +92,7 @@ def reader(self): self.popleft_n(4) self.force_chasing_40 += 1 if self.force_chasing_40 > 5: + self.force_chasing_40 = 0 self.popleft_n(10) ios.print_set('强制更新机制已减少10个弹幕', tag='CTRL', head='SYSTEM', prefix='CHASING') ios.print_set('队列已大于40,自动跳过80%弹幕', tag='SYSTEM', prefix='CHASING') @@ -86,6 +101,7 @@ def reader(self): self.popleft_n(3) self.force_chasing_30 += 1 if self.force_chasing_30 > 10: + self.force_chasing_30 = 0 self.popleft_n(10) ios.print_set('强制更新机制已减少10个弹幕', tag='CTRL', head='SYSTEM', prefix='CHASING') ios.print_set('队列已大于30,自动跳过75%弹幕', tag='SYSTEM', prefix='CHASING') @@ -94,6 +110,7 @@ def reader(self): self.popleft_n(2) self.force_chasing_20 += 1 if self.force_chasing_20 > 15: + self.force_chasing_20 = 0 self.popleft_n(10) ios.print_set('强制更新机制已减少10个弹幕', tag='CTRL', head='SYSTEM', prefix='CHASING') ios.print_set('队列已大于20,自动跳过66%弹幕', tag='SYSTEM', prefix='CHASING') @@ -102,13 +119,14 @@ def reader(self): self.popleft_n(1) self.force_chasing_10 += 1 if self.force_chasing_10 > 20: + self.force_chasing_10 = 0 self.popleft_n(5) ios.print_set('强制更新机制已减少5个弹幕', tag='CTRL', head='SYSTEM', prefix='CHASING') ios.print_set('队列已大于10,自动跳过50%弹幕', tag='SYSTEM', prefix='CHASING') elif self.danmaku_len > 5 and self.tmp % 3 == 0: self.tmp = 0 self.popleft_n(1) - ios.print_set('队列已大于10,自动跳过33%弹幕', tag='SYSTEM', prefix='CHASING') + ios.print_set('队列已大于5,自动跳过33%弹幕', tag='SYSTEM', prefix='CHASING') # 处理与读取机制 if self.danmaku_len != 0: @@ -121,7 +139,6 @@ def reader(self): self.danmaku_len -= 1 former = now - else: time.sleep(3) @@ -140,7 +157,7 @@ class TxtProcess: def __init__(self): self.say_engin = pyttsx3.init() self.say_engin.setProperty('rate', 250) - self.say_engin.setProperty('volume', 0.6) + self.say_engin.setProperty('volume', 1) voices = self.say_engin.getProperty('voices') self.say_engin.setProperty('voice', voices[0].id) @@ -151,6 +168,7 @@ def txt2audio(self, message: str): def main(): + os.system('cls') read = Reader() read.reader()