我以前对编码一无所知,但经过几天的阅读,我想我知道发生了什么。我不完全理解表情符号的编码是如何工作的,但我偶然发现了同样的问题并解决了它。
您想将\xed��\xed�� 映射到其名称解码版本:百分。一个明智的方法可能是在线搜索字典并使用一个键(例如 Unicode)来替换它。在这种情况下,它将是U+1F4AF。
您显示的转换不是不同的编码,而是相同编码表情符号的不同表示法:
-
as.data.frame(tweet) 返回<ed><U+00A0><U+00BD><ed><U+00B2><U+00AF>。
-
iconv(tweet, from="UTF-8", to="ASCII", "byte") 返回<ed><a0><bd><ed><b2><af>。
所以直接使用 Unicode 是不可行的。另一种方法可能是使用已经以<ed>...<ed>... 方式编码表情符号的字典,就像这里的:emoji list。瞧!只有她的清单不完整,因为它来自
包含较少表情符号的字典。
快速的解决方案是简单地抓取一个更完整的字典并将<ed>...<ed>... 与其对应的英文文本翻译映射。我已经这样做了,并且发布了 here。
尽管没有其他人发布具有正确编码的列表这一事实困扰着我。事实上,我发现的大多数字典都有 UTF-8 编码,使用的不是<ed>...<ed>... 表示,而是<f0>...。事实证明,对于相同的 unicode U+1F4AF,它们都是正确的 UTF-8 编码,只是字节的读取方式不同。
长答案。推文以 UTF-16 读取,然后转换为 UTF-8,这就是转换不同的地方。当读取由字节对完成时,结果将是 UTF-8 <ed>...<ed>...,当它由四个字节的块读取时,结果将是 UTF-8 <f0>...(这是为什么?我不完全明白,但我怀疑这与您的处理器架构有关)。
因此,解决问题的一种较慢(但更有意识)的方法是刮取<f0>... 字典,将其转换为 UTF-16,成对转换回 UTF-8,您将得到两个 @ 987654337@。这两个 <ed>... 被称为 Unicode U+xxxxx 的低高代理对表示。
举个例子:
unicode <- 0x1F4Af
# Multibyte Version
intToUtf8(unicode)
# Byte-pair Version
hilo <- unicode2hilo(unicode)
intToUtf8(hilo)
返回:
[1] "\xf0\u009f\u0092�"
[1] "\xed��\xed��"
同样,使用iconv(..., 'utf-8', 'latin1', 'byte'),与以下内容相同:
[1] "<f0><9f><92><af>"
[1] "<ed><a0><bd><ed><b2><af>"
PS1.:
函数unicode2hilo是hi-lo到unicode的简单线性变换
unicode2hilo <- function(unicode){
hi = floor((unicode - 0x10000)/0x400) + 0xd800
lo = (unicode - 0x10000) + 0xdc00 - (hi-0xd800)*0x400
hilo = paste('0x', as.hexmode(c(hi,lo)), sep = '')
return(hilo)
}
hilo2unicode <- function(hi,lo){
unicode = (hi - 0xD800) * 0x400 + lo - 0xDC00 + 0x10000
unicode = paste('0x', as.hexmode(unicode), sep = '')
return(unicode)
}
PS2.:
我建议使用iconv(tweet, 'UTF-8', 'latin1', 'byte') 来保留特殊字符,例如 áäà。
PS3.:
要将表情符号替换为其英文文本、标签、哈希或任何您想将其映射到的内容,我建议在表情符号图中使用 DFS,因为有些表情符号的 unicode 是其他更简单的 unicode 的串联(即@987654347 @ 是一个男人翻车,而独立<f0><9f><a4><b8> 是人翻车,<e2><80><8d> 什么都不是,<e2><99><82> 是一个男性标志,而<ef><b8><8f> 什么都不是)虽然 man cartwheeling 和 person cartwheeling male sign 显然在语义上相关,但我更喜欢更忠实的翻译。