Python3 クローラーでは、プロキシの使用は IP ブロックの防止やクロール速度の向上によく使われる方法で、主に複数の IP アドレスからアクセスしているように見せるために使われます。プロキシは無料プロキシと有料プロキシに大きく分けられ、無料プロキシは不安定で、有料プロキシは比較的安定していて信頼性があります。

以下は Python3 クローラープロキシの利用シーンと用途です。

IP ブロックの防止:一部のサイトでは IP ごとのアクセス頻度制限が設けられており、回数が上限を超えるとその IP からのアクセスが禁止されます。プロキシを使えば、このような事態を避けられます。

クロール速度の向上:プロキシを使えば複数の接続を同時に確立できるため、対象データをすばやくクロールできます。

地域制限の回避:サイトによっては、地域ごとに提供するサービスが異なります。特定地域向けにのみ公開されているサイトへアクセスする必要がある場合、プロキシを使えばこの制限を回避し、必要なデータを取得できます。

要するに、プロキシIPは Python3 クローラーにおいて非常に重要な役割を果たします。ただし、プロキシの利用には一定のセキュリティ上の問題も伴うため、利用時には適切なプロキシサービスプロバイダーを選び、ネットワークセキュリティ規定を厳格に守る必要があります。

事前準備

まずは利用可能なプロキシを 1 つ用意する必要があります。プロキシとは IP アドレスとポートの組み合わせで、つまり IP:ポート という形式です。プロキシアクセスに認証が必要な場合は、さらにユーザー名とパスワードの 2 つの情報が必要です。

ここでは、私のローカル環境にプロキシソフトを 1 つインストールしてあり、ローカルの 7890 ポートに HTTP プロキシサービス、つまり 127.0.0.1:7890 を作成しています。また、このソフトは 7891 ポートに SOCKS プロキシサービス、つまり 127.0.0.1:7891 も作成します。そのため、このプロキシを設定するだけで、ローカルマシンの IP を、そのプロキシソフトが接続しているサーバーの IP に切り替えられます。

以下のサンプルでは、上記のプロキシを使って設定方法を説明します。必要に応じて、自分で使えるプロキシに置き換えてください。

プロキシ設定後、テスト用の URL は http://httpbin.org/get です。このリンクにアクセスすると、リクエストに関する情報を取得できます。返された結果の origin フィールドがクライアントの IP なので、それを見ればプロキシ設定が成功したか、つまり IP の偽装に成功したかを判断できます。

では次に、各リクエストライブラリでのプロキシ設定方法を見ていきましょう。

Python3 クローラープロキシを取得する

一部のサイトは、自サイトのデータに対する頻繁なアクセスを検知し、それを阻止する対策を取ります。プロキシサーバーを使えばアクセス元を分散できるため、検知される可能性を下げ、クロール成功率を高められます。

最適な米国静的プロキシIP

IPRoyalは中国地域に非常に親和的なプロキシサービスプロバイダーであり、その住宅プロキシソリューションは非常に魅力的です

IPRoyalを見る
最も安い静的プロキシ

Proxy-seller はデータセンタープロキシのプロバイダーであり、多くの小規模なインターネットマーケターに人気があります。

Proxy-sellerを見る
最もお手頃な静的プロキシ

Shifter.io は、プライバシー保護とより良いインターネット体験をユーザーに提供することを目的とした、よく知られたプロキシサービスプロバイダーです。

Shifter.ioを見る

2. urllib

まずは最も基本的な urllib を例に、プロキシの設定方法を見てみましょう。コードは次のとおりです。

 from urllib.error import URLError
 from urllib.request import ProxyHandler, build_opener

 proxy = '127.0.0.1:7890'
 proxy_handler = ProxyHandler({
    'http': 'http://' + proxy,
    'https': 'http://' + proxy
 })
 opener = build_opener(proxy_handler)
 try:
    response = opener.open('https://httpbin.org/get')
    print(response.read().decode('utf-8'))
 except URLError as e:
    print(e.reason)
 

実行結果は次のとおりです。

 {
  "args": {},
  "headers": {
    "Accept-Encoding": "identity",
    "Host": "httpbin.org",
    "User-Agent": "Python-urllib/3.7",
    "X-Amzn-Trace-Id": "Root=1-60e9a1b6-0a20b8a678844a0b2ab4e889"
  },
  "origin": "210.173.1.204",
  "url": "https://httpbin.org/get"
 }
 

ここでは ProxyHandler を使ってプロキシを設定します。パラメータは辞書型で、キーがプロトコル種別、値がプロキシです。ここではプロキシの前にプロトコルを付ける必要があり、つまり http:// または https://の形式にします。リクエスト先が HTTP プロトコルの場合は http キーに対応するプロキシが使われ、HTTPS プロトコルの場合は https キーに対応するプロキシが使われます。ただし、ここではプロキシ自体を HTTP プロトコルに設定しているため、プレフィックスはすべて http://としています。そのため、HTTP と HTTPS のどちらのリンクにアクセスする場合でも、ここで設定した HTTP プロトコルのプロキシが使われます。

ProxyHandler オブジェクトを作成したら、次は build_opener メソッドにそのオブジェクトを渡して Opener を作成します。これで、この Opener にはすでにプロキシが設定された状態になります。あとは Opener オブジェクトの open メソッドを直接呼び出せば、目的のリンクにアクセスできます。

実行結果は JSON で、origin というフィールドにクライアントの IP が示されます。確認すると、この IP は実際にプロキシの IP であり、本当の IP ではありません。これでプロキシ設定は成功し、実際の IP を隠せました。

認証が必要なプロキシに遭遇した場合は、次の方法で設定できます。

 from urllib.error import URLError
 from urllib.request import ProxyHandler, build_opener

 proxy = 'username:password@127.0.0.1:7890'
 proxy_handler = ProxyHandler({
    'http': 'http://' + proxy,
    'https': 'http://' + proxy
 })
 opener = build_opener(proxy_handler)
 try:
    response = opener.open('https://httpbin.org/get')
    print(response.read().decode('utf-8'))
 except URLError as e:
    print(e.reason)
 

ここで変更するのは proxy 変数だけで、プロキシの前に認証用のユーザー名とパスワードを追加すればよいだけです。username がユーザー名、password がパスワードです。たとえば username が foo、password が bar の場合、プロキシは foo:bar@127.0.0.1:7890

プロキシが SOCKS5 型なら、次の方法で設定できます。

 import socks
 import socket
 from urllib import request
 from urllib.error import URLError

 socks.set_default_proxy(socks.SOCKS5, '127.0.0.1', 7891)
 socket.socket = socks.socksocket
 try:
    response = request.urlopen('https://httpbin.org/get')
    print(response.read().decode('utf-8'))
 except URLError as e:
    print(e.reason)
 

ここでは socks モジュールが必要です。次のコマンドでインストールできます。

 pip3 install PySocks