2012-07-17 113 views
2

我想將curl中獲得的任何網站的輸出轉換爲utf8中的數據庫插入。在bash中將stdout轉換爲utf8

使用前:

html="$(curl -iL -compressed "$link")" 

##code needed to convert nonUTF8 $html to utf8, preferably without writing to file 

## escape characters for insert 
html_q="${html//'\'/\\\\}" 
html_q="${html_q//"'"/\'}" 

## the insert statement 
sqlHtml='INSERT INTO `'"${tableHtml}"'` (`html`) VALUES ('"'${html_q}'"');' 
mysql -u$dbUser -p$dbPass -h$dbHost -P$dbPort -D$dbName --default_character_set utf8 -A <<ENDofMESSAGE 
${sqlHtml} 
ENDofMESSAGE 
+0

您如何期待確定'$ html'中數據的字符集是什麼?您不能將隨機垃圾轉換爲UTF-8,並期望結果合理,您需要知道您要轉換的字符集。 – cdhowie 2012-07-17 14:36:15

+0

可能使用捲曲頭,像http://stackoverflow.com/questions/2510868/php-convert-curl-exec-output-to-utf8 – 2012-07-17 14:38:09

+0

嗯,這是bash,而不是PHP。我不確定curl命令行客戶端能否讓您輕鬆訪問此標頭。你可能會考慮用Python寫這篇文章 - 請參閱[這個答案](http://stackoverflow.com/a/3683863/501250)瞭解可能的解決方案。 – cdhowie 2012-07-17 14:56:56

回答

6

短的問題,答案很簡單:

man iconv

現在,你有更多的一個問題:確定哪些是你的網頁的源編碼。 (提示:在谷歌中鍵入charsetdetector)

+0

可以iconv從標準輸出做到這一點?而不是從文件? – 2012-07-17 14:39:59

+1

你的意思是來自stdin?如果是的話,是的。只是管你的內容。任何| iconv -fSOURCE_ENCODING -tDEST_ENCODING' – Scharron 2012-07-17 14:43:47

0

在一般情況下,如果沒有解析器,就無法正確完成。腳本不會削減它。如果您的目標是存儲頁面,請將其視爲二進制文件,壓縮並轉換爲可打印格式。

+0

定義'parser',舉個例子。在我的問題中,我想模仿瀏覽器輸出的內容,使用該算法指定編碼並將其轉換爲utf8。 – 2012-07-18 06:57:43

+0

如果我將它存儲爲二進制文件,如果我不知道編碼,我將如何搜索它? – 2012-07-18 07:53:47

+0

理解html語法的軟件,它可以將html分隔成不同的元素本身,web瀏覽器有一個,除非您查看http內容頭和/或html的元標記,否則不知道頁面的編碼, – pizza 2012-07-18 08:14:17

0

這裏是我去了解決方案:

#!/bin/bash 

result="$({ stdout="$(curl -Lsv -compressed "$1")" ; } 2>&1; echo "--SePaRaToR--"; echo "$stdout")"; 
echo ' 
found:' 
echo "$result" | grep -o '\(charset\|encoding\)[ ]*=[ ]*["]*[a-zA-Z0-9_: -]*' 
echo ' ' 
status=1 
charset="ISO_8859-1" #set default 
# 1: HTTP Content-Type: header 
# 2: <meta> element in the page 
# 3: <xml> element in the page 
regex='.*(charset|encoding)\s*=\s*["]*([a-zA-Z0-9_: -]*)' 
if [[ "$result" =~ $regex ]] 
    then 
     charset="${BASH_REMATCH[2]}"  
     status=2 
     echo "match succes: $charset" 
    else 
     echo "match fail: $charset : ${BASH_REMATCH[2]}" 
fi 


if [[ "$charset" == *utf-8* || "$charset" == *UTF-8* ]] 
    then 
     charset='NotModified' 
    else 
    echo "iconv '$charset' to UTF-8//TRANSLIT" 
    html=$(echo "$result" | iconv -f"$charset" -t'UTF-8//TRANSLIT') 
    if [ $? -ne 0 ] 
     then 
     echo "translit failed : iconv '$charset' to UTF-8//IGNORE" 
     html=$(echo "$result" | iconv -f"$charset" -t"UTF-8//IGNORE") 
     if [ $? -ne 0 ] 
      then    
      charset="ISO_8859-1" 
      echo "ignore failed : iconv '$charset' to UTF-8//IGNORE" 
      html=$(echo "$result" | iconv -f"$charset" -t"UTF-8//IGNORE") 
      status=4 
     fi 
     status=3 
    fi 

fi 
echo "charset: '$charset' , status: '$status'" 

默認是W3C recomandation
這不是100%準確,但速度很快,99%的時間都能完成。

希望它可以幫助某人在相同的情況。
也感謝所有回答。

+0

如果頁面中沒有1,2,3,並且有數據內容即「<! - encoding = notvalid - >」,那麼iconv命令將失敗。你不想限制$結果到一個可接受的有效子集嗎? – pizza 2012-07-18 17:37:36

+0

我可以在$(iconv --list)] 然後charset =「$ {BASH_REMATCH [2]}」中添加如下內容: 'IF [「$ {BASH_REMATCH [2]}」; 否則保留默認或嘗試以前的匹配; fi' 但這會減慢過程,我需要掃描超過10萬個域名/天。 我將在後期處理中處理這些錯誤,然後用更重的算法重新掃描它們。 – 2012-07-19 08:08:35

+0

無論如何@pizza謝謝你的收穫。 – 2012-07-19 08:09:38