在R中读取含有多种字符编码的文件

14

我试图从大部分使用UTF-8编码(并声明<meta charset="utf-8">)的HTML页面中读取表格到R中,但其中一些字符串使用其他编码方式(我认为是Windows-1252或ISO 8859-1)。这里有一个例子。我想将所有内容正确解码到R数据框中。 XML :: readHTMLTable 需要一个 encoding 参数,但似乎不允许尝试多个编码方式。

那么,在R中,我如何尝试每行输入文件的几种编码方式?在Python 3中,我会这样做:

with open('file', 'rb') as o:
    for line in o:
        try:
            line = line.decode('UTF-8')
        except UnicodeDecodeError:
            line = line.decode('Windows-1252')

3
这个问题目前正在 Meta 讨论中:https://meta.stackoverflow.com/questions/385841/why-was-my-answer-to-my-own-question-deleted?cb=1 (注:Meta 是 Stack Overflow 上的一个讨论区,用户可以在那里讨论各种与网站有关的问题。) - Lauren Rutledge
1个回答

5

似乎有一些R库函数可以猜测字符编码,例如stringi::stri_enc_detect,但如果可能的话,最好使用简单的确定性方法按顺序尝试固定集合的编码方式。看起来最好的方法是利用iconv在转换字符串时无法转换时返回NA的事实。

linewise.decode = function(path)
    sapply(readLines(path), USE.NAMES = F, function(line) {
        if (validUTF8(line))
            return(line)
        l2 = iconv(line, "Windows-1252", "UTF-8")
        if (!is.na(l2))
            return(l2)
        l2 = iconv(line, "Shift-JIS", "UTF-8")
        if (!is.na(l2))
            return(l2)
        stop("Encoding not detected")
    })

如果您创建了一个测试文件,其中包含

$ python3 -c 'with open("inptest", "wb") as o: o.write(b"This line is ASCII\n" + "This line is UTF-8: I like π\n".encode("UTF-8") + "This line is Windows-1252: Müller\n".encode("Windows-1252") + "This line is Shift-JIS: ハローワールド\n".encode("Shift-JIS"))'

然后linewise.decode("inptest")确实返回

[1] "This line is ASCII"                    
[2] "This line is UTF-8: I like π"          
[3] "This line is Windows-1252: Müller"     
[4] "This line is Shift-JIS: ハローワールド"

要使用linewise.decodeXML::readHTMLTable一起,只需像这样说:XML::readHTMLTable(linewise.decode("http://example.com"))

难道不应该是这样吗 iconv(lines, from = "UTF-8", to = "Windows-1252") - Tonio Liebrand
@BigDataScientist 不,我希望最终所有内容都是UTF-8编码(因为事实证明R没有像Python 3的“str”那样没有二进制表示的字符串类型),而Windows-1252是我想要更改的某些行的现有编码。 - Kodiologist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接