【Python】urllib.error.HTTPErrorの解決方法

【Python】urllib.error.HTTPErrorの解決方法 プログラミング

「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の対策を説明しました。

タイトルとURLをコピーしました