【PHPでWebスクレイピング入門】PHPからプロキシ経由でInstagramデータを入手する
今回やりたい事として、PHPを使って対象となるInstagramのJSONデータをプロキシサーバーを経由して入手してみたいと思います。
ご存知の通り、Instagramはスクレイピングなどに対して非常に厳しい制限を設けており、少しでも連続したアクセスなどを行うと自分のIPアドレスが一定の期間利用不可能になってしまいます。この制限で、多くのプログラマが頭を悩ませている部分かと思います。
今回の狙いとして、PHPを別途入手するプロキシサーバーを経由し、複数のIPアドレスを切り分けて使う事で、連続してInstagramのデータを入手したいと思います。
注意事項: Instagramはスクレイピングなどを利用規約にて禁止しており、今回の記事ではPythonのお題として取り上げております。これらを利用して運用する事は、利用規約に抵触する可能性が高いので、あくまで自己責任の範囲で行ってください。
まずは環境の準備
今回は特別なAPIなどを使わず、PHPが標準で持っている関数などを使ってJSONデータを入手してみます。
PHPでは、下記のライブラリ「Instagram-API」がとても有名ですが、どうもDMCAに違反していると言う事で、取り下げられてしまっています。(2020年1月30日現在)
https://github.com/mgp25/Instagram-API
1. InstagramページからJSONデータを入手する - 通常の場合
Instagramのページ構造として、ユーザーや投稿などに関する情報がJavaScript内にJSON形式で埋め込まれているので、こちらはそのJSONデータを取り出す関数モジュールになります。
function get_json_data($url) {
$dom = new DOMDocument;
@$dom->loadHTML(file_get_contents($url));
$xpath = new DOMXPath($dom);
$js = $xpath->query('//body/script[@type="text/javascript"]')->item(0)->nodeValue;
$json = substr($js, strpos($js, '{'), strrpos($js, ';') - strpos($js, '{'));
$data = json_decode($json, true);
return $data;
}
2. InstagramページからJSONデータを入手する - プロキシ経由の場合
2.0プロキシサーバーでテストをする
まず最初にプロキシサーバーを入手します。ネットで検索すると、無料で使えるものや有料のものなど、沢山出てくると思います。今回オススメするのは、Blazing SEOが提供するBlazing Proxiesです。こちらは有料タイプですが、安価で専用のIPアドレスがもらえる事、またロケーションを自由に選べる事が特徴です。申し込みの方法など、詳しくはこちらの記事をご覧ください。
今回テストで使用するコードはこちらです。
$url = "https://expressvpn.com/what-is-my-ip";
$dom = new DOMDocument;
@$dom->loadHTML(file_get_contents($url));
$xpath = new DOMXPath($dom);
#var_dump($xpath);
$js = $xpath->query("//p[@class='ip-address']");
foreach ($js as $node)
{
print("IP Address without Proxy: ".$node->nodeValue."<br>");
#var_dump($x_path->query(".//nodeValue", $node));
}
まずはプロキシなしでPHPを実行してみます。
IP Address without Proxy: 自分のマシンのパブリックIPアドレス
ここで表示されるのが、現在自分のマシン上のパブリックIPとなります。
次は下記のプロキシありのスクリプトでPHPを実行してみます。まず、下記のラインを先ほど購入したプロキシサーバー情報に置き換えてください。
$PROXY_HOST = "アサインされたプロキシのIPアドレス";
$PROXY_PORT = "ポート番号";
$PROXY_USER = "ユーザー名";
$PROXY_PASS = "パスワード";
$auth = base64_encode("$PROXY_USER:$PROXY_PASS");
stream_context_set_default(
array(
'http' => array(
'proxy' => "tcp://$PROXY_HOST:$PROXY_PORT",
'request_fulluri' => true,
'header' => "Proxy-Authorization: Basic $auth"
)
)
);
$dom = new DOMDocument;
@$dom->loadHTML(file_get_contents($url));
$xpath = new DOMXPath($dom);
#var_dump($xpath);
$js = $xpath->query("//p[@class='ip-address']");
foreach ($js as $node)
{
print("IP Address with Proxy: ".$node->nodeValue."<br>");
#var_dump($x_path->query(".//nodeValue", $node));
}
そうすると、結果は先ほどの自分のIPアドレスとは異なる、購入したプロキシサーバーのIPアドレスに切り替わっているはずです。
IP Address with Proxy: アサインされたプロキシのIPアドレス
このテストで、PHPをプロキシサーバー経由でアクセスできる事が確認できました!
2.3 プロキシを経由してInstagramのJSONデータを取得する
冒頭にあったスクリプトに、今回のプロキシサーバーを適用した部分を実際に当てはめてみます。
function get_json_data($url) {
$PROXY_HOST = "アサインされたプロキシのIPアドレス";
$PROXY_PORT = "ポート番号";
$PROXY_USER = "ユーザー名";
$PROXY_PASS = "パスワード";
$auth = base64_encode("$PROXY_USER:$PROXY_PASS");
stream_context_set_default(
array(
'http' => array(
'proxy' => "tcp://$PROXY_HOST:$PROXY_PORT",
'request_fulluri' => true,
'header' => "Proxy-Authorization: Basic $auth"
)
)
);
$dom = new DOMDocument;
@$dom->loadHTML(file_get_contents($url));
$xpath = new DOMXPath($dom);
$js = $xpath->query('//body/script[@type="text/javascript"]')->item(0)->nodeValue;
$json = substr($js, strpos($js, '{'), strrpos($js, ';') - strpos($js, '{'));
$data = json_decode($json, true);
return $data;
}
これで、PHPを使い、プロキシサーバー経由でInstagramへ無事にアクセスできる様になりました。