[Python #6] ステータスコードの使い方(初心者向け)
こんにちは、pythonチームのT.Sです。
今回は、requestsライブラリを使用したWebスクレイピングの際に役立つステータスコードの使い方についてお話しようと思います。
ステータスコードとは
ステータスコードは、IT用語辞典によるとシステム処理結果や現在の状態を外部に知らせるために発する数字や短い符合と定義されています。Webスクレイピングでは、主に3桁の数字により現在の状態を判断します。
前提ですが、requestsライブラリは目的ページのURLにHTTPリクエストを送信し、HTTPレスポンスを取得することでスクレイピングを行います。
ステータスコードは、何らかの理由でHTTPリスポンスを上手く取得できなかった時に役立つことが多いです。
例えば、requestsライブラリでスクレイピングを行う際に、GETメソッドでページにアクセスできない時、または、ページにアクセスできたものの、想定通りのHTTPレスポンスが取得できなかった時に役立つことが多いです。
ステータスコードは、HTTPレスポンスのstatus_code属性で取得でき、3桁の数字で送信されます。
3桁の数字は100番台、200番台、300番台、400番台、500番台に分類できます。
- 100番台:情報応答に関するレスポンスを示しています。要するにサーバー側がこちらのリクエストを処理中であることを意味します。
- 200番台:成功レスポンスを示しています。要するに、リクエストが成功したことを意味します。
- 300番台:リダイレクトを示しています。リダイレクトとは、簡単に言うと、アクセス先ページのURLが変更された時自動的に新しいURLのページにアクセスされることです。つまり、更新前ページにリクエストしても更新後ページに勝手にアクセスしてくれます。ただ、エラーを出力してくれないのでHTML形式が異なっていると突然HTMLデータが取得できなくなってしまうことがあるので注意が必要です。
- 400番台:クライアントエラーを示しています。要するに、こちら側に問題がある場合を指します。こちら側に問題があるので場合によっては対処可能です。
- 500番台:サーバーエラーを示しています。要するに、向こう側(サーバー側)に問題がある場合を指します。
300番台(リダイレクト)
300番台の中からスクレイピングに関するいくつかのステータスコードを例として挙げます。
- 301:リクエストしたページが永久的に更新先ページに移動したことを意味します。リクエスト先URLのドメイン名の変更や、「http」から「https」へSSL化された場合も301番に含まれます。
- 302:リクエストしたページが一時的に更新先ページに移動したことを意味します。302が返ってきた時は、時間を空けてコードを実行してみると上手くいくかもしれません。
400番台(クライアントエラー)
クライアントエラーはこちら側に問題がある為、あらかじめ対策、対処できる場合が多いです。400番台の中からスクレイピンングに関するいくつかのステータスコードを例として挙げます。
- 403:アクセスが禁止されていることを意味します。要するに、何らかの理由でサーバー側がクライアントのリクエストを拒否している状態です。よく聞く「BANされる」というのは、この状態のことです。例えば、スクレイピング先サイトの利用規約に従わなかった場合や、連続アクセスにより相手サーバーに負荷を掛けすぎた場合にBANされることが多いです。
- 404:リクエストしたリソースが存在しないことを意味します。存在しないURLへリクエストした際に見られることが多いです。404が返ってきた時は、指定したURLを見直すと良いかもしれません。
- 408:要求タイムアウトを意味します。要するに、サーバーの指定時間内にリクエストを生成できなかった状態です。408が返ってきた時は、回線状況などを確認した上でもう一度挑戦するのが良いかもしれません。
ステータスコードを見てみる
成功レスポンス(200番台)とリダイレクト(300番台)を例にステータスコードを出力してみます。
実行環境
OS:Windows11 Pro 各種バージョン: Python3.9.7 requests2.26.0
JupyterNotebook公式ページにリクエストしてみる
まずはJupyterNotebook公式ページにリクエストしてみます。ステータスコードはレスポンスオブジェクトのstatus_codeメソッドから出力できます。
import requests
url = 'https://jupyter.org'
res = requests.get(url)
print(res.status_code)
#レスポンスからアクセス先のURLを表示
print(res.url)
以下のような出力が得られます。
ステータスコードは200番台が出力されているのでリクエストに成功したことを意味します。アクセス先のURLもこちらで指定したURLになっていますね。
リダイレクト(300番台)を出力してみる
次に、URLの「https」を「http」にしてリクエストしてみます。
import requests
url = 'http://jupyter.org'
res = requests.get(url)
print(res.status_code)
print(res.url)
すると、「https」の時と全く同じ出力結果が得られます。これはどういうことかというと、requests側で自動的にリダイレクトが行われ、最終的にアクセスが成功していたのでステータスコード200が出力されている状態です。つまり、最終的にアクセスが成功していればステータスコード300番台は出力してくれないということになります。
そこで、300番台からリダイレクトされたか知りたい時は、レスポンスオブジェクトのhistoryメソッドからステータスコードの履歴情報を取得することで300番台を出力することができます。
import requests
url = 'http://jupyter.org'
res = requests.get(url)
print(res.status_code)
print(res.history)
print(res.url)
すると、以下のような出力が得られます。
ステータスコード301でリダイレクトされた後、ステータスコード200でリクエスト成功していることがわかりますね。
エラーを吐き出してみる
ステータスコード301でリダイレクトされていることが分かりました。しかし、実際には同じ301でもサイトが更新していてリダイレクトされたり、ステータスコード302でページが一時的に更新先ページに移動していてリダイレクトされる可能性もあります。スクレイピングを行う際は、ステータスコードが分かっただけでは実用性が高いとは言えないかもしれません。
そこで、ステータスコード200番台の成功レスポンス以外はあえてエラーを吐き出すことにします。エラーはレスポンスオブジェクトのraise_for_statusメソッドで出力することができます。URLはあえて存在しないURLにリクエストしてみます。
import requests
url = 'http://jupyter.org/zzz'
res = requests.get(url)
print(res.status_code)
res.raise_for_status()
ステータスコードは404番なのでしっかりエラーが出力されていますね。
最後に少し応用になりますが、ステータスコードによるエラーを利用した例外処理を使う方法もあります。
import requests
try:
res = requests.get('http://jupyter.org/zzz')
res.raise_for_status()
print(res.status_code)
#スクレイピングコードを記述していく
except requests.exceptions.HTTPError:
print("ステータスコードエラーです。")
出力結果です。
参考
ステータスコードとは - 意味をわかりやすく - IT用語辞典 e-Words
HTTPステータスコードのリスト - ウィキペディア (wikipedia.org)
最後に
今回は、webスクレピングに使われる技術の一部であるステータスコードについて紹介しました。 webスクレイピングに使用できる技術は他にもいろいろあり、今後の投稿でそれらについても触れていきたいと思います。 ファイナルアンサーのPythonチームではwebスクレイピングを用いた課題が用意されています。webスクレイピングに興味がある方は、弊社のインターンで一緒に学びましょう!!