Help us understand the problem. What is going on with this article?

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を利用する。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away