【问题标题】:Scrapy request does not callbackScrapy请求不回调
【发布时间】:2016-11-21 09:06:09
【问题描述】:

我正在尝试创建一个蜘蛛,它从 csv 获取数据(每行两个链接和一个名称),并从每个链接中抓取一个简单的元素(价格),为每一行返回一个项目,该项目的name 是 csv 中的名称,以及两个抓取的价格(每个链接一个)。

一切都按预期工作,除了从每个请求的回调函数返回的价格,而不是返回价格,我得到一个像这样的请求对象:

https://link.com>..

回调函数根本没有被调用,这是为什么呢?

这是蜘蛛:

f = open('data.csv')
f_reader = csv.reader(f)
f_data = list(f_reader)

parsed_data = []

for product in f_data:
    product = product[0].split(';')
    parsed_data.append(product)

f.close()

class ProductSpider(scrapy.Spider):
    name = 'products'
    allowed_domains = ['domain1', 'domain2']

    start_urls = ["domain1_but_its_fairly_useless"]

    def parse(self, response):
        global parsed_data
        for product in parsed_data:

            item = Product()

            item['name'] = product[0]
            item['first_price'] = scrapy.Request(product[1], callback=self.parse_first)
            item['second_price'] = scrapy.Request(product[2], callback=self.parse_second)
            yield item


    def parse_first(self, response):
        digits = response.css('.price_info .price span').extract()
        decimals = response.css('.price_info .price .price_demicals').extract()
        yield float(str(digits)+'.'+str(decimals))

    def parse_second(self, response):
        digits = response.css('.lr-prod-pricebox-price .lr-prod-pricebox-price-primary span[itemprop="price"]').extract()
        yield digits

提前感谢您的帮助!

【问题讨论】:

  • 有点跑题了,但你不应该使用这样的全局变量,并且像这样写入文件也是一个坏主意。 Scrapy 可以自动生成csvscrapy crawl spider -o output.csv
  • 没有 global 怎么办?我知道这是个坏习惯,但我不知道该怎么做。CSV 仅用于读取现有文件。我使用 openpyxl 导出到 excel
  • 啊,我知道你想在这里做什么。为什么不使用简单的实例变量?在注释中显示代码确实很难,但您应该研究__init__ 在 python 中的工作方式以及实例和类变量是什么。

标签: python web-scraping request scrapy scrapy-spider


【解决方案1】:

TL;DR:当您应该产生 Item 或 Request 时,您正在产生一个包含 Request 对象的项目。


长版:
你的蜘蛛中的解析方法应该返回一个scrapy.Item - 在这种情况下,该爬网的链将停止并且scrapy 将输出一个项目或一个scrapy.Requests 在这种情况下,scrapy 将安排一个请求以继续该链。

Scrapy 是异步的,因此从多个请求创建一个项目意味着您需要将所有这些请求链接起来,同时将您的项目传送到每个项目并一点一点地填充它。 请求对象具有meta 属性,您可以在其中存储您想要的任何内容(非常多),它将被带到您的回调函数中。使用它来链接需要多个请求以形成单个项目的项目的请求是很常见的。

你的蜘蛛应该是这样的:

class ProductSpider(scrapy.Spider):
    # <...>
    def parse(self, response):
        for product in parsed_data:
            item = Product()
            item['name'] = product[0]
            # carry next url you want to crawl in meta
            # and carry your item in meta
            yield Request(product[1], self.parse_first,
                          meta={"product3": product[2], "item":item})  


    def parse_first(self, response):
        # retrieve your item that you made in parse() func
        item = response.meta['item']
        # fill it up
        digits = response.css('.price_info .price span').extract()
        decimals = response.css('.price_info .price .price_demicals').extract()
        item['first_price'] = float(str(digits)+'.'+str(decimals))
        # retrieve next url from meta
        # carry over your item to the next url
        yield Request(response.meta['product3'], self.parse_second,
                      meta={"item":item})


    def parse_second(self, response):
        # again, retrieve your item
        item = response.meta['item']
        # fill it up
        digits = response.css('.lr-prod-pricebox-price .lr-prod-pricebox-price-primary 
                              span[itemprop="price"]').extract()
        item['secodn_price'] = digits
        # and finally return the item after 3 requests! 
        yield item

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多