2012-02-10 3 views
9

У меня возникли проблемы с обработкой экранированных символов Unicode в R, особенно тех, которые встречаются при захвате информации из API MediaWiki. Я хотел бы найти строку JSON, какКак правильно иметь дело с экранированными символами Unicode в R e.g. em emash (-)

{"query":{"categorymembers":[{"ns":0,"title":"Banach\u2013Tarski paradox"}]}} 

Какой должна быть вполне допустимо, но при чтении через fromJSON() я получаю:

snip... 
[1] "Banach\023Tarski paradox" 

Первоначально я думал, что это просто проблема с RJSONIO, но я сталкиваюсь похожи проблемы с scan() и readLines(). Я предполагаю, что мне не хватает чего-то очень элементарного.

Я не могу на самом деле дать полностью воспроизводимый пример использования только R, потому что если я посылаю «эм \ u2013dash» в файл с помощью записи() (или какой-либо эквивалентной функции) R будет автоматически конвертировать прочерк. Так вот. Создайте текстовый файл с именем test1 со следующим:

"em\u2013dash" "em–dash" " em \u2013 dash" 

Затем загрузите R (для любого пути к файлу):

> scan(file = "~/R/test1", what = "character", encoding = "UTF-8") 
Read 3 items 
[1] "em\\u2013dash" "em–dash"   " em \\u2013 dash" 
> readLines("~/R/test1", warn = FALSE, encoding = "UTF-8") 
[1] "\"em\\u2013dash\" \"em–dash\" \" em \\u2013 dash\"" 

Добавленных маскирующим, что вызывает мои проблемы с fromJSON(). Я мог бы просто удалить их, но я, вероятно, сломал бы что-то еще в этом процессе, и я думаю, что есть более легкое решение. Благодарю.

Вот информация сессии:

R version 2.14.1 (2011-12-22) 
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit) 

locale: 
[1] C/en_US.UTF-8/C/C/C/C 

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

other attached packages: 
[1] RJSONIO_0.98-0 

loaded via a namespace (and not attached): 
[1] tools_2.14.1 
+0

Если следовать примечание в '' scan' относительно allowEscapes? 'argument to'? Quotes', то _seems_ предположить, что парсер просто не поддерживает это в 'scan'. Но мне это кажется странным, поэтому я надеюсь, что ошибаюсь. – joran

+0

Да, я тоже это видел (бит из '? Quotes'). Я также получаю одинаковое чтение результата в контенте из readLines через соединение или из 'getURL()' в RCurl напрямую. –

ответ

4

Это ошибка в RJSONIO, как вы можете ясно видеть:

> RJSONIO::fromJSON('{"x":"foo\\u2013bar"}') 
      x 
"foo\023bar" 

Это прекрасно работает в rjson:

> rjson::fromJSON('{"x":"foo\\u2013bar"}') 
$x 
[1] "foo–bar" 

и для подтверждения правильности значения:

> Sys.setlocale("LC_ALL", "C") 
[1] "C/C/C/C/C/en_US.UTF-8" 
> rjson::fromJSON('{"x":"foo\\u2013bar"}') 
$x 
[1] "foo<U+2013>bar" 

В вашем анализе вас путают печатные строки и фактические строки. print цитирует его содержимое для печати - если вы хотите увидеть фактическую строку, вы можете использовать cat или charToRaw. Также scan не интерпретирует никаких экранов, поэтому вы получаете то, что вы им даете.

+0

Работает для меня, спасибо. –

9

На самом деле это не ошибка в RJSONIO. Он предназначен для ожидания строки, которая была прочитана R, и которая уже обрабатывает не-ASCII-символы. Когда вы передаете ему строку с \ u, которая не была обработана, а экранирована. На моей машине с языковым параметром en_US.UTF-8, команда

fromJSON('{"query":{"categorymembers":[{"ns":0,"title":"Banach\u2013Tarski paradox"}]}}') 

производит

$query 
$query$categorymembers 
$query$categorymembers[[1]] 
$query$categorymembers[[1]]$ns 
[1] 0 

$query$categorymembers[[1]]$title 
[1] "Banach–Tarski paradox" 

Обратите внимание, что символ с префиксом \u не \\u. Посмотрите, как он появляется в R, когда вы просто вводите эту строку.

Таким образом, проблема находится выше по течению от JSON() относительно того, почему строка содержит \ u.
Я могу добавить поддержку в RJSONIO для обработки таких необработанных строк.

+0

Спасибо за ответ, Дункан. Я вижу, что если я использую вашу строку, она действительно производит именно то, что я хочу. Я не знаю, как это сделать с содержимым, прочитанным через RCurl или readLines. Это, в основном, академическое, поскольку я перешел к rjson, и он отлично работает. –

+0

Хотелось бы узнать больше о том, как справиться с проблемой в «RJSONIO». У меня есть несколько строк с префиксом '\\ u', но не уверен, как обрабатывать их перед переходом на' fromJSON'. – daroczig

1

Я думаю, что основная проблема заключается в том, что опция libjsonJSON_UNICODE не включена в RJSONIO. Однако похоже, проблема не проявляется, когда вход UTF-8 кодированный:

library(RJSONIO) 
x = "北京填鴨们" 
identical(x, fromJSON(toJSON(x))) 
# [1] TRUE 

Проблема возникает только тогда, когда вход использует JSON экранированные символы. В этих случаях RJSONIO кажется генерировать latin1 выход, но не помечает установить кодировку правильно:

x <- fromJSON('["Z\\u00FCrich"]') 
print(x) 
# [1] "Z\xfcrich" 

nchar(x) 
#Error in nchar(x) : invalid multibyte string 1 

Для этого простого примера можно исправить, установив вручную кодировку latin1:

#Set the correct encoding 
Encoding(x) <- "latin1" 
print(x) 
#[1] "Zürich" 

Однако, это, конечно, не будет работать для символов вне latin1 набора:

#This should be: "填" 
fromJSON('["\\u586B"]') 
Смежные вопросы