Pythonで年齢認証などのクッションページを回避してスクレイピングしたい


はじめに

私が運営しているWebアプリケーションのジャンル的に、
スクレイピングでこんなページによく出くわします。

アダルトサイトとかでよく出くわしますが、通常のサイトでも(ログインまではいかないが)強制的にクッションサイトに飛ばされることがあるかと思います。

この強制的にクッションサイトに飛ばされることは、指定したURLではなく、クッションページをスクレイピングすることになってしまうため、大きな問題となります。

こういったページを回避して、目的のページをスクレイピングする方法を忘記録として残しておきます。

クッションページを回避してスクレイピング

それぞれ独立しているわけではありませんが、以下の3通りで概ね解決できるかと。

  1. seleniumを使う
  2. requests.session()を使う
  3. クッキーを渡す

なお、本記事で解説するのは「2」と「3」です。

1. seleniumを使う

一番手っ取り早いのはseleniumでchromeやfirefoxのdriverを使うことです。

seleniumの利点は、GUI的なWebブラウザの操作ができる点。
「あるページにアクセス」→「そのページのある要素をクリック」なんてことが、Python上だけで実現できます。

seleniumの詳しい解説は結構転がっているので、本記事では割愛。

ただ、問題なのはChromeやFirefoxが無い環境では動かせないという点。
sudo権限のないCUIのレンタルサーバーとかでChromeをインストールするのは(できなくはないと思いますが)非常に厳しいです。

2. requests.session()を使う

seleniumを使わなくても、クッションページの回避程度ならrequestsモジュールのsessionで十分な場合が多いです。


import requests
from bs4 import BeautifulSoup

url_certification = 'クッションページの「はい」のURL'
url_target = 'スクレイピングしたいURL'

session = requests.session()
session.get(url_certification)

soup = BeautifulSoup(session.get(url_target).content, 'lxml')

よく使用されるrequests.getはワンタイムのアクセスですが、
上記のようにsessionを使用することで、連続したアクセスを実現が実現できます。
あと、seleniumよりも圧倒的に速いのも利点。

3. クッキーを渡す

クッションページ内の「はい」のURLが、「クッキーを生成するJavaScriptへのアクセス」だと、requests.session()だけではうまくいきません。
このような場合は「はい」をクリックしたときに生成されるクッキーをrequests.getに渡してやることで解決します。


cookie = {'abc': '1'}  # 予め調べておく。

soup = BeautifulSoup(requests.get(url, cookies=cookie).content, 'lxml')

今回はパスワードやメールアドレスなどのセキュアな情報を扱うわけではないので、セキュリティ面などはあまり気にせずに書いています。

cookieの調べ方は、他の方の記事を参照してください。ある要素をクリックしたときに生成されるクッキーの値を取得するといったことは、Chromeなどの実際のブラウザや、前述のselemiumなどから調べることができます。

なお、requests.getにわたすクッキーのvalueは、str型でなければならない点に注意してください。

まとめ

seleniumは色々と高機能で楽ですが、requestsモジュールだけでも色々と実現できます。
機能・速さ・セキュリティなどを考慮して、適材適所を心がけたいですね。