web-dev-qa-db-ja.com

スクレイピーで302リダイレクトを処理する方法

Webサイトを廃棄しているときに、サーバーから302応答を受信して​​います。

2014-04-01 21:31:51+0200 [ahrefs-h] DEBUG: Redirecting (302) to <GET http://www.domain.com/Site_Abuse/DeadEnd.htm> from <GET http://domain.com/wps/showmodel.asp?Type=15&make=damc&a=664&b=51&c=0>

リダイレクトされるのではなく、GETURLにリクエストを送信したい。今、私はこのミドルウェアを見つけました:

https://github.com/scrapy/scrapy/blob/master/scrapy/contrib/downloadermiddleware/redirect.py#L31

このリダイレクトコードをmiddleware.pyファイルに追加し、これをsettings.pyに追加しました。

DOWNLOADER_MIDDLEWARES = {
 'street.middlewares.RandomUserAgentMiddleware': 400,
 'street.middlewares.RedirectMiddleware': 100,
 'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware': None,
}

しかし、私はまだリダイレクトされています。このミドルウェアを機能させるために私がしなければならないのはそれだけですか?私は何かが恋しいですか?

13
mrki

このシナリオでミドルウェアを忘れた場合、これでうまくいきます。

meta = {'dont_redirect': True,'handle_httpstatus_list': [302]}

とはいえ、リクエストを生成するときにメタパラメータを含める必要があります。

yield Request(item['link'],meta = {
                  'dont_redirect': True,
                  'handle_httpstatus_list': [302]
              }, callback=self.your_callback)
12
mrki

Webブラウザで正常に読み込まれるページからホームページまたは固定ページにリダイレクトするなどの説明できない_302_応答は、通常、望ましくないアクティビティに対するサーバー側の対策を示します。

クロール速度を下げるか、スマートプロキシ(例: Crawlera )またはプロキシローテーションサービスを使用して、そのような応答を受け取ったときにリクエストを再試行する必要があります。

このような応答を再試行するには、ソースリクエストのmetaに_'handle_httpstatus_list': [302]_を追加し、コールバックで_response.status == 302_かどうかを確認します。そうである場合は、response.request.replace(dont_filter=True)を生成してリクエストを再試行します。

再試行するときは、特定のURLの最大再試行回数をコードで制限する必要もあります。再試行を追跡するために辞書を保持できます。

_class MySpider(Spider):
    name = 'my_spider'

    max_retries = 2

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.retries = {}

    def start_requests(self):
        yield Request(
            'https://example.com',
            callback=self.parse,
            meta={
                'handle_httpstatus_list': [302],
            },
        )

    def parse(self, response):
        if response.status == 302:
            retries = self.retries.setdefault(response.url, 0)
            if retries < self.max_retries:
                self.retries[response.url] += 1
                yield response.request.replace(dont_filter=True)
            else:
                self.logger.error('%s still returns 302 responses after %s retries',
                                  response.url, retries)
            return
_

シナリオによっては、このコードを ダウンローダーミドルウェア に移動することをお勧めします。

2
Gallaecio

このリダイレクトコードをmiddleware.pyファイルに追加し、これをsettings.pyに追加しました。

DOWNLOADER_MIDDLEWARES_BASE は、RedirectMiddlewareがデフォルトですでに有効になっていることを示しているため、何をしたかは問題ではありません。

リダイレクトされるのではなく、GETURLにリクエストを送信したい。

どうやって?サーバーは、GETリクエストに対して302で応答します。同じURLでもう一度GETを実行すると、リダイレクトされます。

何を達成しようとしていますか?

リダイレクトされないようにする場合は、次の質問を参照してください。

1
warvariuc

Settings.pyでREDIRECT_ENABLEDをFalseに設定すると、 RedirectMiddleware を無効にできます。

1
Steven Almeroth

HTTPCACHE_ENABLED = Trueを使用すると、リダイレクトの無限ループに問題がありました。 HTTPCACHE_IGNORE_HTTP_CODES = [301,302]を設定することで、問題を回避することができました。

1
Ivan Chaer