2012-10-12 19 views
2

previous question中,我被告知Google將UTF-8編碼響應傳遞給查詢。這樣解決了一個問題,就是無間隙空間(A0)在被捲曲傳遞到我的終端後會混亂。這是通過將curl輸出管道輸入到inconv並轉換爲UTF-8來解決的。然而,即使有了這個解決方案,我仍然得到一些奇怪的輸出。谷歌計算器中的特殊字符

考慮2米至英尺以下的轉換:

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山獅10.8.2

回答

2

谷歌計算器通過curl訪問正在返回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隨聲附和將換行通常添加。

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編碼編碼到非破壞空間,這正是Google所傳遞的。因此,在AppleScript中,爲了從UTF-8中取代Non-Breaking Space,我們必須使用Macintosh編碼的†(匕首)。

也有sed的符合涉及幾個特殊分數符號: http://tlt.its.psu.edu/suggestions/international/bylanguage/mathchart.html#fractions

這個故事的寓意是處理時使用JSON,只需使用一個好的JSON解析器。

一個子道德是:不要使用AppleScript來處理JSON。

+0

優秀的答案,謝謝。我正在努力解決同樣的問題,但在Java中。你有關於如何處理'\ xnn'字符的建議嗎? – Alp

+0

@Alp你是否在某個地方開始一個問題?我需要更多的細節來了解你的問題並提供幫助。 – spex

+0

感謝您的關注。我問了一個問題,它已經開始工作了:http://stackoverflow.com/questions/15518340/json-returned-by-google-maps-query-contains-encoded-characters-like-x26-how-to – Alp

1

接受的答案質疑Is there an official API for Google calculator?是負的,所以它似乎是你必須要嘗試反向工程它的功能。這裏它似乎代表47/64分數,因此分子47位於<sup>標記內,分母64位於<sub>標記內,然後<>已使用\xnn表示法進行轉義,其中nn是字符的十六進制代碼。這似乎沒有多大意義,因爲風格的上標籤和下標是沒有意義的,在HTML標記中這樣做很奇怪,並且轉義標籤分隔符很奇怪。然而,主要的問題在於,有時<sup>可能意味着上標將表達式指定爲指數,所以只是刪除這些信息可能會扭曲信息。

+0

我從來沒有問過Google計算器是否有官方API。我的問題完全是關於逆向工程。 – spex

+0

我已經回答了我自己的問題。 – spex