Edited at

ScrapyでProxyを使う方法

More than 1 year has passed since last update.


Proxyの使い方

Proxyの機能は HttpProxyMiddleware で提供されていて、デフォルトで利用可能となっている。

Requestオブジェクトに対しmetaキーで指定することで利用できる。

公式ドキュメントはこちら。

# e.g.

url = 'http://example.com/'
meta = {'proxy': 'http://145.239.92.106:3128'}
scrapy.Request(url, meta=meta)


SpiderのRequestでProxyを使う

start_urls に指定したURLへのアクセスにProxyを使うには start_requests() をOverrideすればよい。start_requests()のドキュメントはこちら

class MySpider(scrapy.Spider):

start_requests = ['http://www.example1.com/', 'http://www.example2.com/']

def start_requests(self):
for url in self.start_urls:
meta = {'proxy': 'http://145.239.92.106:3128'}
yield scrapy.Request(url, meta=meta)


CrawlSpiderのRequestでProxyを使う

start_requests() のOverrideはSpiderと同様にする必要がある。

しかしCrawlSpiderの場合はRuleによって得られたLinkへアクセスするRequestにもProxyを設定する必要がある。

この場合 _build_request() をOverrideすればよい。 CrawlSpiderのソースコードはこちら

class MySpider(CrawlSpider):

def _build_request(self, rule, link):
# CrawlSpider の実装
#r = Request(url=link.url, callback=self._response_downloaded)
#r.meta.update(rule=rule, link_text=link.text)
#return r
r = super(MySpider, self)._build_request(rule, link)
r.meta.update(proxy='http://175.139.252.193:80')
return r


複数のProxyを設定して利用する

Proxyを複数用意してランダムで利用する。Proxyは外部ファイルで設定しておくと利用しやすい。


proxies.yml

---

- http://190.145.80.114:3130
- http://148.217.94.54:3128
- http://125.212.207.121:3128

class MySpider(scrapy.Spider):

proxies = None

# proxies.yml からランダムに選ぶ
def get_proxy(self):
if not self.proxies:
f = open('proxies.yml')
self.proxies = yaml.load(f)
f.close()
return self.proxies[int(random() * len(self.proxies))]

def start_requests(self):
for url in self.start_urls:
meta = {'proxy': self.get_proxy()}
yield scrapy.Request(url, meta=meta)


Proxyのエラーに対処する

Proxyが動いていなかったり、アクセスが拒否された時には別のProxyを設定したい。こういう場合には errback にcallbackメソッドを指定する。

class MySpider(scrapy.Spider):

start_requests = ['http://www.example1.com/', 'http://www.example2.com/']
proxies = None

def get_proxy(self):
if not self.proxies:
f = open('proxies.yml')
self.proxies = yaml.load(f)
f.close()
return self.proxies[int(random() * len(self.proxies))]

def start_requests(self):
for url in self.start_urls:
meta = {'proxy': self.get_proxy()}
yield scrapy.Request(
url,
meta=meta,
callback=self.parse_page,
errback=self.new_request
)

def new_request(self, failure):
meta = {'proxy': self.get_proxy()}
yield scrapy.Request(
url=failure.request.url,
meta=meta,
callback=self.parse_page,
errback=self.new_request
)


Tips 利用可能なProxyのリストを作る


ワンライナーでproxyをチェックする

フリーのプロキシーサーバーはこういったサイトにまとめられている。必要に応じてピックアップし一覧にする。

例えばこのようなもの。

$ cat proxy_list

192.241.157.239:8080
125.212.207.121:3128
145.239.92.106:3128
185.93.3.123:8080
175.139.252.193:80

簡単なワンライナーでチェックして利用の可否を判定する。

$ cat proxy_list |\

xargs -I@ bash -c "URL=@; curl --proxy http://@ http://example.com 1>/dev/null 2>&1 && echo success \$URL || echo failure \$URL"

success となったProxyを利用する。