「urllib.error.HTTPError: HTTP Error 403: Forbiddenが出て困っている・・・」
「urllib.requestでアクセスできないページがある・・・」
このような場合には、この記事の内容が参考となります。
この記事では、urllib.error.HTTPError: HTTP Error 403: Forbiddenの解決方法を解説しています。
本記事の内容
- urllib.error.HTTPErrorとは?
- urllib.error.HTTPError: HTTP Error 403: Forbiddenの原因
- urllib.error.HTTPError: HTTP Error 403: Forbiddenの対策
それでは、上記に沿って解説していきます。
urllib.error.HTTPErrorとは?
urllib.errorとは、urllib.requestが投げる例外を定義しているモジュールです。
そして、urllib.errorは以下の例外を送出します。
- URLError
- HTTPError
それぞれを以下で説明します。
urllib.error.URLError
この例外は、そもそも指定したURLにアクセスできない場合に出ます。
最も目にするのは、以下のエラーでしょう。
urllib.error.URLError: <urlopen error [Errno -2] Name or service not known>
このエラーは、urllib.requestで「https://example.commm/」にアクセスを試みた場合に出ています。
ドメインの存在チェックをする場合には、この例外を利用できるでしょう。
urllib.error.HTTPError
この例外は、指定したURLにアクセス可能です。
アクセスした結果として、何かしらの反応があったと言えます。
その反応は、HTTPステータスコードとして取得できます。
urllib.error.HTTPError: HTTP Error 301: Moved Permanently urllib.error.HTTPError: HTTP Error 400: Bad Request urllib.error.HTTPError: HTTP Error 401: Unauthorized urllib.error.HTTPError: HTTP Error 403: Forbidden urllib.error.HTTPError: HTTP Error 404: Not Found urllib.error.HTTPError: HTTP Error 500: Internal Server Error urllib.error.HTTPError: HTTP Error 503: Service Unavailable
HTTPステータスコード2xx以外の場合は、上記のようにエラーとなります。
つまり、urllib.error.HTTPErrorはHTTPステータスコード2xx以外の場合だと言うことです。
以上、urllib.error.HTTPErrorについて説明しました。
次は、urllib.error.HTTPError: HTTP Error 403: Forbiddenの原因を説明します。
urllib.error.HTTPError: HTTP Error 403: Forbiddenの原因
urllib.error.HTTPError: HTTP Error 403: Forbidden
urllib.requestを利用している場合、上記のエラーに遭遇することがあります。
それも結構な頻度で存在します。
この原因は、アクセスしたページがHTTPステータスコード403を返しているからです。
では、なぜアクセスしたページがHTTPステータスコード403を返すのでしょうか?
該当アクセスを禁止したいからです。
真っ当なアクセスではないと判断されてしまったと言えます。
出禁状態ですね。
出禁を食らうのは、ユーザーエージェントがその原因となります。
デフォルトでは、urllib.requestでアクセスした場合のユーザーエージェントは以下となります。
Python-urllib/Pythonバージョン
アクセスログには、次のように記録されます。
185.81.157.200 - - [29/Nov/2021:21:55:23 +0900] "GET /index.php?id=1%27 HTTP/1.1" 301 486 "-" "Python-urllib/2.7" 185.81.157.200 - - [29/Nov/2021:23:00:39 +0900] "GET /index.php?id=1%27 HTTP/1.1" 301 486 "-" "Python-urllib/2.7" 20.212.106.170 - - [01/Dec/2021:05:55:09 +0900] "GET /.git/HEAD HTTP/1.1" 301 470 "-" "Python-urllib/3.6" 103.192.78.20 - - [03/Dec/2021:14:07:02 +0900] "GET /.git/HEAD HTTP/1.1" 301 470 "-" "Python-urllib/3.8" 202.87.162.237 - - [04/Dec/2021:21:58:12 +0900] "GET /.git/HEAD HTTP/1.1" 301 470 "-" "Python-urllib/3.9" 202.87.162.237 - - [04/Dec/2021:22:12:52 +0900] "GET /.git/HEAD HTTP/1.1" 301 470 "-" "Python-urllib/3.9" 2.56.59.229 - - [22/Dec/2021:00:47:28 +0900] "GET /.git/HEAD HTTP/1.1" 301 470 "-" "Python-urllib/3.8" 143.244.148.9 - - [22/Dec/2021:01:30:53 +0900] "GET /.git/HEAD HTTP/1.1" 301 470 "-" "Python-urllib/3.9"
これは、当ブログにおけるアクセスログからの抜粋になります。
攻撃のようなことが、urllib.requestを用いて実行されているということです。
皆さんはこれを見て、urllib.requestによるアクセスを禁止したくなりませんか?
なるかもしれませんね。
ユーザーエージェントに「Python-urllib」を含む場合は出禁だと・・・
その結果として、次のようなエラーを目にすることになるのです。
urllib.error.HTTPError: HTTP Error 403: Forbidden
以上、urllib.error.HTTPError: HTTP Error 403: Forbiddenの原因を説明しました。
次は、urllib.error.HTTPError: HTTP Error 403: Forbiddenの対策を説明します。
urllib.error.HTTPError: HTTP Error 403: Forbiddenの対策
urllib.error.HTTPError: HTTP Error 403: Forbiddenの原因は、判明しています。
原因がわかれば、その対策は可能となります。
その対策とは、ユーザーエージェントを偽装することです。
その偽装が本当に効果があるかを確かめるために、確認用のページを用意しました。
ユーザーエージェント偽装確認ページ
(テストで利用したい場合は、ご自由にどうぞ)
https://self-development.info/sv/api/check_useragent.php
ブラウザでアクセスしたら、そのブラウザのユーザーエージェントを表示します。
このページを利用して、偽装なし・ありの場合を検証します。
偽装なし
まずは、偽装なしの状態でアクセスしてみましょう。
import urllib.request url = "https://self-development.info/sv/api/check_useragent.php" request = urllib.request.Request(url=url) with urllib.request.urlopen(request) as response: print(response.read().decode('utf-8'))
上記を実行すると、次のエラーが表示されます。
urllib.error.HTTPError: HTTP Error 403: Forbidden
もちろん、このときのユーザーエージェントは「Python-urllib」を含みます。
アクセスログには、次のように記録されています。
●.●.●.● - - [06/Aug/2022:08:34:57 +0900] "GET /sv/api/check_useragent.php HTTP/1.1" 403 4958 "-" "Python-urllib/3.10"
偽装あり
次は、偽装ありの状態でアクセスします。
import urllib.request url = "https://self-development.info/sv/api/check_useragent.php" headers = { "User-Agent": "camouflage useragent", } request = urllib.request.Request(url=url, headers=headers) with urllib.request.urlopen(request) as response: print(response.read().decode('utf-8'))
上記を実行すると、設定したユーザーエージェントが表示されます。
camouflage useragent
この結果を確認できれば、偽装は成功と言えます。
なお、このときのアクセスは以下のようにログに記録されています。
●.●.●.● - - [06/Aug/2022:08:38:22 +0900] "GET /sv/api/check_useragent.php HTTP/1.1" 200 5086 "-" "camouflage useragent"
HTTPステータスコードが200であり、「camouflage useragent」も確認できます。
以上、urllib.error.HTTPError: HTTP Error 403: Forbiddenの対策を説明しました。