R可以读取html编码的表情符号吗?

J L*_*J L 6 xml html-encode r emoji xml2

我的问题,如下所述,是如何使用R来读取包含HTML表情符号代码的字符串��,并且(1 ) in the parsed string, or (2) convert it into its text equivalent (":hugging face:")?

背景

我有一个文本消息的XML数据集(来自Android/iOS应用程序[信号])(https://signal.org/),我正在阅读R文本挖掘项目.数据看起来像这样,每个文本消息都在sms节点中表示:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!-- File Created By Signal -->
    <smses count="1">
        <sms protocol="0" address="+15555555555" contact_name="Jane Doe" date="1483256850399" readable_date="Sat, 31 Dec 2016 23:47:30 PST" type="1" subject="null" body="Hug emoji: &#55358;&#56599;" toa="null" sc_toa="null" service_center="null" read="1" status="-1" locked="0" />
</smses>
Run Code Online (Sandbox Code Playgroud)

问题

我目前正在使用xml2R 的包读取这些数据.xml2::read_xml但是,当我使用该函数时,我收到以下错误消息:

Error in doc_parse_raw(x, encoding = encoding, base_url = base_url, as_html = as_html,  : 
  xmlParseCharRef: invalid xmlChar value 55358
Run Code Online (Sandbox Code Playgroud)

据我所知,这表明表情符号字符不被识别为有效的XML.

使用该xml2::read_html功能确实有效,但会删除表情符号字符.这方面的一个小例子是:

example_text <- "Hugging emoji: &#55358;&#56599;"
xml2::xml_text(xml2::read_html(paste0("<x>", example_text, "</x>")))
Run Code Online (Sandbox Code Playgroud)

(输出:[1] "Hugging emoji: ")

这个字符有效的HTML - 谷歌搜索&#55358;&#56599;实际上将它在搜索栏中转换为"拥抱的脸"表情符号,并显示与该表情符号相关的结果.

我发现的其他信息似乎与这个问题有关

我一直在搜索Stack Overflow,并且没有发现任何与此特定问题相关的问题.我也找不到一个直接在它们代表的表情符号旁边提供HTML代码的表格,因此在解析之前无法将这些HTML代码转换为大循环中的文本等价物(尽管效率低下)数据集; 例如,无论这份名单,也没有它的基础数据集似乎在这样的字符串55358.

ren*_*nsa 6

tl; dr:表情符号不是有效的HTML实体;已使用UTF-16数字代替Unicode代码点来构建它们。我在答案的底部描述了一种算法,将其转换为有效的XML。


找出问题

R绝对可以处理表情符号:

在此处输入图片说明

实际上,在R中存在一些用于处理表情符号的软件包。例如,emojifontemo软件包都允许您基于Slack样式的关键字检索表情符号。这只是从HTML转义格式获取源字符以便转换它们的问题。

xml2::read_xml似乎可以与其他HTML实体(例如“&”号或双引号)一起使用。我查看了这个SO答案,以查看HTML实体上是否存在任何特定于XML的约束,并且看起来它们存储的表情符号很好。所以我尝试将您表情符号中的表情符号代码更改为该答案中的表情符号代码:

body="Hug emoji: &#128512;&#128515;"
Run Code Online (Sandbox Code Playgroud)

而且,可以肯定的是,它们被保留了(尽管它们显然不再是拥抱表情符号了):

> test8 = read_html('Desktop/test.xml')
> test8 %>% xml_child() %>% xml_child() %>% xml_child() %>% xml_attr('body')
[1] "Hug emoji: \U0001f600\U0001f603"
Run Code Online (Sandbox Code Playgroud)

我在此页面上查找了拥抱表情符号,但没有 十进制HTML实体&#55358;&#56599;。看来表情符号的UTF-16十进制代码已包装在&#和中;

总之,我认为答案是您的表情符号实际上不是有效的HTML实体。如果您无法控制源,则可能需要进行一些预处理以解决这些错误。

那么,为什么浏览器会正确转换它们呢?我想知道浏览器在这些方面是否更具灵活性,并对这些代码可能是什么进行了一些猜测。我只是在推测。


将UTF-16转换为Unicode代码点

经过更多调查后,看来有效的emoji表情HTML实体使用Unicode代码点(如果为,则为十进制;如果为&#...;,则为十六进制&#x...;)。Unicode代码点不同于UTF-8或UTF-16代码。(该链接解释了很多关于如何的表情符号和其他字符编码不同,BTW!很好看的。)

因此,我们需要将源数据中使用的UTF-16代码转换为Unicode代码点。参考有关UTF-16的Wikipedia文章,我已经验证了它是如何完成的。每个Unicode代码点(我们的目标)是20位数字或5个十六进制数字。从Unicode转换为UTF-16时,您将其分成两个10位数字(中间的十六进制数字被切成两半,其中两位进入每个块),对它们进行一些数学运算并得出结果) 。

向后退,就像您想要的那样,是这样完成的:

  • 您的UTF-16十进制数字(目前位于两个单独的块中)为 55358 56599
  • 分别将这些块转换为十六进制可得出 0x0d83e 0x0dd17
  • 0xd800从第一个区块减去0xdc00第二个区块即可0x3e 0x117
  • 将它们转换为二进制,将其填充到10位并连接它们,这是 0b0000 1111 1001 0001 0111
  • 然后我们将其转换回十六进制,即 0x0f917
  • 最后,我们添加0x100000x1f917
  • 因此,我们的(十六进制)HTML实体为&#x1f917;。或者,以十进制表示&#129303

因此,要对该数据集进行预处理,您需要提取现有数字,使用上述算法,然后将结果放回去(使用1 &#...;而不是2)。


在R中显示表情符号

据我所知,在R控制台中没有打印表情符号的解决方案:它们总是以"U0001f600"(或您所拥有的)形式出现。但是,我上面描述的软件包可以在某些情况下帮助您绘制表情符号(我希望扩展ggflags以便在某些时候显示任意全彩表情符号)。他们还可以帮助您搜索表情符号以获取其代码,但是使用代码AFAIK却无法获取名称。但是,如果您已将表情符号代码提取到一列中,则可以尝试将表情符号列表从emojilib R导入R并与数据框进行联接,以获取英文名称。