自然言語処理では、しばしばコーパスを作るためにWeb上のリソースを利用します。そのためにスクレイピングをするのですが、大量のリクエストを特定のサイトに送るとBanされる可能性があります。今回はそれを防ぐ一つの方法を書きます。(悪用厳禁)
TL;DR
VPNを使おう。
概要
nordvpnのようなVPNを使えば、数十の国の数千のサーバを利用することができます。もし、これらの膨大なサーバリストを使ってスクレイピングに利用することができれば、以下の2つのメリットがあります:
- ランダムにIPを変え続ければブロックされる可能性が下がり、仮にブロックされても別のサーバーのIPを使えばいい。
- 複数のサーバのIPを利用してスクレイピングするので、並列化すれば、time.sleepの間隔を長めにしてもスクレイピングできるデータ量は多い。
実用的には、大量のサーバホストのなかからランダムに1つ選んでそこへ接続するという方法があります。
コード例
metadata.py
proxyサーバリストをmetadata.pyという名前で作成します。(名前は何でもいいです)
PROXY: proxyのURLのフォーマット。UNはユーザ名、 PSはパスワード、SVはPROXIES内に保存されているサーバプレフィクス。
PROXY = "http://{UN}:{PS}@{SV}.nordvpn.com:80" PROXIES = [ "md8", "no135", "es59", "se161" ...(と数千のサーバリストを書いていく) ]
requestsを使った接続
requestsモジュールを使ってプロキシに接続し、ターゲットのサイトを取得できます。
import json import random import requests import metadata def load_account(account_file): with open(account_file) as f: ac = json.load(f) return ac ac = load_account("account.json") def build_proxy(ac): sv = random.choice(metadata.PROXIES) return metadata.PROXY.format(UN=ac["user"], PS=ac["pass"], SV=sv) def download_html(url): proxy = build_proxy(ac) r = requests.get(url, proxies={"http": proxy, "https": proxy}) return r.text if __name__ == "__main__": html = download_html( "https://search.yahoo.com/search?p=test&fr=yfp-t&fp=1&toggle=1&cop=mss&ei=UTF-8" ) print(html)
サーバリストの見つけ方
nordvpnのサーバリストは基本的に国名のprefixとサーバ番号の組み合わせです。
サーバリストを発見するには、以下のページから探すことができます。
https://nordvpn.com/servers/tools/
あるいは、ロケーションコードが分かる場合は以下のスクリプトを使えます:
import socket import threading import queue HOST = "{LOC}{NUM}.nordvpn.com" def socket_it(url): try: socket.getaddrinfo(url, 80, proto=socket.IPPROTO_TCP) return url except Exception: return None def run(q, url): q.put(socket_it(url)) def check(location_code, max_num=1000): q = queue.Queue() for i in range(max_num): u = HOST.format(LOC=location_code, NUM=str(i)) t = threading.Thread(target=run, args=(q, u)) t.daemon = True t.start() return q if __name__ == "__main__": import sys q = check(sys.argv[1]) while not q.empty(): s = q.get(timeout=0.1) if s is not None: print(s)
$ python3 check_server.py jp
[出力]
jp201.nordvpn.com jp202.nordvpn.com jp204.nordvpn.com jp203.nordvpn.com jp208.nordvpn.com jp209.nordvpn.com jp218.nordvpn.com jp219.nordvpn.com jp220.nordvpn.com jp221.nordvpn.com jp222.nordvpn.com jp225.nordvpn.com jp234.nordvpn.com jp235.nordvpn.com jp233.nordvpn.com jp236.nordvpn.com jp227.nordvpn.com jp223.nordvpn.com jp226.nordvpn.com jp224.nordvpn.com jp232.nordvpn.com