在字符串 Python 中搜索特定特殊字符时出现问题

问题描述 投票:0回答:1

我正在用 Python 开发一个不和谐的机器人,它将在黑名单上查找特定的触发词并对其进行审查。我已经让它大部分工作了,但是已经被审查的文字给它带来了问题。
我的解决方案是搜索“||” (对于那些不熟悉的人来说,将文本放在 || 组之间会将其放在不和谐的剧透标签后面),然后仅当单词不在它们之间时才运行该函数。我遇到的问题实际上是找到“||”的位置。
这是我第一次真正尝试使用 Python,而且主要是通过谷歌搜索,如果这是显而易见的事情,很抱歉 ^^'

为了清晰起见进行编辑:理想的输入输出示例是
在:“天哪,我死了”
出:“天哪,我太死了||ead||”
目前正在运行
在:“||天啊我死了||”
理想出局:“||天啊我死了||
当前无法运行并返回错误

我的第一次尝试是使用

censor_pos = [m.span() for m in re.finditer('||', mge, flags=0)]
其中“mge”是消息。这返回了字符串中的每个位置(又名“死”将返回 (0,0)(1,1)(2,2)(3,3),(4,4)) 我意识到这是因为 |是一个特殊的角色。
接下来我尝试将其更改为
censor_pos = [m.span() for m in re.finditer(re.escape('||'), mge, flags=0)]
(添加 re.escape)返回
TypeError: expected string or bytes-like object, got 'NoneType'
有趣的是,我确实尝试将 censor_pos 打印到控制台以查看发生了什么,它似乎确实获得了正确的位置,之后发生了错误。

因为我知道这可能是代码中其他地方的问题,所以这是我运行它的完整函数:

def Censor_Trigger(mge, word): #function to censor trigger words given a message and a trigger word
    
    censor_pos = [m.span() for m in re.finditer(re.escape('||'), mge, flags=0)] #finds all instances of "||" to know which parts of message are censored
    trigger_pos = [m.span() for m in re.finditer(word, mge, flags=re.IGNORECASE)] #finds all instances of a trigger word, giving positions as tuples in an array
    censored_msg = mge
    print (censor_pos)
    print (trigger_pos)
    y = 0 #variable to account for position change when censoring multiple instances of the same word
    for x in trigger_pos:
        a = 0
        is_censored = False
        for z in censor_pos:
            if  0<=a and (a+1)<(len(censor_pos)):
                if censor_pos[a][1]<=x[0]<=censor_pos[a+1][0]:
                    is_censored = True
                    return
                else:
                    is_censored = False          

            a=a+1
                
        if is_censored == False:
            censored_msg = censored_msg[:x[1]+(y*4)] + "||" + censored_msg[x[1]+(y*4):]
            censored_msg = censored_msg[:(x[0]+1+(y*4))] + "||" + censored_msg[(x[0]+1+(y*4)):]    
            y=y+1
            print(censored_msg)
        else:
            return
        
        
    return censored_msg

并且在 for 循环中调用

trigger_words = ["dead", "trigger", "example", "another"] #list of triggers
for x in trigger_words: #runs the function to censor trigger words for all words in the trigger list
                 Mess = Censor_Trigger(Mess, x)

完整的错误是

[2023-09-03 19:26:01] [ERROR   ] discord.client: Ignoring exception in on_message
Traceback (most recent call last):
  File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\client.py", line 441, in _run_event
    await coro(*args, **kwargs)
  File "C:\Users\user\Desktop\Discord Bot Fun\Test Code.py", line 17, in on_message
    Mess = Censor_Trigger(Mess, x)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\Desktop\Discord Bot Fun\Test Code.py", line 37, in Censor_Trigger
    censor_pos = [m.span() for m in re.finditer(re.escape('||'), mge, flags=0)] #finds all instances of "||" to know which parts of message are censored
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\re\__init__.py", line 223, in finditer
    return _compile(pattern, flags).finditer(string)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: expected string or bytes-like object, got 'NoneType'
python regex discord discord.py special-characters
1个回答
0
投票

您想要完成的事情只有通过来自您自己的机器人的消息才能实现。 如Message.edit文档中所述,机器人可以不能编辑其他用户的消息,并且会引发

Forbidden
异常。

按照您想要的模式进行替换的代码将如下所示:

@bot.listen()
async def on_message(message: discord.Message):
    censor_words = ["dead", "trigger", "example", "another"]

    matching_item = next((item for item in censor_words if item in message.content), None)
    if matching_item:
        ret_message = message.content.replace(matching_item, f"{matching_item[0]}||{matching_item[1:]}||")
        await message.edit(content=ret_message)
© www.soinside.com 2019 - 2024. All rights reserved.