APIの仕様変更

APIデータでキーワードランキングのデータが取れなくなったと以前に記事にしました。

取得できなくなったランクデータ代替案

APIの仕様変更に伴い取得ができなくなったランキングデータの代わりとして何かないか探したところ、とある通販サイトに検索キーワードのランキングページが存在するのをたまたま見つけました。そこで、PHPでスクレイピングをできないかを試みることにしました。

スクレイピング

スクレイピングは、Webサイトから必要なデータを取得して、データをDBなどに格納して分析とかに使ってしまおうというWeb技術です。googleがクローラーでデータを取って検索エンジンを作っているのもこれの一種とはいえます。

PHPでスクレイピング

PHP スクレイピング」で調べると、某会社さんの技術系ブログでphpQueryの記事がでている影響か、phpQueryを使った説明ばかりが見つかりましたが、こちらのブログを見ると、10年以上前に開発が止まったphpQueryライブラリを使うよりも、今もバージョンアップが続けられている「PHP Simple HTML DOM Parser」を使う方が賢明だということなので、「PHP Simple HTML DOM Parser」を使ってやってみることにしました。

PHPのスクレイピングのライブラリは「PHP Simple HTML DOM Parser」がオススメ

PHPでスクレイピング。phpQueryとphp-simple-html-dom-parserの比較と設置方法 | エス技研

composerによるSimple HTML DOM Parser追加

エス技研さんの記事では、ダウンロードしてFTPを上げて設定すると書いてありましたが、twitter系APIの「cowitter」を設定したときにも使った「composer」がありますので、composerを使って設定してみました。

% php composer.phar require simplehtmldom/simplehtmldom

ところが、composerがエラーを吐いてうまくうごいてくれません。どうやら安定バージョンが見つからないと怒られているようです。

[InvalidArgumentException]
Could not find a version of package simplehtmldom/simplehtmldom matching your minimum-stability (stable).

色々調べてみると、リリースバージョン付けて叩けばインストールできるよ。という謎の海外ブログを見つけたので、その通りにやってみたらうまくいきました。

% php composer.phar require simplehtmldom/simplehtmldom:2.0-RC2
Simple HTML DOM Parserが無事入りました

Simple HTML DOM Parserの利用

ライブラリのインストールができましたので、早速使ってみます。simple_html_dom.phpというファイルがどこかに生成されているので、まずは読み込みます。

require '/simplehtmldom/simplehtmldom/simple_html_dom.php';

このsimple_html_dom.phpの中身をみてみると、HTMLファイル全体を取り込むfunction file_get_html()と、HTMLファイルから指定文字列を使って取り込むfunction str_get_html()の2つが用意されているようですが、とりあえずfunction file_get_html()を使って取り込んでみます。

$html = file_get_html($Target_URL);

すると、関数内で対象ファイルを読み込んだsimple_html_domクラスのインスタンスをnewしてくれるようなので、あとはこの$htmlを操作すれば大丈夫そうです。

<a>タグのhref属性を取りたければ、こんな感じで呼び出してあげれば、HTML内のリンクを全て集めることがができました。簡単ですね。

//a要素取得
foreach($html->find('a') as $element){
    echo $element->href;
}

スクレイピングしたデータ

結果、キーワードがエンコードされたURLを大量に取得ができましたので、エンコード文字列あたりを取り出し、これをデコードすればキーワードが取得できそうです。

https://search.***.**.jp/search/mall/%E3%83%9E%E3%82%B9%E3%82%AF/

取得できた楽天市場の商品キーワードリンク

かなり雑ですが、URLの最後尾/を取ってから/で区切り、最後尾要素だけデコードしてキーワードで配列に貯めてあげればできあがりました。

foreach($html->find('a') as $element){
    $KeyWord[] = urldecode(end(explode("/",substr($element->href, 0, -1))));
}

おわりに

とある通販サイトにはランキング形式で検索キーワードが表示されているので、この順位を元にこれまでAPIで取れていた検索スコアを自分でセットしてDBに入れてあげれば、APIで取得していたランキングデータと同じように扱うことできました。

一度は機能的に終わったサイトもこれで復活できましたので、サイト名もKeyword Tool++と変えてあらたにやり直すことにしました。APIは突然の仕様変更や終了があるから困りますね。