Python 回调之间项装入器的疑难解答
为了理解中的“幼稚方法”示例 我正试图复制这段代码。我们的想法是在每个字段都来自不同网站的地方填充一个项目 我试图理解为什么在运行下面的代码时会出现以下行为,并使用Python 回调之间项装入器的疑难解答,python,csv,scrapy,web-crawler,Python,Csv,Scrapy,Web Crawler,为了理解中的“幼稚方法”示例 我正试图复制这段代码。我们的想法是在每个字段都来自不同网站的地方填充一个项目 我试图理解为什么在运行下面的代码时会出现以下行为,并使用scrapy crawl compSpider-o prices.csv将结果导出到csv文件中 该代码实际上用相关价格填充nic_价格,但对tester_价格的填充方式不同 我认为应该这样做,因为item loader对象在请求元字段中从创建item loader对象的第一个回调[firstRequest]传递到第二个回调[pars
scrapy crawl compSpider-o prices.csv
将结果导出到csv文件中
该代码实际上用相关价格填充nic_价格,但对tester_价格的填充方式不同
我认为应该这样做,因为item loader对象在请求元字段中从创建item loader对象的第一个回调[firstRequest]传递到第二个回调[parseDescription1],在第二个回调[parseDescription1]中item loader对象最终加载到一个item中
我已经测试了css选择器的工作。有人能帮我理解为什么我会有这种行为吗
项目申报
蜘蛛代码
css选择器是“确实可以工作”。问题存在于itemloader变量l中,您正在该变量中保存meta dict,它指向来自firstRequest回调的响应,而不是指向此css选择器可以工作的parseDescription1回调 'div.price-breakdown div.price-unclused-tax span.price::text' 要解决这个问题,只需创建一个新的itemloaderparseDescription1,或者更好地加载项目本身,而不是在元目录中加载它的加载程序,如下所示
def firstRequest(self, response):
l = ItemLoader(item=ProductItem(), response=response)
l.add_css('nic_price', 'div.product-info p.product-price span[itemprop="price"]::text')
yield Request('https://www.tester.co.uk/test-safe-pen-co-meter',
meta={'item': l.load_item()},
callback=self.parseDescription1)
def parseDescription1(self, response):
# Recover item
item = response.meta['item']
l = ItemLoader(item=ProductItem(), response=response)
# Use just as before
l.add_css('tester_price', 'div.price-breakdown div.price-excluding-tax span.price::text')
l.add_value('nic_price', item['nic_price'])
yield l.load_item()
最近,我遇到了同样的问题。尝试使用两种方法,但每种方法都有很大的缺点:
add_value()
引入了双重处理值的问题(通过输入和输出处理器),这使得设计那些使代码更难读取和维护的处理器变得更加困难scrapy.loader.ItemLoader
源代码(非常小和简单的代码,顺便说一下)中找到的是它的parent
关键字参数,它允许您传递parent ItemLoader并将其所有值复制到新的ItemLoader
以下是修改后的parseDescription1
:
def parseDescription1(自我,响应):
#恢复项目(加载器)
loader=response.meta['loader']
如果响应。正文:
loader=ItemLoader(item=ProductItem(),response=response,parent=loader)
#照常使用
tester\u loader.add\u css('tester\u price','div.price-breakdown div.price-excluding-tax span.price::text'))
产量加载器。加载_项()
scrapy crawl
结果:
2016-11-01 10:48:50[scrapy]调试:爬网(200)(参考:无)
2016-11-01 10:48:50[scrapy]调试:爬网(200)(参考:无)
2016-11-01 10:48:50[scrapy]调试:爬网(200)(参考:无)
2016-11-01 10:48:51[scrapy]调试:爬网(200)(参考:https://www.shop.niceic.com/6559-megger-mft1711-multifunction-tester-1008-121)
2016-11-01 10:48:51[刮伤]调试:刮伤自
{'nic_price':[u'\xa3509.00'],
“测试仪价格”:[u'\n\t\t\xa349.00\n\t\t']}
我的程序的目标是通过从不同站点获取每个属性来生成项目。我试图实现您的代码,但随后我分别生成了“l”和“l2”项加载器,这将产生两个项。我正在研究一种解决方法,欢迎提供任何帮助。解决此问题的方法有很多,一种简单的方法是在metameta={'item':l.load_item(),
then中加载项本身,而不是它的加载器,在parseDescription1中,从元目录中获取项目并将nic_价格作为值添加到item=response.meta['item']
l.add_值('nic_价格',item['nic_价格])
我最终传递的是项目,而不是项目加载器。在每个链式解析函数中,我都添加了项的一个属性。我刚刚发现用新的变量覆盖加载器变量更好。也仅当响应有主体
成员时才执行此操作。有点编辑代码。我得到一个错误:keyrerror:loader=response.meta['loader']
上使用Scrapy 1.4.0的“loader'
。
import scrapy
from scrapy.http import Request
from scrapy.loader import ItemLoader
from comparator.items import ProductItem
class Compspider(scrapy.Spider):
name = "compSpider"
#start_urls = ( 'https://www.shop.niceic.com/', )
def start_requests(self):
yield Request(
'https://www.shop.niceic.com/6559-megger-mft1711-multifunction-tester-1008-121', callback=self.firstRequest)
def firstRequest(self, response):
l = ItemLoader(item=ProductItem(), response=response)
l.add_css('nic_price', 'div.product-info p.product-price span[itemprop="price"]::text')
yield Request('https://www.tester.co.uk/test-safe-pen-co-meter', meta={'loader' : l}, callback= self.parseDescription1)
def parseDescription1(self, response):
# Recover item(loader)
l = response.meta['loader']
# Use just as before
l.add_css('tester_price', 'div.price-breakdown div.price-excluding-tax span.price::text')
yield l.load_item()
def firstRequest(self, response):
l = ItemLoader(item=ProductItem(), response=response)
l.add_css('nic_price', 'div.product-info p.product-price span[itemprop="price"]::text')
yield Request('https://www.tester.co.uk/test-safe-pen-co-meter',
meta={'item': l.load_item()},
callback=self.parseDescription1)
def parseDescription1(self, response):
# Recover item
item = response.meta['item']
l = ItemLoader(item=ProductItem(), response=response)
# Use just as before
l.add_css('tester_price', 'div.price-breakdown div.price-excluding-tax span.price::text')
l.add_value('nic_price', item['nic_price'])
yield l.load_item()