Python3.4-在写入文件时移除或忽略表情符号

人气:65 发布:2023-01-03 标签: xml python unicode emoji

问题描述

我正在尝试解析一个XML文件,并将其内容写入一个纯文本文件。到目前为止,我的程序一直在运行,直到它命中一个表情符号字符,然后Python抛出以下错误:

UnicodeEncodeError: 'charmap' codec can't encode characters in position 177-181: character maps to <undefined>

我转到错误位置,在XML文件中找到以下emoji:

我的问题是如何将它们编码为Unicode,或者在写入文件时完全删除/忽略它们。

当我将print()打印到控制台时,它输出得很好,但在写入文件时抛出错误。

我搜索了Google和Here,但我得到的唯一答案是它们已经编码为Unicode。你能看到我的是字面意思吗?我不确定我说的是否正确。

我正在使用的XML文件也具有以下格式:

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<?xml-stylesheet type="text/xsl" href="sms.xsl"?>
<smses count="1">
  <sms protocol="0" address="+00000000000" date="1346772606199" type="1" subject="null" body="Lorem ipsum dolor sit amet, consectetur adipisicing elit," toa="null" sc_toa="null" service_center="+00000000000" read="1" status="-1" locked="0" date_sent="1346772343000" readable_date="Sep 4, 2012 10:30:06 AM" contact_name="John Doe" />
</smses>

推荐答案

您有两个选项:

选择可以处理Emoji代码点的编码。您已使用默认编解码器(取决于您的系统)打开要写入的文件,或者选择了不支持代码点的显式编码。

UTF编码能够很好地处理码点;我在这里选择UTF-8:

with open(filename, 'w', encoding='utf8') as outfile:
    outfile.write(yourdata)

设置错误处理模式,用替换字符、转义序列替换编解码器无法处理的代码点,或者完全忽略它们。请参见open() functionerrors参数:

错误是指定如何处理编码和解码错误的可选字符串-这不能在二进制模式下使用。有多种标准错误处理程序可用,但已注册到codecs.register_error()的任何错误处理名称也是有效的。标准名称为:

'strict'如果存在编码错误,则引发ValueError异常。默认值None具有相同的效果。 'ignore'忽略错误。请注意,忽略编码错误可能会导致数据丢失。 'replace'导致在存在格式错误的数据的位置插入替换标记(如'?')。 'surrogateescape'将把任何不正确的字节表示为Unicode专用区域中的代码点,范围从U+DC80到U+DCFF。当在写入数据时使用surrogateescape错误处理程序时,这些私有代码点将被转换回相同的字节。这对于处理未知编码的文件很有用。 'xmlcharrefreplace'仅在写入文件时支持。编码不支持的字符将替换为相应的XML字符引用&#nnn;'backslashreplace'(仅在书写时支持)将不受支持的字符替换为Python的带反斜杠的转义序列。

因此使用errors='ignore'打开文件将不会写入Emoji代码点,而不是引发错误:

with open(filename, 'w', errors='ignore') as outfile:
    outfile.write(yourdata)

演示:

>>> a_ok = 'The U+1F44C OK HAND SIGN codepoint: U0001F44C'
>>> print(a_ok)
The U+1F44C OK HAND SIGN codepoint: 
>>> a_ok.encode('utf8')
b'The U+1F44C OK HAND SIGN codepoint: xf0x9fx91x8c'
>>> a_ok.encode('cp1251', errors='ignore')
b'The U+1F44C OK HAND SIGN codepoint: '
>>> a_ok.encode('cp1251', errors='replace')
b'The U+1F44C OK HAND SIGN codepoint: ?'
>>> a_ok.encode('cp1251', errors='xmlcharrefreplace')
b'The U+1F44C OK HAND SIGN codepoint: &#128076;'
>>> a_ok.encode('cp1251', errors='backslashreplace')
b'The U+1F44C OK HAND SIGN codepoint: \U0001f44c'

请注意,'surrogateescape'选项的空间有限,实际上仅对解码未知编码的文件非常有用;它在任何情况下都无法处理Emoji。

14