【问题标题】:Scrapy: return FormRequest in Downloader MiddlewareScrapy:在下载器中间件中返回 FormRequest
【发布时间】:2020-05-05 06:36:12
【问题描述】:

我正在抓取的网站有时会重定向到带有我想在下载器中间件中处理的表单的页面。这个想法是每次发生这种重定向时,它都会自动提交表单并检索结果。我的中间件看起来像:

from scrapy import FormRequest

class SubmitFormMiddleware:
    def process_response(self, request, response, spider):
        if response.css('form.loginbox').getall():
            post_form_url = response.css('form.loginbox::attr(action)').get()
            return FormRequest(url=response.urljoin(post_form_url),
                                     formdata={'username': 'my_username',
                                               'password': 'my_password',
                                               'data_selection': 'all'
                                               },
                                     method='POST',
                                     dont_filter=True)
        else:
            return response

这不起作用,因为我没有定义任何回调(我不应该因为我在中间件中):

NotImplementedError: DefaultSpider.parse callback is not defined

如果我只想返回一个请求,我会得到类似的东西:

redirected = request.replace(url=response.urljoin(post_form_url))
return self._redirect(redirected, request, spider, response.status)

但这不适用于提交表单。有人知道在下载器中间件中使用 FormRequest 的“Scrapy-thonic”方式是什么吗?

【问题讨论】:

  • 我似乎无法重现该错误,我可以完全按照您编写的方式生成 FormRequest。您确定错误与中间件有关,而且您不只是缺少蜘蛛中的 parse 方法吗?
  • 我的蜘蛛中确实有一个解析功能。但是,目前我正在调用scrapy shell "my_website.com",所以我的蜘蛛没有使用,但中间件是。
  • @WimHermans,是否可以在FormRequest 中添加类似callback=response.request.callback 的内容?

标签: python scrapy middleware


【解决方案1】:

我设法通过以下方式解决了这个问题:

from scrapy import FormRequest

class SubmitFormMiddleware:
    def process_response(self, request, response, spider):
        if response.css('form.loginbox').getall():
            post_form_url = response.css('form.loginbox::attr(action)').get()
            form_request_handle = FormRequest(url=response.urljoin(post_form_url),
                                     formdata={'username': 'my_username',
                                               'password': 'my_password',
                                               'data_selection': 'all'
                                               },
                                     method='POST',
                                     dont_filter=True)
            return request.replace(url=form_request_handle.url,
                                     method='POST',
                                     body=form_request_handle.body,
                                     headers=form_request_handle.headers,
                                     dont_filter=True)
        else:
            return response

虽然这可行,但我仍然对解决在中间件中提交FormRequest 的“scrapy-thonic”方式感到好奇。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-25
    • 1970-01-01
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多