想生成一个vcf时遇到了从字符串到 Quoted Printable编码转换的问题
1. 从手机里导出的vcf是这样的格式:
BEGIN:VCARD
VERSION:2.1
N;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:;=E5=B7=A5=E4=BC=9A=E7=9B=9F=E7=BB=8F=E6=B5=8E;;;
FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=B7=A5=E4=BC=9A=E7=9B=9F=E7=BB=8F=E6=B5=8E
TEL;CELL:3000000100
END:VCARD
BEGIN:VCARD
VERSION:2.1
N;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:;=E5=B7=A5=E4=BC=9A=E9=98=BF=E6=97=97=E5=B8=B8;;;
FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=B7=A5=E4=BC=9A=E9=98=BF=E6=97=97=E5=B8=B8
TEL;CELL:3000000101
END:VCARD
2. 百度了一下, QUOTED-PRINTABLE是邮件常用的编码方式, python中有一个对应的模块 quopri
反编译:
In[189]: quopri.decodestring('=E5=B7=A5=E4=BC=9A=E7=9B=9F=E7=BB=8F=E6=B5=8E').decode('utf-8')
Out[189]: '工会盟经济'
编译:
In[191]: quopri.encodestring('工会盟经济'.encode())
Out[191]: b'=E5=B7=A5=E4=BC=9A=E7=9B=9F=E7=BB=8F=E6=B5=8E'
3. 然而, 进一步发现英文字符的处理有问题
In[192]: quopri.encodestring('Hello'.encode())
Out[192]: b'Hello'
这显然是不合理的
==> 百度到了这样的方法: bytes(engCharacter, encoding='unicode_escape').hex() 验证一下:
In[194]: bytes('Hello ', encoding='unicode_escape').hex()
Out[194]: '48656c6c6f20'
In[195]: quopri.decodestring('=48=65=6C=6C=6F=20=E5=B7=A5=E4=BC=9A=E7=9B=9F=E7=BB=8F=E6=B5=8E').decode('utf-8')
Out[195]: 'Hello 工会盟经济'
4. 看起来问题变得很简单了: 给我一段文本, 我拆分出中文的部分, 英文的部分, 以不同的方法编译再拼接就可以了
例如: 'Hello 工会盟经济', ''工会盟经济Hello '', 'He工会盟经济llo '
a) 先判断是否有非中文字符: '\u4e00' <= i <= '\u9fa5' :
没有的话, 直接使用2里的 encodestring函数
有的话, 中文部分使用quopri.encodestring; 英文使用 bytes(str, encoding='unicode_escape').hex(); 然后再拼接就可以了
拆分很简单, engPartNameList = re.findall('[a-zA-Z]+',originalName) 即可提取出对应的英文字符串
但是拼接很麻烦, 需要把engPartNameList 里的每个元素与originalName对应起来, 注意前后顺序; 而且还有一个风险, 很多字符集, 例如 空格, 中行线, 等
我在a这个牛角尖里想了一天, 终于想到了简单的方法b:
b) 将originalName里每个字符做了判断, 非中文字符, 就使用bytes函数, 中文字符, 就使用quopri.encodestring函数, 然后拼接即可
代码如下:
def engNameToQuoPriStr(engCharacter): #非中文字符编码 quotedPrintableName = '=' + bytes(engCharacter, encoding='unicode_escape').hex().upper() return quotedPrintableName def chinNameToQuoPriStr(chinCharacter): #非中文字符编码 byteName = quopri.encodestring(chinCharacter.encode()) quotedPrintableName = str(byteName)[2:-1] return quotedPrintableName def UtfNameToQuoPriStr(realName): quotedPrintableName = '' for i in realName: if '\u4e00' <= i <= '\u9fa5': quotedPrintableName += chinNameToQuoPriStr(i) else: quotedPrintableName += engNameToQuoPriStr(i) return quotedPrintableName
事后验证, 即使包含表情符也是正确的, 哈