Python Scrapy请求不回调

Python Scrapy请求不回调,python,web-scraping,request,scrapy,scrapy-spider,Python,Web Scraping,Request,Scrapy,Scrapy Spider,我试图创建一个spider,它从csv(两个链接和每行一个名称)获取数据,并从每个链接中提取一个简单元素(价格),为每行返回一个项目,项目名称为csv中的名称,以及两个提取的价格(每个链接一个) 所有操作都按预期进行,除了这样一个事实,即不是返回价格,而是从每个请求的回调函数返回价格,而是得到如下请求对象: 回调函数根本不会被调用,这是为什么 这是蜘蛛: f = open('data.csv') f_reader = csv.reader(f) f_data = list(f_reader)

我试图创建一个spider,它从csv(两个链接和每行一个名称)获取数据,并从每个链接中提取一个简单元素(价格),为每行返回一个项目,项目名称为csv中的名称,以及两个提取的价格(每个链接一个)

所有操作都按预期进行,除了这样一个事实,即不是返回价格,而是从每个请求的回调函数返回价格,而是得到如下请求对象:

回调函数根本不会被调用,这是为什么

这是蜘蛛:

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

提前感谢您的帮助

TL;DR:当您应该生成项或请求时,您正在生成一个包含请求对象的项


长版本:
爬行器中的解析方法应该返回
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
class ProductSpider(scrapy.Spider):
# 
def解析(自我,响应):
对于解析的_数据中的产品:
项目=产品()
项目['name']=产品[0]
#携带下一个你想在meta中爬行的url
#把你的东西放在meta里
屈服请求(产品[1],self.parse_优先,
meta={“product3”:产品[2],“item”:item})
def parse_first(自我,响应):
#检索在parse()func中创建的项目
item=response.meta['item']
#加满
digits=response.css('.price_info.price span').extract()
小数=response.css('.price\u info.price.price\u demicals').extract()
项目['first_price']=浮动(str(数字)+.'.+str(小数))
#从元数据中检索下一个url
#将您的项目转到下一个url
屈服请求(response.meta['product3'],self.parse_秒,
meta={“item”:item})
def parse_秒(自我,响应):
#再次检索您的项目
item=response.meta['item']
#加满
digits=response.css('.lr prod pricebox price.lr prod pricebox price primary
span[itemprop=“price”]”)。摘录()
项目['secodn_price']=位数
#最后在3次请求后返回物品!
收益项目

TL;DR:当您应该生成项或请求时,您正在生成一个包含请求对象的项


长版本:
爬行器中的解析方法应该返回
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
class ProductSpider(scrapy.Spider):
# 
def解析(自我,响应):
对于解析的_数据中的产品:
项目=产品()
项目['name']=产品[0]
#携带下一个你想在meta中爬行的url
#把你的东西放在meta里
屈服请求(产品[1],self.parse_优先,
meta={“product3”:产品[2],“item”:item})
def parse_first(自我,响应):
#检索在parse()func中创建的项目
item=response.meta['item']
#加满
digits=response.css('.price_info.price span').extract()
小数=response.css('.price\u info.price.price\u demicals').extract()
项目['first_price']=浮动(str(数字)+.'.+str(小数))
#从元数据中检索下一个url
#将您的项目转到下一个url
屈服请求(response.meta['product3'],self.parse_秒,
meta={“item”:item})
def parse_秒(自我,响应):
#再次检索您的项目
item=response.meta['item']
#加满
digits=response.css('.lr prod pricebox price.lr prod pricebox price primary
span[itemprop=“price”]”)。摘录()
项目['secodn_price']=位数
#最后在3次请求后返回物品!
收益项目

有点离题,但你不应该像那样使用全局变量,这样写入文件也是个坏主意。Scrapy可以通过
Scrapy crawl spider-o output.csv
自动生成
csv
?我知道这是个坏习惯,但我不知道该怎么做。。CSV仅用于读取现有文件。我使用openpyxl导出到excelAh,我知道你想在这里做什么。为什么不使用简单的实例变量呢?在注释中显示代码确实很难,但您应该研究的是
\uuu init\uuu
在python中是如何工作的,以及什么是实例和类变量。有点离题,但您不应该像这样使用全局变量,这样写入文件也是一个坏主意。s