EUC-JPエンコードと戦う
webからhtmlデータをとってHaskellで解析しようとしたのだけど、対象のhtmlがEUC-JPエンコードでなかなかうまくいかない。仕方ないので、
- wgetを使ったshellスクリプトをHaskellプログラムで吐き出す
- そのshellスクリプトをコンソールから起動して、ファイルに保存
- 同時にshellスクリプト中でiconvコマンドでUTF-8に変換
- ファイルをHaskellプログラムで開いて解析
という手順をとることにした。そんなことするくらいなら、PythonとかPerlで良いんじゃね? という気もしないではないけど、これで順調に動いていた。
ところが、新しく欲しくなったhtmlデータのURIがEUC-JPでURIエンコードされている。これに困った。ウキーとなった。
結局、URIエンコードするコマンドをHaskellで書いて、それを上記shellスクリプトのなかで呼び出すことすることにする:
module Main where import Data.ByteString.Lazy as BS (getContents, unpack) import Codec.Text.IConv import Text.Printf import Data.Char import System main = do args <- getArgs bs <- BS.getContents putStr $ f $ unpack $ convert "UTF-8" (args!!0) bs where f l = concat $ map g l g w = map toUpper $ printf "%%%02x" w
これを「ghc --make UriEscape.hs」でコンパイルしておいて、Haskellプログラムでつぎのようなshellスクリプトを吐かせる:
#!/bin/sh wget -O - http://xx.jp/xx.cgi?v=`echo ほげ | ./UriEscape EUC-JP` | iconv -f EUC-JP -t UTF-8 | sed 's/EUC-JP/UTF-8/' > foo.html wget -O - http://xx.jp/xx.cgi?v=`echo ふが | ./UriEscape EUC-JP` | iconv -f EUC-JP -t UTF-8 | sed 's/EUC-JP/UTF-8/' > bar.html
で、その後、foo.htmlとかbar.htmlとかを開いて解析。
(追記)
ちょっと改良:
- printfに「x」ではなく「X」を使えば、toUpperはいらない
- コードを整理
- echoに「-n」をつけないと改行がゴミとして混じる
module Main where import Data.ByteString.Lazy as BS (getContents, unpack) import Codec.Text.IConv import Text.Printf import System main = do args <- getArgs bs <- BS.getContents putStr $ conv (args!!0) bs conv to = concat . map (printf "%%%02X") . unpack . convert "UTF-8" to
#!/bin/sh wget -O - http://xx.jp/xx.cgi?v=`echo -n ほげ | ./UriEscape EUC-JP` | iconv -f EUC-JP -t UTF-8 | sed 's/EUC-JP/UTF-8/' > foo.html wget -O - http://xx.jp/xx.cgi?v=`echo -n ふが | ./UriEscape EUC-JP` | iconv -f EUC-JP -t UTF-8 | sed 's/EUC-JP/UTF-8/' > bar.html