如何防止Z͎̠͗ͣḁ̵͙̑l͖͙̫̉ͦ̾͊ͬg͔̤̞͓̐̓̒̽o͓̳͇̔ͥ文本?

时间:2014-03-09 00:47:20

标签: javascript unicode diacritics combining-marks zalgo

我已经阅读了how Zalgo text works,我正在寻找一个聊天或论坛软件如何防止这种烦恼。更确切地说,需要的完整的Unicode组合字符是什么:

a)要么被剥离,假设聊天参与者只使用不要求组合标记的语言(即你可以用组合标记写“未婚夫”,但你会是一个如果你坚持这样做,那就是Zalgo'ed自己);或者,

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

编辑:与此同时,我发现了一个完全不同的措辞问题(“How to protect against... diacritics?”),这与此问题基本相同。我让它的标题更明确,所以其他人也会发现它。

5 个答案:

答案 0 :(得分:15)

假设您对此非常认真并想要一个技术解决方案,您可以按照以下方式执行:

  1. 将传入的文本拆分为较小的单位(单词或句子);
  2. 使用您选择的字体渲染服务器上的每个单元(具有巨大的线高和Zalgo“噪音”所在的基线下方的大量空间);
  3. 训练机器学习算法,判断它是否太“暗”和“忙”;
  4. 如果算法的置信度低于人类主持人。
  5. 这可能很有趣,但在实践中,最好立即前往第四步。

    编辑:这是Python 2.7中更实用,更直接的解决方案。分类为“Mark,nonspacing”“Mark,enclosing”的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字符。 (0.5的THRESHOLD被猜测并且可能需要调整以用于实际使用。)这种类型的算法在支付/编码工作方面可能是最好的。

    #!/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.  
    

答案 1 :(得分:6)

制作方框overflow:hidden。它实际上并没有禁用Zalgo文本,但它可以防止它损坏其他注释。

<style>
.comment {
  /* the overflow: hidden is what prevents one comment's combining marks from affecting its siblings */
  overflow: hidden;
  /* the padding gives space for any legitimate combining marks */
  padding: 0.5em;
  /* the rest are just to visually divide the three comments */
  border: solid 1px #ccc;
  margin-top: -1px;
  margin-bottom: -1px;
}
</style>
<div class=comment>The below comment looks aweful.</div>
<div class=comment>H̡̫̤ͭ̓̓̇͗̎̀ơ̯̗͒̄̀̈ͤ̀͡w͓̲͙͋ͬ̊ͦ̂̀̚ ͎͉͖̌ͯͅͅd̳̘̿̃̔̏ͣ͂̉̕ŏ̖̙͋ͤ̊͗̓͟͜e͈͕̯̮͌ͭ̍̐̃͒s͙͔̺͇̗̱̿̊̇͞ ̸ͩͩ͑̋̀ͮͥͦ̊Z̆̊͊҉҉̠̱̦̩͕ą̟̹͈̺̹̋̅ͯĺ̡̘̹̻̩̩͋͘g̪͚͗ͬ͒o̢̖͇̬͍͇̔͋͊̓ ̢͈͂ͣ̏̿͐͂ͯ͠t̛͓̖̻̲ͤ̈ͣ͝e͋̄ͬ̽͜҉͚̭͇ͅx̌ͤ̓̂̓͐͐́͋͡ț̗̹̄̌̀ͧͩ̕͢ ̮̗̩̳̱̾w͎̭̤̄͗ͭ̃͗ͮ̐o̢̯̻̾ͣͬ̽̔̍͟r̢̪͙͍̠̀ͅǩ̵̶̗̮̮ͪ́?̙͉̥̬ͤ̌͗ͩ̕͡</div>
<div class=comment>The above comment looks aweful.</div>

Preview on JSFiddle

答案 2 :(得分:5)

之前曾问过一个相关的问题:https://stackoverflow.com/questions/5073191/how-is-zalgo-text-implemented但是在这里进行预防很有意思。

就防止这种情况而言,您可以选择以下几种策略:

  1. 完全防止变音符号的组合(并且让许多国际用户感到不安),
  2. 使用白名单或黑名单过滤掉组合字符(并减少一小部分国际用户)
  3. 防止一定数量的组合字符(以及更小百分比的用户的小便)
  4. 有一个健康的主持人社区(有所有缺点,请在此处查看您的问题)

答案 3 :(得分:2)

您可以使用Mathias Bynens的strip-combining-marks删除应用程序中的Zalgo文本。

模块 strip-combined-marks 可用于浏览器(通过Bower)和Node.js应用程序(通过npm)。

以下是如何将其与npm一起使用的示例:

var stripCombiningMarks = require("strip-combining-marks");
var zalgoText = 'U̼̥̻̮͍͖n͠i͏c̯̮o̬̝̠͉̤d͖͟e̫̟̗͟ͅ';
var stripptedText = stripCombiningMarks(zalgoText); // "Unicode"

答案 4 :(得分:1)

使用PHP和拆迁工人的心态你可以用iconv功能摆脱Zalgo。当然,这也会杀死任何其他UTF-8字符。

$unZalgoText = iconv("UTF-8", "ISO-8859-1//IGNORE", $zalgoText);