いきなりPHPなネタですが。
マッシュアップ系のサービスを作っていると、指定されたURLのページタイトルを取得したい時が頻繁にあります。そんな時、いわゆるスクレイピングしてタイトルを抜き出すんですが、近頃たくさんでまわっているスクレイピングツールやら、ライブラリやら使わなくてもページタイトルくらいは抜き出せるんで、簡単なサンプルを書いてみる。
<?php /** * ページタイトルを取得する関数 */ function getPageTitle( $url ) { $html = file_get_contents($url); //(1) $html = mb_convert_encoding($html, mb_internal_encoding(), "auto" ); //(2) if ( preg_match( "/<title>(.*?)<\/title>/i", $html, $matches) ) { //(3) return $matches[1]; } else { return false; } } ?>
(1) file_get_contents関数で指定されたURLからHTML文字列を取得
(2) mb_convert_encoding関数で内部エンコーディングに指定している文字コードに変換
(3) preg_match関数で正規表現を使ってtitleタグを抜き出す
ってな感じ。
呼び出し方は下記のような感じで。
<?php echo getPageTitle( "http://creazy.net/" ); ?>
まとめ
今回はtitleタグだけ抜けば良かったので正規表現も単純な感じだったけど、深い階層のタグなんかにアクセスするにはDOMとかXPathとかの助けを借りた方が直感的でいいですね。
でも、シンプルな正規表現ですむ場合、DOMやXPathよりも高速になったりするので色々試してみるのもいいかもしれない。
結構、便利そうですねぇ~。
でも、コンテンツサイズがデカイページとかだと、取り出しに時間がかかりそうな気もしますねw
ちなみに、C言語で似たような事をやってます。
titleタグのように単純なタグの場合は良いのですが、属性が指定されるタグなどはイロイロなパターンで指定できたりするので、パースするのは結構面倒なものがあったりします(苦笑
正規表現だとお手軽なんだけど、HTMLの場合、コメントとか、ネストとかもあったりして、それら考えられうる記法の全パターンでのエラーや脆弱性の危険といったことまで気を回すと、結局はきちんとレキサ、パーサ書いた方がシンプルで確実という結論になっちゃうんですよね~。
とはいえ最近は大抵の言語で既にライブラリあるので幸せライフですw
正直XついてないHTMLはプログラミング的観点だと文法キモすぎるw
>Qやんさん
> でも、コンテンツサイズがデカイページとかだと、取り出しに時間がかかりそうな気もしますねw
確かにそうですね。タイトルだけほしいって事は結構あるんですよねぇ。
じゃあ、ページタイトルはHTTPヘッダーにのせて、HEADで読める様にすれば!(無茶)
titleタグだから正規表現ってのはあります。
複雑な構造ではキモイコードになることうけあいですからねぇ。
>天空さん
まあ、ちゃんとパーサ使うべきでしょうね。
でも、パフォーマンスがでない事が多くて・・・。最近のはそうでもないのかなぁ。
まあ、勝手にスクレイピングしている立場からすると、文法とかとやかく言えないんですけど。
やっぱり技術力のあるサイトのマークアップはしっかりしている印象です。
せめてValidなX?HTML書いてほしいっす。
例えば一番わかりやすくてしかもありがちな例だと、
新タイトル
これだけで意図しない動作になっちゃいます。
また、これに対応するとしても、単純に修正すると
タイトル
“>
とかが通らなくなると。
これは明らかに意地悪ですがw
コントロール不可能な外部要因で誤動作の危険を内包することが判明している場合は
個人的にはよっぽどのメリットがなければ安全側のスタンス取ることにしてます。
確かに、スクリプト言語自体でかかれたライブラリだと、
ビルトインのregex系関数に比べるとパフォーマンスにはかなり響きますね…。
幸運にもネイティブコードのライブラリ(C/C++とかPHPならPECLとか)が
使える場合は大差ないんですが…。
あ、文法の件は書く側じゃなくて、htmlの文法規約自体がプログラム処理するにはフリーダム&カオスということを言いたかったw
く、しまったソースの部分タグ駄目だったw
全角で再度w
(でも変に文字が残っててMTもタグ処理微妙に抜けがあるのかな…)
例えば一番わかりやすくてしかもありがちな例だと、
<!--<title>旧タイトル</title>-->
<title>新タイトル</title>
これだけで意図しない動作になっちゃいます。
また、これに対応するとしても、単純に修正すると
<meta name=”foo” content=”<!--”>
<title>タイトル</title>
<meta name=”bar” content=”-->”>
とかが通らなくなると。
これは明らかに意地悪ですがw