• 一般社団法人Pythonエンジニア育成推進協会 顧問理事 寺田学氏

    著者:寺田学
    一般社団法人Pythonエンジニア育成推進協会 顧問理事

一般社団法人Pythonエンジニア育成推進協会(以下、当協会)の顧問理事の寺田学です。私は試験の問題策定とコミュニティ連携を行う立場です。Web上の情報から様々なデータを取得して何かしたいと思うのは、データ分析に関わる人だけではありません。インターネット上にある情報をプログラミングによって手元に持ってこられるようになれば、自分の趣味や仕事に役立つ便利なツールを作れるようになります。Webからデータを持ってくる方法にはいろいろありますが、よく利用されるのはスクレイピングで、これはPythonでも行うことができます。そこで今回はPythonを使ったスクレイピングについてお話しします。

Webからデータを集めるにはまずWebの仕組みを知ろう

Webからデータを持ってくるには、まずWebブラウザとWebの仕組みについて考える必要があります。WebページはHTMLで書かれており、その中にはいろいろな記述があります。たとえば、HTMLでリンクを書くには【<a href=”(URL)”>(ブラウザに表示する文字)</a>】と書きます。ユーザーはブラウザに表示されたリンクをクリックすることでリンク先に遷移できますし、ブラウザの戻るボタンを押せば前の画面に戻ることができます。リンクをクリックしたとき、ブラウザは裏側で、そのURLがどこのサーバにあるのかを調べて対象のサーバにアクセスし、相手先のサーバからHTMLやWebのデザインが書かれたCSS、動作が書かれたJavaScript、画像などの関連するデータを取得し、HTMLの記述に基づいてレンダリングしてブラウザに表示させるという動作をしています。ブラウザ自体は高機能なので、これも含めてPythonでやろうとすれば難しくなりますが、スクレイピングのために必要な情報をWebから持ってくるだけなら、Pythonを使えば取得できます。

Webが高機能化、スクレイピングしにくい構成に

ただ、注意しなくてはならないのは、昨今のWebページが非常に高機能化してきていることです。従来のHTML上にすべての情報が記述されているサイトなら、HTMLを取得・分析・解析すれば何の問題もなく必要な情報が取得できますが、JavaScriptがフル活用されているWebサイトの場合は一筋縄ではいきません。たとえば、最近よく増えているのがAjaxなどと言われる非同期通信技術を使う場合です。まずファーストビューとなる部分だけを取得し、下にスクロールするごとにブラウザがデータをサーバに再度取得し、レンダリング表示させるサイトがそれにあたります。また、さらに高度なもので、Single Page Application(SPA)と呼ばれるHTML自体にはほとんど情報を持たせず、Ajaxによる通信によってページを遷移させずにコンテンツを切り替えることができるというものがあります。こういった作りのサイトの場合、WebページのHTMLから情報を取得することが難しい構成になっているため、どう情報を取得するか、その方法を考えていかなくてはいけません。これについては後ほど説明します。

HTMLの構造を理解して、ライブラリを便利に使おう

前述の通り、従来のHTML上にすべての情報があるサイトでは、HTMLの取得・分析・解析と、加工を施せば情報を抜き出すことができますが、そのためには多少のHTMLの知識が必要になります。

HTML自体は階層化されている情報のため、通常なら<body>タグの間に<div>や<p>タグ、id属性などのいろいろな要素が含まれており、ここから必要な情報を取得していくことになります。もし、HTMLの構造を調べてみても、いまいちどうなっているかわかりにくい場合にはChromeやFirefoxのデベロッパーツールを使えばその構造を把握することができます。スクレイピングに必要な情報は、文字列メソッドや正規表現を利用して取得することはできますが、現実的にこれをやろうと考えるとちょっと大変です。

そこで、Pythonの標準ライブラリであるurllibや、サードパーティ製ライブラリであるRequests、Beautiful Soup 4などを使えばデータの取得を簡単に行うことができます。ここからはスクレイピングのよくあるパターンについて説明します。

Beautiful Soup 4なら簡単にスクレイピングしたい情報を指定できる

デベロッパーツールで見つけたidやul、liなどの要素をBeautiful Soup 4で指定すれば、リストとして適切な情報を取得できるようになります。これがよく行われるスクレイピングのパターンです。

Beautiful Soup 4は、HTMLの構成が複雑なものの場合、その構造を把握することさえできれば、その構造に対して直接アクセスできるため、面倒な工夫をせずとも基本的に取得できる、便利でわかりやすく、使いやすいツールです。もしBeautiful Soup 4を導入したくないという場合で、きっちりとしたXMLでHTMLが記述されているのであれば標準ライブラリのElementTreeや似たようなツールで取得することも可能です。ただBeautiful Soup 4の方が絶対的に楽だとは思います。

ライブラリをうまく活用すれば、その先の情報の取得も容易に

取得した情報のさらに先、たとえばニュース一覧からニュースの詳細を知りたいといったこともよくあります。この場合、ニュース一覧をHTTPリクエストで取得し、その中にあるaタグのhref要素が確認できれば次のページのURLを取得できます。その後、Requestsなどを使い、HTTP通信によってデータを取得し、Beautiful Soup 4で解析させれば新しい情報をどんどん取ってこられるようになります。

より高度なスクレイピングをしたいならフレームワークScrapyを使う

ここまでRequestsやBeautiful Soup4というライブラリを紹介しましたが、スクレイピングをするためのライブラリにScrapyという高度なスクレイピングをしてくれるフレームワークもあります。本格的にスクレイピングをしたいという場合はこういったフレームワークを使うという手もあります。個人的にはそこまで求めていなかったため、使用方法を覚える手間を考えると多少使用したことがある程度で留まっていますが、RequestsとBeautiful Soup4を兼ね備えたようなもので便利ですし、フレームワークとしてはよくできているものという印象です。

簡易的に情報を抜き出しPandasで処理するという手も

もしHTMLの中からtableタグの情報だけを取得した後にPandasで処理したいのであれば、Pandasで使えるread_htmlという関数があります。これは厳密にはスクレイピングではありませんが、HTML要素のtableタグに囲われたもの全てを取って来てくれるので、処理を簡易的に済ませることが可能です。

高機能なサイトをスクレイピングしたいなら提供元が公開している情報を確認しよう

ここでお話しした手法はHTMLの中にすべての情報が書かれていることを前提として解析するものであるため、ブラウザがJavaScriptを通じて別のAPI通信によって新たなデータを取得し、都度レンダリングしなおしているようなサイトや、SPAが使われているサイトでは別の手段をとる必要があります。

デベロッパーツールで解析できればと思うかもしれませんが、デベロッパーツールで確認できる情報はレンダリングし終わった結果のため、IDなどのすべての情報を確認できますが、ブラウザのHTMLソース表示機能では最低限のソースしかない、または全く別のHTMLが表示されます。そのため、Requestsやurllibなどでは、「今」ブラウザに表示されている情報ではない情報しか取得できず、目的の情報にアクセスして取得することは残念ながらできません。そもそもほとんどのサイトがスクレイピングさせることを目的とした作りではありませんので、HTMLを解析して何かをすることについてはどうしても限界が出てきます。

ではそうした場合にどうすればいいか。まずはそのサイトがAPIや情報を別途提供していないか確認してみましょう。たとえば、最近あまり利用されなくなりましたがRSSを使用して何かできる可能性もあります。また、特別なエンドポイントが用意されているようならAPI通信でJSONが取れる可能性もあります。そういったデータを適切に取れる仕組みをサービス提供側が用意しているようなら、そこから情報を取ってくる方がスクレイピングするより適切に取れますし、より確実にアクセスしやすくなります。

もし、そうしたものが用意されておらず、動的にやるしかないようであればPythonの力だけではなかなか難しく、ほかのフレームワークやヘッドレスブラウザ、Seleniumなどの別のツールを使った方法を模索することになります。一気にハードルが上がりますが、検討してみてください。

APIとAPI専用ライブラリを使えばTwitterやYouTubeからもスクレイピングが可能に

TwitterやYouTubeから、何らかの一覧データが欲しいというケースがありますが、この時はAPIが使われることがほとんどです。たとえばTwitterはSPAによってできているため、ブラウザ上に表示されている全部の情報がHTMLに載っていません。 そのため、Twitterが提供しているAPIを使用することになります。

API通信をする場合、JSONでそのままデータが返ってくるような単純なものであれば、PythonでJSONを解析するための標準ライブラリjsonを使えば、データを取得することはできると思いますが、そういった多くのサービスが提供しているAPIは認証キーが必要などの様々な手続きを踏まなければなりません。そうなると、その部分をすべてプログラミングしなくてはならず、またAPIの仕様もよく変わるため結構大変な手間が発生します。そのため、APIを操ってくれる専用のライブラリがサービス提供側かサードパーティ製で提供されていないか、まずは調べてみましょう。

たとえばTwitterであれば、Tweepyというサードパーティ製ライブラリが存在します。Tweepyを使ってAPIを操作すれば、比較的簡単に情報を検索するなどの動作ができるようになっているため、うまくPythonで使いこなせば問題なくデータを取得できます。そこまでできれば、あとはHTMLの構造や通信についてはすべて忘れ、ライブラリを使いこなせるようになることで様々なことができるようになります。こういったAPIをうまく使いこなすのはPythonの得意なところなので、いろいろ試してもらえればと思います。

スクレイピングは一歩間違うとサイバー攻撃や利用規約違反になるので注意しよう

最後に、スクレイピングの注意点として、相手側のWebサーバに攻撃を仕掛けているような状態になってしまうことがあるということをお伝えしておきます。というのも、プログラミング的に誰かのWebサーバにアクセスしてデータを取ってくるものになりますので、処理の方法によってはループして1秒間に何回もアクセスしてしまい、相手側のWebサーバに大量のアクセスによる負荷をかけてしまう可能性が出てきます。そのかけてしまった負荷の規模によってはサーバをダウンさせてしまうため、法的に罰せられる可能性が出てきます。

また、Webサイトには運営側のライセンスや使用条件などの規約が設定されています。その規約の中で、スクレイピングのような機械的にデータを取得させるというような行為を禁止しているサイトもありますので、プログラムを作る前には必ず、大量のアクセスや機械的なアクセス、再利用の許可などの項目について規約に記述があるかを確認しましょう。

スクレイピングに限った話ではありませんが、プログラミングによって自分ができることが増え、日々の生活や仕事が便利になれば、それは誰にとっても嬉しく、そして、日々のモチベーションアップにつながります。昨今のSPAやAjax通信を大量に使うような高度なサイトでスクレイピングをするのはなかなか一筋縄ではいかないだろうとは思いますが、このコラムの内容をヒントに色々と試行錯誤してスクレイピングに挑戦していってもらえればと思います。

当協会の最新情報は公式サイトか、公式Facebookページでご覧いただけます。FacebookページではPythonに関連したニュースもお知らせしていますので、ぜひフォローしてみてください。また、YouTubeチャンネル「Pythonエンジニア認定試験」では、私が試験概要や学習のコツをお話ししたものや、合格した方のコメント動画を公開しています。こちらもぜひご覧ください。

[PR]提供:Pythonエンジニア育成推進協会