長めの前書き。
Webスクレイピング、藤井聡太です。(あいさつ)
「将棋なんか指したことあんの(´・_・`)」
もちろん、ニセモノです。私は藤井八段などではなく無冠の一介のサラリーマンプログラマーです。なので、将棋の天才となってウハウハ、なんて夢はあきらめて地道に稼ごうと思います「当たり前だ(´・_・`)」
稼ぐ、といえば。とあるプログラミング動画を見ておりましたらば、最近の稼げるプログラミング技術ベストスリーは1.WebAPI、2.Webスクレイピング、3.LINEチャットボット、なんだそうです。うち、LINEは好きじゃないので却下、WebAPIは今、実際の業務でやっておりますので残る**「Webスクレイピング」**につきまして今回、PHPでチャレンジしてみようと思います。稼げるプログラマーになって、コレで老後もウハウハです。
PHPQuery以外の選択肢を検討
ところで、PHPでWebスクレイピング!といってググってみるとめちゃくちゃ「PHPQuery」ってヤツばっかり出てくるんですが…(´・_・`)
しかし、アレでしょ?10年くらいアプデされてない、だっさいライブラリなんでしょ?却下だ却下。
んで代わりに押されたのが**「Simple HTML DOM Parser」**でこちらは使い方はPHPQueryライクで使いやすいんだとか。しかし↓のページ
PHPネイティブのDOMによるスクレイピング入門 - Qiita
によると内部で何回も正規表現を使って全ての要素をパースしてるので遅いんだそうです。他のライブラリとしては**「Goutte」というのもあり、こちらは内部でPHPネイティブのDOMを使っているそうなんでよさそうですが、しかし、せっかくだから(座右の銘)、先のページで提示されていた、「ライブラリ追加せずにPHPネイティブのDOMでやる」**というのを試してみることにしました。
カンタンなやつからいきます
なるべく単純でカンタンなことからやってみよう、と思いまして。そんでタイトルだけ取るとかなら、要素1コだけだから楽勝でしょ
…と思ったら「文字化け」というワナにハマりました(´・_・`)なんとか文字化けを克服したのが下のコードです。
<html>
<?php
$dom = new DOMDocument('1.0', 'UTF-8');
$html = file_get_contents("https://b.hatena.ne.jp/hobonichi1101/");
$html = mb_convert_encoding($html, "HTML-ENTITIES", 'auto');
@$dom->loadHTML($html);
$xpath = new DOMXpath($dom);
$title = $xpath->query("//title")->item(0)->nodeValue;
echo $title;
?>
</html>
サンプルをはてブにしたの失敗だったかなあ。HTMLにクセがあるんだよなあ。
複数要素をとりこむ
上のコードを改良して、対象のはてブのリンク部分を取得します。
<html>
<?php
$dom = new DOMDocument('1.0', 'UTF-8');
$html = file_get_contents("https://b.hatena.ne.jp/hobonichi1101/");
$html = mb_convert_encoding($html, "HTML-ENTITIES", 'auto');
@$dom->loadHTML($html);
$xpath = new DOMXpath($dom);
foreach ($xpath->query("//li[@class='bookmark-item js-user-bookmark-item']") as $node) {
echo '<p>';
echo '<a href="';
echo $xpath->evaluate('string(.//@href)', $node);
echo '">';
echo $xpath->evaluate('string(.//a)', $node);
echo '</a>';
echo '</p>';
}
?>
</html>
軽く説明しますと、はてなブックマークのリンク部分はリスト形式になっていまして、bookmark-item js-user-bookmark-itemというclass属性をもっております。なので$xpath->queryに
//li[@class='bookmark-item js-user-bookmark-item']
と指定してやるとその全てを取得できます。んで、取得した要素をforeachでループ回しながら、その中に含まれているA属性のテキストとhref属性(リンクurl)をそれぞれ
$xpath->evaluate('string(.//a)', $node);
$xpath->evaluate('string(.//@href)', $node);
で取得します。以上。