我已经阅读了有关how Zalgo text works的信息,并且正在寻找了解聊天或论坛软件如何避免这种烦恼的方法。更准确地说,什么是完整的Unicode组合字符集,需要:

a)要么被剥夺,假设聊天参与者只使用不需要组合标记的语言(即,您可以用组合标记写“未婚夫”,但是如果您坚持这样做,您可能会有点Zalgo的习惯所以);或者,

b)最多减少8个连续字符(maximum encountered in actual languages)?

编辑:同时,我发现了一个完全不同的短语问题(“How to protect against... diacritics?”),该问题与该问题基本相同。我使标题更明确,因此其他人也会找到它。

最佳答案

假设您对此非常认真,并且想要一个技术解决方案,则可以执行以下操作:

  • 将输入的文本分成较小的单元(单词或句子);
  • 使用您选择的字体渲染服务器上的每个单元(具有很大的行高,并且在Zalgo“杂讯”将到达的基线下方有很多空间);
  • 训练一种机器学习算法来判断它看起来是否太“黑”和“忙”;
  • 如果算法的可信度低,则取决于人工主持人。

  • 实现起来可能很有趣,但实际上,最好直接进行第四步。

    编辑:这是Python 2.7中一个更实用的解决方案(如果说不准)。分类为“标记,无间距”的Unicode字符“标记,封闭”的似乎是用于创建Zalgo效果的主要工具。与上述想法不同,这不会尝试确定文本的“美学”,而只会删除所有此类字符。 (毋庸置疑,这会丢弃许多多种语言的文本。请继续阅读以获得更好的解决方案。)要过滤出更多字符类别,请将其添加到ZALGO_CHAR_CATEGORIES中。
    #!/usr/bin/env python
    import unicodedata
    import codecs
    
    ZALGO_CHAR_CATEGORIES = ['Mn', 'Me']
    
    with codecs.open("zalgo", 'r', 'utf-8') as infile:
        for line in infile:
            print ''.join([c for c in unicodedata.normalize('NFD', line) if unicodedata.category(c) not in ZALGO_CHAR_CATEGORIES]),
    

    输入示例:
    1
    H̡̫̤ͭ̓̓̇͗̎̀ơ̯̗͒̄̀̈ͤ̀͡w͓̲͙͋ͬ̊ͦ̂̀̚ ͎͉͖̌ͯͅͅd̳̘̿̃̔̏ͣ͂̉̕ŏ̖̙͋ͤ̊͗̓͟͜e͈͕̯̮͌ͭ̍̐̃͒s͙͔̺͇̗̱̿̊̇͞ ̸ͩͩ͑̋̀ͮͥͦ̊Z̆̊͊҉҉̠̱̦̩͕ą̟̹͈̺̹̋̅ͯĺ̡̘̹̻̩̩͋͘g̪͚͗ͬ͒o̢̖͇̬͍͇̔͋͊̓ ̢͈͂ͣ̏̿͐͂ͯ͠t̛͓̖̻̲ͤ̈ͣ͝e͋̄ͬ̽͜҉͚̭͇ͅx̌ͤ̓̂̓͐͐́͋͡ț̗̹̄̌̀ͧͩ̕͢ ̮̗̩̳̱̾w͎̭̤̄͗ͭ̃͗ͮ̐o̢̯̻̾ͣͬ̽̔̍͟r̢̪͙͍̠̀ͅǩ̵̶̗̮̮ͪ́?̙͉̥̬ͤ̌͗ͩ̕͡
    2
    H̡̫̤ͭ̓̓̇͗̎̀ơ̯̗͒̄̀̈ͤ̀͡w͓̲͙͋ͬ̊ͦ̂̀̚ ͎͉͖̌ͯͅͅd̳̘̿̃̔̏ͣ͂̉̕ŏ̖̙͋ͤ̊͗̓͟͜e͈͕̯̮͌ͭ̍̐̃͒s͙͔̺͇̗̱̿̊̇͞ ̸ͩͩ͑̋̀ͮͥͦ̊Z̆̊͊҉҉̠̱̦̩͕ą̟̹͈̺̹̋̅ͯĺ̡̘̹̻̩̩͋͘g̪͚͗ͬ͒o̢̖͇̬͍͇̔͋͊̓ ̢͈͂ͣ̏̿͐͂ͯ͠t̛͓̖̻̲ͤ̈ͣ͝e͋̄ͬ̽͜҉͚̭͇ͅx̌ͤ̓̂̓͐͐́͋͡ț̗̹̄̌̀ͧͩ̕͢ ̮̗̩̳̱̾w͎̭̤̄͗ͭ̃͗ͮ̐o̢̯̻̾ͣͬ̽̔̍͟r̢̪͙͍̠̀ͅǩ̵̶̗̮̮ͪ́?̙͉̥̬ͤ̌͗ͩ̕͡
    3
    

    输出:
    1
    How does Zalgo text work?
    2
    How does Zalgo text work?
    3
    

    最后,如果您希望检测而不是无条件删除Zalgo文本,则可以执行字符频率分析。下面的程序对输入文件的每一行执行该操作。函数is_zalgo为给定字符串的每个单词计算一个“Zalgo分数”(分数是潜在的Zalgo字符数除以字符总数)。然后查看单词分数的third quartile是否大于THRESHOLD。如果THRESHOLD等于0.5,则意味着我们正在尝试检测每四个单词中是否有一个具有超过50%的Zalgo字符。 (猜测的THRESHOLD为0.5,可能需要针对实际使用进行调整。)就 yield /编码工作而言,这种算法可能是最好的。
    #!/usr/bin/env python
    from __future__ import division
    import unicodedata
    import codecs
    import numpy
    
    ZALGO_CHAR_CATEGORIES = ['Mn', 'Me']
    THRESHOLD = 0.5
    DEBUG = True
    
    def is_zalgo(s):
        if len(s) == 0:
            return False
        word_scores = []
        for word in s.split():
            cats = [unicodedata.category(c) for c in word]
            score = sum([cats.count(banned) for banned in ZALGO_CHAR_CATEGORIES]) / len(word)
            word_scores.append(score)
        total_score = numpy.percentile(word_scores, 75)
        if DEBUG:
            print total_score
        return total_score > THRESHOLD
    
    with codecs.open("zalgo", 'r', 'utf-8') as infile:
        for line in infile:
            print is_zalgo(unicodedata.normalize('NFD', line)), "\t", line
    

    样本输出:
    0.911483990148
    True    Señor, could you or your fiancé explain, H̡̫̤ͭ̓̓̇͗̎̀ơ̯̗͒̄̀̈ͤ̀͡w͓̲͙͋ͬ̊ͦ̂̀̚ ͎͉͖̌ͯͅͅd̳̘̿̃̔̏ͣ͂̉̕ŏ̖̙͋ͤ̊͗̓͟͜e͈͕̯̮͌ͭ̍̐̃͒s͙͔̺͇̗̱̿̊̇͞ ̸ͩͩ͑̋̀ͮͥͦ̊Z̆̊͊҉҉̠̱̦̩͕ą̟̹͈̺̹̋̅ͯĺ̡̘̹̻̩̩͋͘g̪͚͗ͬ͒o̢̖͇̬͍͇̔͋͊̓ ̢͈͂ͣ̏̿͐͂ͯ͠t̛͓̖̻̲ͤ̈ͣ͝e͋̄ͬ̽͜҉͚̭͇ͅx̌ͤ̓̂̓͐͐́͋͡ț̗̹̄̌̀ͧͩ̕͢ ̮̗̩̳̱̾w͎̭̤̄͗ͭ̃͗ͮ̐o̢̯̻̾ͣͬ̽̔̍͟r̢̪͙͍̠̀ͅǩ̵̶̗̮̮ͪ́?̙͉̥̬ͤ̌͗ͩ̕͡
    
    0.333333333333
    False   Příliš žluťoučký kůň úpěl ďábelské ódy.
    

    10-02 17:12