将unicode转换为gsm字符的算法

时间:2011-02-28 12:51:50

标签: python unicode encoding sms gsm

我需要一种算法(最好是在Python中)将任意字符串转换为仅包含GSM字母表中字符的字符串。我需要这个过滤器将字符串作为文本发送到SMS:es。如果可能,算法还应该用最接近的可编码等效替换字符。例子:

>>> gsm_convert('© all rights reserved')
[copyright sign] all rights reserved
# or
C all rights reserved
>>> gsm_convert('––– long dashes –––')
--- long dashes ---

Python有一些内置算法可以做到这一点,但这些函数也将输入字符串转换为不正确的ascii。 GSM处理ascii中没有的几个字符。

4 个答案:

答案 0 :(得分:4)

从在Perl和PHP中执行此操作,我将使用正则表达式分两步完成。

  • 首先包括正则表达式支持

    import re
    
  • 用最接近的匹配替换任何你可以使用的字符。

    我建议使用一组正则表达式,例如使用以下

    将“á”替换为“a”
    message = ur'abc\u00e9\u00e1'
    message = re.sub(ur'\u00e1','a',message)
    
  • 删除任何不在GSM字符集中的剩余字符。

    message = ur'abc\u00e9\u00e1'    
    
    message = re.sub(ur'[^\u0040\u00A3\u0024\u00A5\u00E8\u00E9\u00F9\u00EC\u00F2\u00C7\u000A\u00D8\u00F8\u000D\u00C5\u00E5\u0394\u005F\u03A6\u0393\u039B\u03A9\u03A0\u03A8\u03A3\u0398\u039E\u00C6\u00E6\u00DF\u00C9\u0020\u0021\u0022\u0023\u00A4\u0025\u0026\u0027\u0028\u0029\u002A\u002B\u002C\u002D\u002E\u002F\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037\u0038\u0039\u003A\u003B\u003C\u003D\u003E\u003F\u00A1\u0041\u0042\u0043\u0044\u0045\u0046\u0047\u0048\u0049\u004A\u004B\u004C\u004D\u004E\u004F\u0050\u0051\u0052\u0053\u0054\u0055\u0056\u0057\u0058\u0059\u005A\u00C4\u00D6\u00D1\u00DC\u00A7\u00BF\u0061\u0062\u0063\u0064\u0065\u0066\u0067\u0068\u0069\u006A\u006B\u006C\u006D\u006E\u006F\u0070\u0071\u0072\u0073\u0074\u0075\u0076\u0077\u0078\u0079\u007A\u00E4\u00F6\u00F1\u00FC\u00E0\u20AC\u005B\u005C\u005D\u005E\u007B\u007C\u007D\u007E]','',message)
    
    print message
    

在此示例中,它将打印abcé,删除不属于GSM字符集的á\u00e1)。

答案 1 :(得分:1)

听起来你需要一个编解码器。谷歌搜索出现了这个:http://demo.sahanafoundation.org/gsoc2010/amishra/gsoc/modules/pygsm/gsmcodecs/ 我不知道它是否有效,你必须自己找出来。

该代码的许可证位于http://demo.sahanafoundation.org/gsoc2010/amishra/gsoc/modules/pygsm/LICENSE

编辑:嗨,这里是pygsm的贡献者(如果有任何疑问,请在docstring测试中调用该数字)。

仅供参考 - 上面链接的Sahana代码似乎已移至:http://eden.sahanafoundation.org/browser#modules/pygsm/

此外,此Sahana代码源自https://github.com/developmentseed/slingshotSMS,源自原始的独立库https://github.com/adammck/pygsm/ ...其许可证位于https://raw.github.com/adammck/pygsm/master/LICENSE

答案 2 :(得分:0)

第一个响应中的链接看起来可能会起作用; FWIW,我使用了从this post链接的库作为做类似事情的基础。

正如您将看到的,作者已经创建了一个适合编码希腊语的编解码器,所以这只是一个起点。

你说你想将“任意”字符串转换为“最接近的等价物”;使它完全随意可能很困难,因为“最接近”可能在不同的域中具有不同的含义(例如,你如何处理Unicode雪人)?

如果你只是想处理拉丁语或拉丁语衍生的字母表,那么“任意”应该是可行的。

答案 3 :(得分:0)

这是我的C#代码(法语)

    public static bool IsGsmString(string message)
    {
        // https://messente.com/documentation/tools/sms-length-calculator
        // https://stackoverflow.com/questions/29541753/regex-only-checks-first-character-in-string-c-sharp/29541980#29541977

        //var strMap = new Regex(@"^[@£$¥èéùìòÇØøÅå_ÆæßÉ!""#%&'()*+,./\w:;<=>? ¡ÄÖÑܧ¿äöñüà^{}\[~\]|€-]*$");
        //return !strMap.IsMatch(message.Replace(Environment.NewLine, ""));   // Enlever les saut de ligne car non inclus dans le Map

        foreach (char c in message.ToCharArray())
            if (!IsGsmChar(c))
                return false;

        return true;
    }

    public static bool IsGsmChar(char c)
    {
        string strGSMTable = "@£$¥èéùìòÇ`Øø`ÅåΔ_ΦΓΛΩΠΨΣΘΞ`ÆæßÉ !\"#¤%&'()*=,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑÜ`¿abcdefghijklmnopqrstuvwxyzäöñüà";
        strGSMTable += "^{}\\[~]|€" + Environment.NewLine;   // Adding extended char and CRLF

        return strGSMTable.IndexOf(c) >= 0;
    }

    public static string ReplaceNoneGsmChar(string message)
    {
        var converted = "";

        foreach (char c in message.ToCharArray())
        {
            if (IsGsmChar(c))
                converted += c;
            else
                converted += GsmReplacement(c);
        }

        return converted;
    }

    private static string GsmReplacement(char c)
    {
        switch (c)
        {
            case 'â':
                return "a";
            case 'ê':
            case 'ë':
                return "e";
            case 'î':
            case 'ï':
                return "i";
            case 'ô':
                return "o";
            case 'û':
                return "u";
            case 'ÿ':
                return "y";

            case 'Â':
            case 'À':
                return "A";
            case 'È':
            case 'Ê':
            case 'Ë':
                return "E";
            case 'Î':
            case 'Ï':
            case 'Ì':
                return "I";
            case 'Ô':
                return "I";
            case 'Ù':
            case 'Û':
                return "U";

            case '’':
            case '`':
                return "'";

            case '«':
            case '»':
                return @"""";

            case 'µ':
                return "u";
            case '©':
                return "C";
            case 'œ':
                return "oe";

            default:
                return "_";   // non remplacable
        }
    }