2

上一个问题中,有人告诉我 Google 会将 UTF-8 编码的响应传递给查询。这解决了不间断空格 (A0) 在通过 curl 传递到我的终端后被混淆的问题。这是通过将 curl 输出传递到 inconv 并转换为 UTF-8 来解决的。然而,即使有了这个解决方案,我仍然得到一些奇怪的输出。

考虑以下 2 m 到英尺的转换:

http://www.google.com/ig/calculator?hl=en&q=2%20m%20in%20feet

这是我在浏览器和其他地方看到的输出:

{lhs: "2 meters",rhs: "6.56167979 feet (6 feet 6\x3csup\x3e47\x3c/sup\x3e\x26#8260;\x3csub\x3e64\x3c/sub\x3e inches)",error: "",icc: false}

预期的输出是:

{lhs: "2 meters",rhs: "6.56167979 feet (6 feet 6 47/64 inches)",error: "",icc: false}

我可以使用正则表达式或其他解决方案进行文本替换,但我想知道这里发生了什么。有什么见解吗?

我正在运行 Mac OS X Mountain Lion 10.8.2

4

2 回答 2

2

通过 curl 访问的 Google 计算器正在返回 JSON。Google 正在使用 \xHH 表示法,因为这是 JSON 的标准。如果输出被发送到浏览器(或任何其他解析 HTML)而不是标准输出,则只需要一个好的 JSON 解码器。

让我们看看我们可以从命令行做什么来解析 JSON。

echo -en $(curl -s 'http://www.google.com/ig/calculator?hl=en&q=4^22') > ~/temp.html

这为我们提供了可以通过浏览器查看的有效 HTML,但我们需要将所有内容简化为可以通过标准输出显示的内容。

echo -en "$(curl -s --connect-timeout 10 "http://www.google.com/ig/calculator?hl=en&q=2%20m%20in%20feet")" | sed -e 's/<sup>/ &/g' -e :a -e 's/<[^>]*>//g;/</N;//ba' | perl -MHTML::Entities -ne 'print decode_entities($_)' | iconv -f ISO-8859-1 -t UTF-8

对于 echo 命令,-e 解释转义符,例如 \x3e、\x3c 和 \x26(分别为 <、> 和 &),而 -n 抑制 echo 通常会添加的换行符。

sed 的管道在所有(上标)标记之前添加一个空格,然后删除所有 HTML 标记。

然后到 perl 的管道解码所有 HTML 实体,例如 ⁄ 到 ⁄(分数斜线)。 http://en.wikipedia.org/wiki/Html_special_characters#Character_entity_references_in_HTML

iconv 的管道将 ISO-8859-1 输出转换为预期的 UTF-8。这是最后完成的,因为 perl 行可以生成需要正确转换的 UTF-8 实体。

这仍然存在区分分数和指数的问题(47/64,其中 47 包含在上标标签中,64 包含在下标标签中,10^13 ,其中 13 包含在上标标签中)。

我们可能会变得非常愚蠢,并制作一个非常长的 sed 行来解析所有特殊字符(以下是 AppleScript 中的,因此您可以看到语法变得多么荒谬):

set jsonResponse to do shell script "curl " & queryURL & " | sed -e 's/[†]/,/g' -e 's/\\\\x26#215;/*/g' -e 's/\\\\x26#188;/ 1\\/4/g' -e 's/\\\\x26#189;/ 1\\/2/g' -e 's/\\\\x26#190;/ 3\\/4/g' -e 's/\\\\x26#8539;/ 1\\/8/g' -e 's/\\\\x26#8540;/ 3\\/8/g' -e 's/\\\\x26#8541;/ 5\\/8/g' -e 's/\\\\x26#8542;/ 7\\/8/g' -e 's/\\\\x3csup\\\\x3e\\([0-9]*\\)\\\\x3c\\/sup\\\\x3e\\\\x26#8260;\\\\x3csub\\\\x3e\\([0-9]*\\)\\\\x3c\\/sub\\\\x3e/ \\1\\/\\2/g' -e 's/\\\\x3csup\\\\x3e\\([0-9]*\\)\\\\x3c\\/sup\\\\x3e/^\\1/' -e 's/( /(/g'"

†(匕首)字符在 MacRoman 集(Macintosh 编码)中是十进制的 160。在十六进制中,这是 0xA0 或 \xA0 并以 UTF-8 编码编码为非中断空间,这是谷歌正在传递的。所以在 AppleScript 中,为了替换 UTF-8 中的非中断空格,由于 Macintosh 编码,我们必须使用 †(匕首)。

sed 行还处理几个特殊的分数符号:http: //tlt.its.psu.edu/suggestions/international/bylanguage/mathchart.html#fractions

这个故事的寓意是,在处理 JSON 时,只需使用一个好的 JSON 解析器。

一个子道德是:不要使用 AppleScript 来处理 JSON。

于 2012-10-15T18:13:07.750 回答
1

问题的公认答案Google 计算器有官方 API 吗?是负数,因此您似乎只需要尝试对其功能进行逆向工程。在这里,它似乎表示分数 47/64,因此分子 47 在<sup>标记内,分母 64 在<sub>标记内,然后<>已使用\xnn符号进行转义,nn是字符的十六进制代码。这似乎没有多大意义,因为风格上的上标和下标是没有意义的,在 HTML 标记中这样做很奇怪,并且转义标签分隔符很奇怪。然而,主要问题是,有时,<sup>可能意味着上标使表达式成为指数,因此仅删除此类信息可能会扭曲信息。

于 2012-10-12T22:33:11.417 回答