PythonでプロキシをローテーションするΑ方法

IPブロックを克服し、ウェブスクレイピングプロセスを効率化するために、Pythonでのプロキシローテーションをマスターしましょう。
3 分読
How to Rotate Proxies in Python blog image

このPythonでプロキシをローテーションする方法に関するガイドでは、以下を学びます:

  • プロキシとは何か、なぜ使用するのか
  • プロキシローテーションとは何か、なぜ必要なのか
  • Pythonでプロキシをローテーションする方法
  • Pythonでプロキシをローテーションする際の一般的な制限事項

早速見ていきましょう!

プロキシとは?

プロキシとは、インターネット上でユーザーとネットワークリソースの仲介役として機能するサーバーです。つまり、プロキシは当事者間でリクエストとレスポンスを転送する仲介者と考えることができます。

なぜPythonでプロキシを使用するのか?

プロキシを使用してウェブサイトにリクエストを送信すると、まずリクエストはプロキシサーバーを経由します。その後、プロキシはあなたのリクエストをウェブサイトに転送し、レスポンスを受け取ってあなたに送り返します。このプロセスにより、宛先に対してあなたのIPアドレスが隠蔽され、リクエストがあなたのデバイスではなくプロキシサーバーから来ているように見えます。

プロキシを使用したい典型的な理由は、ウェブリクエストの自動化やウェブスクレイピングの場合です。このシナリオでは、豊富なライブラリと大規模で活発なコミュニティのおかげで、Pythonはウェブスクレイピングに最適な言語の一つです。

プロキシローテーションとは何か、なぜ必要なのか?

単一のIPアドレスから過剰なリクエストを送信すると、ウェブサイトはレート制限や完全なIPブロックによってあなたをブロックする可能性があります。ここでプロキシによるローテーションが役立ちます。

ウェブリクエストを行う際に異なるプロキシサーバーを体系的に切り替えることは、IPアドレスローテーションを実装する最良の方法の一つです。この手順は一般的なアンチスクレイピング技術を回避するのに役立ち、以下の利点をもたらします:

  • IPブロックの回避:複数のIPにリクエストを分散させることで、ウェブサイトがスクレイピング活動を検出しブロックすることを困難にします。
  • レート制限の回避:ウェブサイトは特定の時間枠内でIPアドレスごとにリクエスト制限を設定することがよくあります。プロキシをローテーションすることで、あるIPでこれらの制限に達した後もスクレイピングを続けることができます。
  • 地域制限コンテンツへのアクセス:一部のウェブサイトは地理的位置に基づいて異なるコンテンツを表示します。異なる国のプロキシを使ったプロキシローテーションにより、地域特有のコンテンツにアクセスできます。

Pythonでプロキシをローテーションする方法:3つのアプローチ

プロキシとは何か、なぜローテーションするのかがわかったところで、Pythonでのステップバイステップのチュートリアルの準備をしましょう。次の段落では、異なるアプローチとライブラリを使用してPythonでプロキシをローテーションする方法を示します。

すべてのスクリプトの対象サイトは、HTTPBinプロジェクトの/ipエンドポイントです。この特別なエンドポイントは呼び出し元のIPアドレスを返すため、サーバーから見えるIPがローテーションしているかどうかをテストするのに最適です。

Pythonでプロキシをローテーションしてみましょう!

要件

Pythonでプロキシをローテーションするチュートリアルを再現するには、マシンにPython 3.7以降がインストールされている必要があります。

前提条件

プロジェクトのメインフォルダをproxy_rotation/と呼ぶとします。このステップの最後には、フォルダは以下の構造になります:

proxy_rotation/
    ├── requests_file.py
    ├── async.py
    ├── scrapy_rotation/
    └── venv/ 

ここで:

  • requests.pyとasync.pyは、それぞれRequestsとAIOHTTPのプロキシローテーションロジックを格納するPythonファイルです。
  • scrapy_rotation/はScrapyプロジェクトを含むフォルダです。後で作成してインスタンス化します。
  • venv/は仮想環境を含みます

venv/ 仮想環境ディレクトリは次のように作成できます:

python -m venv venv

Windowsで有効化するには、以下を実行します:

venvScriptsactivate

同様に、macOSとLinuxでは、以下を実行します:

source venv/bin/activate

最後の前提条件として、プロキシのリストを取得する必要があります。この記事では、当社の無料プロキシリストを使用できます。

RequestsでPythonのプロキシをローテーションする方法

このチュートリアルセクションでは、Requestsを使用してPythonでプロキシをローテーションする方法を学びます。

ステップ#1:依存関係のインストール

有効化した仮想環境で、以下でRequestsをインストールします:

pip install requests

ステップ#2:ローテーションロジックの定義

Requestsを使ってPythonでプロキシをローテーションするには、requests_file.pyファイルに以下のコードを記述します:

import random
import requests

# プロキシのリストを定義し、ランダムに1つ返す
def get_random_proxy():
    proxies = [
        "http://PROXY_1:PORT_X",
        "http://PROXY_2:PORT_Y",
        "http://PROXY_3:PORT_X",
        # ここにさらにプロキシを追加...
    ]

    # ランダムにプロキシを選択
    return random.choice(proxies)

for i in range(3):
    proxy_url = get_random_proxy()
    proxies = {
        "http": proxy_url,
        "https": proxy_url,
    }
    response = requests.get("https://httpbin.io/ip", proxies=proxies)
    print(response.text)

ここで:

  • get_random_proxy()関数は取得したプロキシのリストを格納し、random.choice()メソッドでランダムに1つ返します。
  • forループはランダム化されたプロキシのリストを反復し、requests.get()メソッドで実際のリクエストを行います。詳細については、PythonのRequestsでプロキシを使用するガイドをお読みください。

ステップ#3:スクリプトの起動

スクリプトを起動するには、以下を実行します:

python requests_file.py

以下が期待されるレスポンスです:

{
  "origin": "PROXY_3:PORT_K"
}
{
  "origin": "PROXY_1:PORT_N"
}
{
  "origin": "PROXY_2:PORT_P"
}

素晴らしい!スクリプトの出口IPが望み通りにローテーションされました。

AIOHTTPでPythonのプロキシをローテーションする方法

Requestsライブラリを使用したランダム化アプローチの主な制限は、一度に1つのプロキシしか使用しないことです。つまり、次のプロキシが使用される前に、各リクエストが完了するのを待つ必要があります。

この制限を回避するには、AIOHTTPを使用できます。このライブラリは非同期リクエストを可能にし、ノンブロッキングな方法で複数のプロキシを同時に使用できます。言い換えれば、ターゲットサーバーへの非同期並列リクエストを行うことで、リストからプロキシをローテーションすることができます。AIOHTTPの実際の動作については、非同期ウェブスクレイピングのガイドをご覧ください。

次のセクションでは、AIOHTTPでPythonのプロキシをローテーションする方法を示します。

ステップ#1:依存関係のインストール

有効化した仮想環境で、以下でAIOHTTPをインストールします:

pip install aiohttp

ステップ#2:ローテーションロジックの定義

AIOHTTPを使ってPythonでプロキシをローテーションするには、async.pyファイルに以下のコードを記述します:

import asyncio
import aiohttp

# プロキシのリストを定義
proxies_list = [
    "http://PROXY_1:PORT_X",
    "http://PROXY_2:PORT_Y",
    "http://PROXY_3:PORT_X",
    # ここにさらにプロキシを追加...
]

async def fetch_ip(session, proxy_address, attempt):
    print(f"Attempt {attempt} using proxy: {proxy_address}")
    async with session.get("https://httpbin.io/ip", proxy=proxy_address) as response:
        json_response = await response.json()
        print(f"Response from httpbin.io/ip (Attempt {attempt}):")
        print(f"IP Address: {json_response.get('origin', 'Unknown')}")
        print("-" * 40)
        return json_response

async def main():
    async with aiohttp.ClientSession() as session:
        tasks = []
        num_attempts = 3
        for i in range(num_attempts):
            # モジュロ演算子でプロキシをローテーション
            proxy_address = proxies_list[i % len(proxies_list)]
            tasks.append(fetch_ip(session, proxy_address, i + 1))
        # すべてのリクエストを同時に実行
        await asyncio.gather(*tasks)

# スクリプトを起動
asyncio.run(main())

このコードは以下を行います:

  • fetch_ip()関数は、セッション、プロキシ、試行番号を取り、リクエストを管理します。具体的には、対象ウェブサイトにGETリクエストを送信し、レスポンスを出力します。
  • main()関数は:
    • HTTP接続を管理するためにaiohttp.ClientSession()メソッドでセッションを作成します。
    • 複数のリクエストを同時に送信するためのタスクのリストと試行回数を設定します。
    • リクエスト数がプロキシの数を超えた場合にプロキシがラウンドロビン方式で再利用されるように、モジュロ演算子(i % len(proxies_list))を使用してプロキシをローテーションします。詳細は、AIOHTTPでプロキシを設定する方法のチュートリアルをご覧ください。
    • asyncio.gather()メソッドを使用してすべてのタスクを同時に実行します。

ステップ#3:スクリプトの起動

スクリプトを起動するには、以下を実行します:

python async.py

これが期待されるレスポンスです:

Attempt 1 using proxy: http://PROXY_1:PORT_X
Attempt 2 using proxy: http://PROXY_2:PORT_Y
Attempt 3 using proxy: http://PROXY_3:PORT_Z

Response from httpbin.io/ip (Attempt 3):
IP Address: xxx.xxx.xxx.xxx
----------------------------------------
Response from httpbin.io/ip (Attempt 1):
IP Address: yyy.yyy.yyy.yyy
----------------------------------------
Response from httpbin.io/ip (Attempt 2):
IP Address: zzz.zzz.zzz.zzz
----------------------------------------

素晴らしい!IPが期待通りにローテーションされています。

Python Scrapyでプロキシをローテーションする方法

以前の記事では、scrapy-rotating-proxiesを使用してScrapyでプロキシをローテーションする可能性について説明しました。

このガイドセクションでは、その方法を学びます!

ステップ#1:依存関係のインストール

有効化した仮想環境で、必要なライブラリをインストールします:

pip install scrapy scrapy-rotating-proxies

ステップ#2:新しいScrapyプロジェクトの作成

リポジトリのメインフォルダ(proxy_rotation/)内で、このコマンドで新しいScrapyプロジェクトをインスタンス化します:

scrapy startproject scrapy_rotation

これにより、以下の構造を持つscrapy_rotation/という新しいサブフォルダが作成されます:

scrapy_rotation/
  ├── scrapy_rotation/ 
  │   ├── __init__.py
  │   ├── items.py # スクレイピングされたアイテムのデータ構造を定義
  │   ├── middlewares.py # カスタムミドルウェア
  │   ├── pipelines.py # スクレイピングされたデータの後処理を処理
  │   ├── settings.py # プロジェクト設定
  │   └── spiders/ # すべてのスパイダー用フォルダ
  └── scrapy.cfg # Scrapy設定ファイル

メインフォルダ(proxy_rotation/)から、scrapy_rotation/に移動します:

cd scrapy_rotation

以下を実行して、対象ウェブサイトを指す新しいスパイダーを作成できます:

scrapy genspider rotation http://httpbin.io/ip

このスクリプトはspiders/フォルダ内にrotation.pyファイルも作成します。

ステップ#3:ローテーションロジックの定義

プロキシローテーションロジックは、以下の設定でsettings.pyファイルを変更することで管理できます:

# ローテーションプロキシミドルウェアを有効化
DOWNLOADER_MIDDLEWARES = {
    "rotating_proxies.middlewares.RotatingProxyMiddleware": 610,
    "rotating_proxies.middlewares.BanDetectionMiddleware": 620,
}

# ローテーションするプロキシのリスト
ROTATING_PROXY_LIST = [
    "http://PROXY_1:PORT_X",
    "http://PROXY_2:PORT_Y",
    "http://PROXY_3:PORT_Z",
    # 必要に応じてさらにプロキシを追加
]

# リトライ設定を構成
RETRY_TIMES = 5  # 失敗したリクエストのリトライ回数
RETRY_HTTP_CODES = [500, 502, 503, 504, 408]  # リトライするHTTPコード

ここでプロキシローテーションを管理しているのは、DOWNLOADER_MIDDLEWARES内のrotating_proxies.middlewares.RotatingProxyMiddleware: 610オプションです。具体的には、このオプションはROTATING_PROXY_LISTからプロキシを選択し、各リクエストに割り当てます。

また、rotating_proxies.middlewares.BanDetectionMiddleware: 620オプションにより、スクレイパーはIPが対象ウェブサイトによって禁止またはブロックされたかどうかを検出できます。その理由でリクエストが失敗した場合、ミドルウェアは新しいプロキシでリクエストを再試行します。つまり、このオプションはRotatingProxyMiddlewareと緊密に連携して、禁止されたプロキシが自動的に回避されるようにします。

さて、spiders/フォルダ内のrotation.pyファイルに以下を記述できます:

import scrapy

class IpSpider(scrapy.Spider):
    name = "ip_spider"
    start_urls = ["http://httpbin.io/ip"]
    def parse(self, response):
        # レスポンスからIPアドレスを抽出して出力
        ip = response.json().get("origin")
        self.log(f"IP Address: {ip}")

このクラスはスパイダー全体をインスタンス化し、各リクエストでレスポンスを出力します。

ステップ#4:スクリプトの起動

スクリプトを起動するには、IpSpider()クラスの名前であるip_spiderを使用する必要があります:

scrapy crawl ip_spider

ScrapyがCLIで返すデータは特に充実しています。すべてがうまくいった場合、他の情報の中に以下のようなものが見つかります:

2026-02-18 14:55:17 [rotating_proxies.expire] DEBUG: Proxy <http://PROXY_1:PORT_X> is GOOD
2026-02-18 14:55:17 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://httpbin.io/robots.txt> (referer: None)
2026-02-18 14:55:24 [rotating_proxies.middlewares] INFO: Proxies(good: 1, dead: 0, unchecked: 2, reanimated: 0, mean backoff time: 0s)

Pythonでのプロキシローテーションに対する上記アプローチの制限

上記のプロキシローテーション方法は便利ですが、いくつかの制限があります:

  • プロキシのリストを手動で取得し管理する必要があります。
  • 定型的なコードが必要です。
  • 高品質なプロキシサーバーを使用しない場合、依然としてIPブロックが発生する可能性があります。

Pythonでのプロキシローテーションをより効率的かつ効果的に処理する方法をお探しなら、Bright Dataは市場で最高のローテーションプロキシの一部を提供しています。単一のプロキシURLだけで、HTTPクライアントやスクレイピングライブラリに統合できます。これにより、定型的なコードと手動のローテーション管理が不要になります。

このアプローチの他の主な利点は以下の通りです:

  • 設定可能なスティッキーIPによる自動IPローテーション
  • 400M+ monthly百万のレジデンシャルIPへのアクセス
  • プロキシサーバーの場所に対するジオロケーション制御
  • HTTP、HTTPS、SOCKSプロトコルのサポート

プロキシ管理を簡素化しましょう—当社の自動ローテーションプロキシをご覧ください!

まとめ

この記事では、Requests、AIOHTTP、Scrapyという3つの異なるライブラリを使用して、Pythonでプロキシをローテーションする方法を学びました。上記のガイドセクションで示したように、このプロセスは複雑ではなく、数行のコードしか必要としません。

しかし、このアプローチにはいくつかの欠点があります:

  • コードが定型文だらけで、スクリプトの保守性が低下します。
  • 大量のプロキシサーバーリストを管理しアクセスを提供する必要があります。

幸いなことに、Bright Dataの自動ローテーションプロキシを使えば、Pythonでプロキシをローテーションするより効率的なソリューションで、こうした手間をすべて省くことができます。

Bright Dataは世界最高のプロキシサーバーを管理しており、フォーチュン500企業や50,000+の顧客にサービスを提供しています。その提供内容には幅広い種類のプロキシが含まれます:

今すぐBright Dataアカウントを作成して、当社のプロキシとスクレイピングソリューションをテストしてください!