web-dev-qa-db-ja.com

認証された(ログインした)ユーザーセッションでScrapyを使用する

Scrapy docs には、Scrapyで認証済みセッションを使用する方法を示す次の例があります。

class LoginSpider(BaseSpider):
    name = 'example.com'
    start_urls = ['http://www.example.com/users/login.php']

    def parse(self, response):
        return [FormRequest.from_response(response,
                    formdata={'username': 'john', 'password': 'secret'},
                    callback=self.after_login)]

    def after_login(self, response):
        # check login succeed before going on
        if "authentication failed" in response.body:
            self.log("Login failed", level=log.ERROR)
            return

        # continue scraping with authenticated session...

私はそれが機能している、それは大丈夫です。しかし、私の質問はcontinue scraping with authenticated session、彼らは最後の行のコメントで言うように?

55
Herman Schaaf

上記のコードでは、認証に使用されているFormRequestにはafter_loginコールバックとして設定された関数。これは、after_login関数が呼び出され、ログイン試行が応答として取得したページが渡されます。

その後、特定の文字列(この場合は"authentication failed"。見つかった場合、クモは終了します。

さて、スパイダーがここまで到達すると、認証に成功したことがわかり、新しいリクエストの生成やデータのスクレイピングを開始できます。したがって、この場合:

from scrapy.selector import HtmlXPathSelector
from scrapy.http import Request

# ...

def after_login(self, response):
    # check login succeed before going on
    if "authentication failed" in response.body:
        self.log("Login failed", level=log.ERROR)
        return
    # We've successfully authenticated, let's have some fun!
    else:
        return Request(url="http://www.example.com/tastypage/",
               callback=self.parse_tastypage)

def parse_tastypage(self, response):
    hxs = HtmlXPathSelector(response)
    yum = hxs.select('//img')

    # etc.

here を見ると、スクレイピングの前に認証するクモの例があります。

この場合、parse関数(すべてのリクエストのデフォルトのコールバック)で処理します。

def parse(self, response):
    hxs = HtmlXPathSelector(response)
    if hxs.select("//form[@id='UsernameLoginForm_LoginForm']"):
        return self.login(response)
    else:
        return self.get_section_links(response)

そのため、要求が行われるたびに、ログインフォームが存在するかどうか応答がチェックされます。存在する場合、ログインする必要があることがわかります。そのため、関連する関数を呼び出します。存在しない場合は、応答からデータをスクレイピングする関数を呼び出します。

これが明確であることを願っています。他にご質問がある場合はお気軽にお問い合わせください。


編集:

さて、単一のリクエストを生成してそれをスクレイピングする以上のことをしたいのです。リンクをたどりたい。

そのために必要なことは、ページから関連リンクをスクレイプし、それらのURLを使用してリクエストを生成することです。例えば:

def parse_page(self, response):
    """ Scrape useful stuff from page, and spawn new requests

    """
    hxs = HtmlXPathSelector(response)
    images = hxs.select('//img')
    # .. do something with them
    links = hxs.select('//a/@href')

    # Yield a new request for each link we found
    for link in links:
        yield Request(url=link, callback=self.parse_page)

ご覧のとおり、ページ上のすべてのURLに対して新しいリクエストが生成され、それらのリクエストのそれぞれが、応答でこの同じ関数を呼び出すため、再帰的なスクレイピングが行われます。

上に書いたのはほんの一例です。ページを「クロール」したい場合は、手動で行うのではなく、 CrawlSpider を調べる必要があります。

66
Acorn