【问题标题】:Unable to force scrapy to make a callback using the url that got redirected无法强制scrapy使用重定向的url进行回调
【发布时间】:2020-04-07 16:01:35
【问题描述】:

我创建了一个 python 脚本,使用 scrapy 来抓取某个网页中的一些可用信息。问题是我尝试使用的链接经常被重定向。但是,当我尝试使用请求几次时,我得到了所需的内容。

如果是scrapy,我无法重复使用该链接,因为无论我尝试多少次,我发现它都会重定向。我什至可以使用 response.meta.get("redirect_urls")[0] 捕获主 url,这意味着在 parse 方法中递归使用。但是,它总是被重定向,因此callback 没有发生。

这是我目前的尝试 (the link used within the script is just a placeholder):

import scrapy
from scrapy.crawler import CrawlerProcess

class StackoverflowSpider(scrapy.Spider):

    handle_httpstatus_list = [301, 302]
    name = "stackoverflow"
    start_url = 'https://stackoverflow.com/questions/22937618/reference-what-does-this-regex-mean'

    def start_requests(self):
        yield scrapy.Request(self.start_url,meta={"lead_link":self.start_url},callback=self.parse)


    def parse(self,response):

        if response.meta.get("lead_link"):
            self.lead_link = response.meta.get("lead_link")
        elif response.meta.get("redirect_urls"):
            self.lead_link = response.meta.get("redirect_urls")[0]

        try:
            if response.status!=200 :raise
            if not response.css("[itemprop='text'] > h2"):raise
            answer_title = response.css("[itemprop='text'] > h2::text").get()
            print(answer_title)

        except Exception:
            print(self.lead_link)
            yield scrapy.Request(self.lead_link,meta={"lead_link":self.lead_link},dont_filter=True, callback=self.parse)


if __name__ == "__main__":
    c = CrawlerProcess({
        'USER_AGENT': 'Mozilla/5.0',
    })
    c.crawl(StackoverflowSpider)
    c.start()

问题:如何强制 scrapy 使用重定向的 url 创建 callback

【问题讨论】:

  • 您还想要原始链接和重定向链接的响应吗?或者您想在可数重定向后获得引导链接的响应?要不然是啥?我试图弄清楚究竟是什么目的。
  • 来自原始链接,即使它被重定向。
  • 那么为什么不在解析回调中禁用重定向呢?您需要重定向 URL 中的任何内容吗?
  • 可以分享链接吗?
  • 您的代码似乎已经产生了对原始 URL 的新请求。我不明白你在问什么。

标签: python python-3.x redirect web-scraping scrapy


【解决方案1】:

您可能想查看this
如果您需要防止重定向,可以通过请求元:

request = scrapy.Request(self.start_url,meta={"lead_link":self.start_url},callback=self.parse)
request.meta['dont_redirect'] = True
yield request

根据文档,这是一种停止重定向的方法。

【讨论】:

  • 我并不是要阻止重定向。我已经知道那个关键字了。如果我按照您建议的方式进行,脚本将优雅地忽略它。我正在尝试的是重用该 url 来获得响应。顺便说一句,这就是他们的文档所说的 - If Request.meta has dont_redirect key set to True, the request will be ignored by this middleware
【解决方案2】:

据我了解,您希望抓取一个链接,直到它停止重定向并最终获得 http 状态 200

如果是,那么您必须首先从您的代码中删除 handle_httpstatus_list = [301, 302] 然后在middlewares.py中创建一个CustomMiddleware

class CustomMiddleware(object):

    def process_response(self, request, response, spider):

        if not response.css("[itemprop='text'] > h2"):
            logging.info('Desired text not found so re-scraping' % (request.url))
            req = request.copy()
            request.dont_filter = True

            return req
        if response.status in [301, 302]:
            original_url = request.meta.get('redirect_urls', [response.url])[0]
            logging.info('%s is redirecting to %s, so re-scraping it' % (request._url, request.url))
            request._url = original_url
            request.dont_filter = True

            return request

        return response

那么你的蜘蛛应该看起来像这样

class StackoverflowSpider(scrapy.Spider):

    name = "stackoverflow"
    start_url = 'https://stackoverflow.com/questions/22937618/reference-what-does-this-regex-mean'

    custom_settings = {
        'DOWNLOADER_MIDDLEWARES': {
            'YOUR_PROJECT_NAME.middlewares.CustomMiddleware': 100,
        }
    }

    def start_requests(self):
        yield scrapy.Request(self.start_url,meta={"lead_link":self.start_url},callback=self.parse)

    def parse(self,response):

        answer_title = response.css("[itemprop='text'] > h2::text").get()
        print(answer_title)

如果你告诉我你正在抓取哪个网站,那么我可以帮助你,你也可以给我发电子邮件,这在我的个人资料中

【讨论】:

  • 终于有人能理解我想要达到的目标了。感谢 umair 的回答。如果我在实施它时遇到困难,我会告诉你的。再次感谢。
  • @MITHU 当然,如果您有任何问题,请告诉我
猜你喜欢
  • 1970-01-01
  • 2014-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-05
  • 2011-08-29
  • 1970-01-01
相关资源
最近更新 更多