V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
viiii
V2EX  ›  问与答

[求助] Scrapy 报错 KeyError: 'item'

  •  
  •   viiii · 2019-08-19 23:39:41 +08:00 · 1666 次点击
    这是一个创建于 1927 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,在写爬虫时,碰到这个错误 使用的是 crawlspider 通用爬虫,下面是代码(先调用 parse_a,再调用 parse_b)

        name = 'crawl_spider'
        allowed_domains = ['baidu.com']
        start_urls = ['https://www.baidu.com']
    
        rules = (...)
        
    def parse_a(self,response)
    	...
        yield item  # item 定义省略
        yield scrapy.Request(url=url,callback=self.parse_b,meta={'item':item})
        
    def parse_b(self,response)
    	item = response.meta["item"]  # 获取 parse_a 传递过来的 item 对象
        print(item)
        ...
    
    

    运行代码后报错如下:

    Traceback (most recent call last):
      File "C:\Users\mypc\Anaconda3\lib\site-packages\scrapy\utils\defer.py", line 102, in iter_errback
        yield next(it)
      File "C:\Users\mypc\Anaconda3\lib\site-packages\scrapy\spidermiddlewares\offsite.py", line 29, in process_spider_output
        for x in result:
      File "C:\Users\mypc\Anaconda3\lib\site-packages\scrapy\spidermiddlewares\referer.py", line 339, in <genexpr>
        return (_set_referer(r) for r in result or ())
      File "C:\Users\mypc\Anaconda3\lib\site-packages\scrapy\spidermiddlewares\urllength.py", line 37, in <genexpr>
        return (r for r in result or () if _filter(r))
      File "C:\Users\mypc\Anaconda3\lib\site-packages\scrapy\spidermiddlewares\depth.py", line 58, in <genexpr>
        return (r for r in result or () if _filter(r))
      File "C:\Users\mypc\Anaconda3\lib\site-packages\scrapy\spiders\crawl.py", line 78, in _parse_response
        for requests_or_item in iterate_spider_output(cb_res):
      File "d:\Python_project\2019-08-18\novel\novel\spiders\crawl_spider", line 63, in parse_chapter_detail
        item = response.meta["item"]  # 获取前面传递过来的 item 对象
    KeyError: 'item'
    

    猜测可能是传递 item 哪里没搞对导致的错误

    PS:使用 crawlspider 这样传递 item 是否正确?如果不对,应该怎么在不同方法间传递 item 对象?

    第 1 条附言  ·  2019-08-20 12:18:26 +08:00

    parse_b 中打印了一下meta的信息, 如下所示:

    >>>print("meta info ----->")
    >>>print(response.meta)
    
    meta info ----->
    {'rule': 2, 'link_text': '第一千九百三十三章 转身', 'depth': 2, 'download_timeout': 180.0, 'download_slot': 'www.23us.so', 'download_latency': 0.23895788192749023}
    

    可能是前面parse方法传入的item没有存进去, 现在该怎么传递item? 更迷糊了...

    7 条回复    2019-08-21 09:25:09 +08:00
    warcraft1236
        1
    warcraft1236  
       2019-08-20 10:02:49 +08:00
    debug 看一下,怀疑 response 的 meta 里边没有 item
    viiii
        2
    viiii  
    OP
       2019-08-20 12:20:56 +08:00
    @warcraft1236 打印一下发现确实没有 item,已经在上面追加附言
    请问这里该怎么传递 item? 爬取的目标信息分布在不同级别的页面中,无法一次全部获取完整
    warcraft1236
        3
    warcraft1236  
       2019-08-20 13:15:29 +08:00
    首先,你这个 item 对应的 value,是要传递什么数据,如果是需要持久化的,应该用 pipeline
    warcraft1236
        4
    warcraft1236  
       2019-08-20 13:18:02 +08:00
    我记得 scrapy 官方的教程里边,meta 就是这么传递,你应该没写错,还是得 debug 一下,看看执行的时候发生了什么
    viiii
        5
    viiii  
    OP
       2019-08-20 15:04:37 +08:00
    @warcraft1236
    以采集某小说内容为例,
    首先在 parse_a 中获取 标题 /简介 /作者等信息, yield 给 pipeline 存到数据表 a 中; 再将 item 传递给 parse_b
    第二步, 获取章节正文,存到数据表 b 中 (由于章节正文页面不显示书籍标题,只有章节标题,所以存到表 b 中的时候,需要从 parse_a 里传递书籍标题到 parse_b 中)

    基本流程就是这个样子,用 crawlspider 第一次遇到这个情况
    viiii
        6
    viiii  
    OP
       2019-08-20 16:13:26 +08:00
    还有一点比较奇怪, 同样传递方式,在 spider (普通爬虫)里面就一切正常, 换到 crawlspider(通用爬虫)就报 KeyError 错误
    warcraft1236
        7
    warcraft1236  
       2019-08-21 09:25:09 +08:00
    @viiii 才注意到,我一般都是继承 spider,没继承过 crawlspider,不过感觉 meta 这块应该没有什么改变才是,你可以看看 crawlspider 的实现
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3813 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 10:31 · PVG 18:31 · LAX 02:31 · JFK 05:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.