hack のためのネタ帳, etc,,,

状況

HTML を scraping したかったのだが、対象箇所が1箇所だと Ruby や Python を持ち出して parse するのも面倒なので bash で済ませたいなと。
しかし sed でやるのは煩雑なので、もっと手軽な方法がないものかと「bash html parse」でググってみたところ xmllint が使えそうなことが分かった。
ところが、UTF-8 で書かれたマルチバイト文字を含む HTML を xmllint に食わせて xpath を処理させてみたところ、マルチバイトコードが上手く処理出来ず、以下のように属性値は数値文字参照(numeric character reference)に、要素の内容は一応 UTF-8 っぽいのだがおかしなコードに文字化けしてしまう。
$ read html <<<'<!DOCTYPE html><html><head><meta name="title" content="こんにちは世界"></head><body><p>こんにちは世界</p></body></html>'
$ echo $html
<!DOCTYPE html><html><head><meta name="title" content="こんにちは世界"></head><body><p>こんにちは世界</p></body></html>
$ echo "$html" | xmllint --xpath '//meta' --html -
<meta name="title" content="&#xE3;&#x81;&#x93;&#xE3;&#x82;&#x93;&#xE3;&#x81;&#xAB;&#xE3;&#x81;&#xA1;&#xE3;&#x81;&#xAF;&#xE4;&#xB8;&#x96;&#xE7;&#x95;&#x8C;"/>

$ echo こんにちは世界|xxd
00000000: e381 93e3 8293 e381 abe3 81a1 e381 afe4  ................
00000010: b896 e795 8c0a                           ......
$ echo "$html" | xmllint --xpath 'string(//p)' --html - | xxd
00000000: c3a3 c281 c293 c3a3 c282 c293 c3a3 c281  ................
00000010: c2ab c3a3 c281 c2a1 c3a3 c281 c2af c3a4  ................
00000020: c2b8 c296 c3a7 c295 c28c 0a              ...........
$ echo "$html" | xmllint --xpath 'string(//p)' --html - | nkf -g
UTF-8
ヘルプを見ると --encode ENCODING ってオプションがあったので、試しに --encoding utf-8 を与えてみたが効果が見られなかった。

解決方法

xmllint encoding」でググったところ以下のページを見つけた。
曰く、きちんと <meta charset="utf-8"/> を付けろと。
$ echo "$html" | sed -E 's@<head>@\0<meta charset="utf-8"/>@g' | xmllint --xpath '//meta' --html -
<meta charset="utf-8"/>
<meta name="title" content="こんにちは世界"/>
$ echo "$html" | sed -E 's@<head>@\0<meta charset="utf-8"/>@g' | xmllint --xpath '//meta[@name="title"]' --html -
<meta name="title" content="こんにちは世界"/>
$ echo "$html" | sed -E 's@<head>@\0<meta charset="utf-8"/>@g' | xmllint --xpath '//meta[@name="title"]/@content' --html -
 content="こんにちは世界"
$ echo "$html" | sed -E 's@<head>@\0<meta charset="utf-8"/>@g' | xmllint --xpath 'string(//meta[@name="title"]/@content)' --html -
こんにちは世界

$ echo "$html" | sed -E 's@<head>@\0<meta charset="utf-8"/>@g' | xmllint --xpath '//p' --html -
<p>こんにちは世界</p>
$ echo "$html" | sed -E 's@<head>@\0<meta charset="utf-8"/>@g' | xmllint --xpath 'string(//p)' --html -
こんにちは世界
$ echo "$html" | sed -E 's@<head>@\0<meta charset="utf-8"/>@g' | xmllint --xpath '//p/text()' --html -
こんにちは世界

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Wiki内検索

フリーエリア

管理人/副管理人のみ編集できます