如何从 R 中的 JSON 数据解析十六进制代码

How to parse hex codes from JSON data in R

我已经 JSON 从网络上以如下格式抓取:

\x22datetime\x22\x3A\x222019\x2D05\x2D12\x2017\x3A00\x3A00\x22\x7D\x5D

如果我复制并粘贴数据,它解析得很好:

\"datetime\":\"2019-05-12 17:00:00\"}]

然而,当我将数据作为文本文件导入时,或者当使用 rvest 从网络上抓取数据时,每个反斜杠都显示为双反斜杠:

\x22datetime\x22\x3A\x222019\x2D05\x2D12\x2017\x3A00\x3A00\x22\x7D\x5D

我想知道如何让 R 将十六进制代码解析为特殊字符,即它看起来像这样:

"datetime":"2019-05-12 17:00:00"}]

我认为主要问题在于抓取,因为看起来您要导入的实际上是字符串,如“\x22”,而不是编码的“:”。

但要模拟 "what would I get if I typed this input at a prompt",您可以使用 evalparse,如下所示:

input <- readLines(file) # Or similar
# Next line for testing, note both single and double quotes
input <- '"\x22datetime\x22\x3A\x222019\x2D05\x2D12\x2017\x3A00\x3A00\x22\x7D\x5D"'
result <- eval(parse(text=input))

对于文本文件中已有的数据,这是一种解决问题的方法。不过,总的来说,R 使用的反斜杠与许多其他语言略有不同:只有少数语言允许使用单个反斜杠(例如 \x##\u####\n\b , \r, \t, 也许还有其他)。文字反斜杠是双反斜杠。由于您的文本文件有一个文字反斜杠,后跟 "x" 和一些数字,R 尽职尽责地将它们作为文字字符串读入,而不是 \x## 所代表的十六进制代码。

s <- '\x22datetime\x22\x3A\x222019\x2D05\x2D12\x2017\x3A00\x3A00\x22\x7D\x5D'

这部分匹配 \x 的任何实例,但由于它是 R,我们需要 \\ 来表示文字 \ ... 奇怪,我知道。我们还捕获了以下两个十六进制数字:

gre <- gregexpr("\\x[0-9a-fA-F]{2}", s)
regm <- regmatches(s, gre)[[1]]
regm
#  [1] "\x22" "\x22" "\x3A" "\x22" "\x2D" "\x2D" "\x20" "\x3A" "\x3A" "\x22" "\x7D"
# [12] "\x5D"

有了这个 regm,我们可以使用十六进制转换和一些 raw 函数来转换为真正的 ascii 字符:

sapply(as.raw(strtoi(substr(regm, 3, 4), 16L)), rawToChar)
#  [1] "\"" "\"" ":"  "\"" "-"  "-"  " "  ":"  ":"  "\"" "}"  "]" 

函数regmatches不仅提取字符串中的特定模式,还可以替换它们。

regmatches(s, gre) <- list(sapply(as.raw(strtoi(substr(regm, 3, 4), 16L)), rawToChar))
s
# [1] "\"datetime\":\"2019-05-12 17:00:00\"}]"