使用 Scrapy 登录 EventBrite

Logging into EventBrite with Scrapy

我想了解更多关于如何使用 Scrapy 登录网站的信息。我查看了一些文档和教程,最后找到了 Using FormRequest.from_response() to simulate a user login. Using Chrome dev tools, I look at the "login" response after logging in from the page https://eventbrite.ca/signin/login

可能需要注意的一些重要事项是,当尝试在浏览器中登录时,网页会将您定向到 https://eventbrite.ca/signin,您可以在其中输入电子邮件并提交表格。

这会向 https://www.eventbrite.ca/api/v3/users/lookup/ with just the email provided, and if all is dandy, the webpage will use JS to "redirect" you to https://eventbrite.ca/signin/login 发送 POST 请求并生成 "password" 输入元素。

填写密码并点击表单按钮后,如果成功,它将重定向+生成登录响应作为 POST 发送到 https://www.eventbrite.ca/ajax/login/ 的结果,电子邮件,pw,和一些其他信息(可以在我的代码片段中找到)。

首先,我尝试逐步执行此操作:从 .ca/signup 开始,将 POST 与我的电子邮件一起发送到查找端点,但我收到 401 错误。接下来我尝试直接转到 .ca/signup/login,并提交在登录响应中找到的所有信息,但收到 403.

我确定我一定遗漏了一些东西,虽然看起来我正在 POST 访问正确的 URL 并找到正确的表格,但无法弄清楚还剩下什么。同样在尝试了一段时间之后,想知道 Selenium 是否会提供更好的替代方法来登录并在包含大量 JS 的网页上执行一些自动化操作。任何帮助表示赞赏。

def login(self, response):
    yield FormRequest.from_response(
        response,
        formxpath="//form[(@novalidate)]",
        url='https://www.eventbrite.ca/ajax/login/',
        formdata={
            'email': 'email@email.com',
            'password': 'password',
            'forward':'',
            'referrer': '/',
            'pckg': '',
            'stld': ''
        }, 
        callback=self.begin_event_parse
    )

.ca/signup/登录尝试 (403):

 [scrapy.core.engine] DEBUG: Crawled (403) <POST https://www.eventbrite.ca/ajax/login/> (referer: https://www.eventbrite.ca/signin/login)

.ca/signup 尝试 (401):

[scrapy.core.engine] DEBUG: Crawled (401) <POST https://www.eventbrite.ca/api/v3/users/lookup/> (referer: https://www.eventbrite.ca/signin/login)

您的 headers 中似乎缺少 X-CSRFToken。此令牌用于保护资源免受 Cross-site 请求伪造。

在这种情况下,它是在 cookie 中提供的,您需要存储并传递它。

适合我的简单实现:

import re
import scrapy

class DarazspidySpider(scrapy.Spider):
    name = 'darazspidy'

    def start_requests(self):
        yield scrapy.Request('https://www.eventbrite.ca/signin/?referrer=%2F%3Finternal_ref%3Dlogin%26internal_ref%3Dlogin%26internal_ref%3Dlogin', callback=self.lookup)

    def lookup(self, response):
        yield scrapy.FormRequest(
            'https://www.eventbrite.ca/api/v3/users/lookup/',
            formdata={"email":"email@mail-v.net"},
            headers={'X-CSRFToken': self._get_xcsrf_token(response),},
            callback=self.login,
        )

    def _get_xcsrf_token(self, response):
        cookies = response.headers.getlist('Set-Cookie')
        cookie, = [c for c in cookies if 'csrftoken' in str(c)]
        self.token = re.search(r'csrftoken=(\w+)', str(cookie)).groups()[0]
        return self.token

    def login(self, response):
        yield scrapy.FormRequest(
            url='https://www.eventbrite.ca/ajax/login/',
            formdata={
                'email': 'email@mail-v.net',
                'password': 'pwd',
                'forward':'',
                'referrer': '/?internal_ref=login&internal_ref=login',
                'pckg': '',
                'stld': ''
            },             
            callback=self.parse,
            headers={'X-CSRFToken': self.token}
        )

    def parse(self, response):
        self.logger.info('Logged in!')

理想情况下,您希望创建一个中间件来为您完成这项工作。

一般来说,当您遇到这种行为时,您希望尽可能地模仿浏览器发送的内容,因此请仔细查看 headers 并尝试复制它们。