PHPのfile_get_contentsでSSL(TLS)エラーが出た話

2021年10月19日

テクノロジー

eyecatch 今更ながら、スクレイピングに未来を感じる、ユゲタです。 今どき、右を向いても左を向いても「DX」やら「RPA」やら、「ローコード」やらやらで、プログラミングがわからなくてもIT化したり、 人の作業をどんどんコンピュータにやらせる時代になってきましたが、 インターネットがその一役をかっている事はいうまでもないでしょう。 そして、インターネットでのAPIを現在は金融機関でしか法律で強制されていないですが、便利にWEBサイトの情報を取り込むために 「スクレイピング」の技術は必須と言ってもいいでしょう。

PHPでスクレイピング

擬似的なwebブラウザで、webサイトの情報をjavascriptで取得できるNodejs系のシステムは、サーバー環境も専用の構築をしないといけません。 もっと簡単にどんなサーバーでも取得出来るようにするために、 PHPでそのままHTMLソースコードを取得するという方法があります。 この方法は、webサイト側でjavascriptを使った、あとから読み込み処理などに対応できないため、完璧な方法ではありませんが、 GoogleのSEOを考えると、あとから読み込みのwebサイトを作るよりは、静的に近い状態の表示をするwebサイトを作ったほうが、良いでしょう。 そして、そうしたサイトであれば、PHPでの取得でほぼ問題がないと思うので、 実はいま現在、色々なサイトに対して、スクレイピング操作をするシステムを作っているんですが、PHPでの簡易スクレイピングで構築していました。 PHPでのスクレイピングは本当に簡単で、 $html = file_get_contents(%URL); とするだけで、簡単にHTMLのソースコードが取得できます。

file_get_contentsで出たSSL(TLS)エラー

そして、HTMLソースコードの中から必要な情報を取得するだけなんですが、今回file_get_contentsで次のエラーが出力されました。 PHP Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in test.php on line *** PHP Warning: file_get_contents(): Failed to enable crypto in test.php on line *** PHP Warning: file_get_contents(https://mynt.work/radio/?f=rss_radio): failed to open stream: operation failed in test.php on line *** どうやらSSL(TLS)がうまく認証されないというエラーで、原因としては、Redhat系のLinuxディストリビューションで、中間証明書というのが、古くなっていて起きる現象のようです。 かくゆう、ボクの使っているサーバーもCentOS7xだったので、原因は間違いなくコレでした。

解決方法

これを解決するには2つの方法があり、どちらをやってもいいですが、オススメは2番めの方です。 理由は後ほど説明しますね。 解決法の1つ目は、サーバーサイドの中間証明書を更新させるか、PHP.iniを更新するか、中間証明書を無効にするという方法で、 やり方はすみません、ググってください。 そしてオススメの解決方法の2つ目は、PHPのfile_get_contentsにオプション設定フラグを付ける方法で、次のように記述します。 // エラーがでた記述 $html = file_get_contents(%url); // 下記のように書き換える $options = array( "ssl" => array( "verify_peer" => false, "verify_peer_name" => false ) ); $html = file_get_contents(%url, false, stream_context_create($options)); ね、カンタンでしょ。 こっちのほうが、他のサーバーでの中間証明書エラーに対応できるので、サーバー側でいちいち証明書の設定作業をするよりも遥かに楽で現実的で汎用的です。

技術の根本的に思うこと

SSL(TLS)を無効にできて、正常に取得ができるのであれば、一体何のためのSSL(TLS)証明書なのかという疑問が頭をよぎります。 そもそも、PHP言語の側でも、このオプションがデフォルトでもいいかと思うんですが、 今後そのようにデフォルト変更されても困るので、現時点での仕様をちゃんと理解して、安定して今後使い続けたいです。 (じゃあ、ボヤくなよ、というツッコミはナシで) そして、SSL(TLS)がデフォルト仕様になってきている今現在としては、PHP以外でもこうしたSSLなどにおけるエラーが出やすいと思いますし、 今後TLSのバージョンも上がってくる事を考えると、プログラムエラーを無くすためにも、プログラミングとしてのお作法となり得るかもしれませんね。 そして、今回、開発中にこのエラーを経験させてくれた、神様、ありがとう!!! 本番で、これが起きた時のてんやわんやぶりを、想像したら、非常にありがたく感じられます。 開発中のエラーに感謝しつつ、自分をスキルアップさせてくれた、運にも感謝です。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ