scrapy中meta的一个坑点

scrapy的meta的作用就是在执行scrapy.Request()函数时把一些回掉函数中需要的数据传进去,meta必须是一个字典,在下一个函数中可以使用response.meta防问,这里需要注意的是,meta传递的数据是浅拷贝传递的,如果传递的数据是可变的数据类型,那么很容易造成数据不对应的错误,以下是本人在工作中的遇到此问题的代码片段:

    def parse_jinyan(self, response):
        '''评论页'''
        doctorId = response.xpath('//script').re('doctorId:"(\d+)"')
        if not doctorId:
            return
        base_url = 'https://m.haodf.com/ndoctor/ajaxshowlist?is2YearsAgo={params[is2YearsAgo]}&diseasename={params[diseasename]}&diseasekey={params[diseasekey]}&doctorPinyin={params[doctorPinyin]}&doctorId={params[doctorId]}&pinyinRef={params[pinyinRef]}&sn={params[sn]}&diseaseId={params[diseaseId]}&num={params[num]}&size={params[size]}&time={params[time]}&_t={params[_t]}'
        # url参数
        params = {
            'is2YearsAgo': '1',
            'diseasename': '全部',
            'diseasekey': 'all',
            'doctorPinyin': response.meta['doctorPinyin'],
            'doctorId': doctorId[0],
            'pinyinRef': response.meta['pinyinRef'],
            'sn': response.meta['sn'],
            'diseaseId': '',
            'num': '1',
            'size': '10',
            'time': '',
            '_t': str(int(time.time() * 1000))
        }
        # 两年前的评论
        if self.scope == 'allComment':
            yield scrapy.FormRequest(
                url=base_url.format(params=params),
                meta={'hid': response.meta['hid'], 'ddid': response.meta['ddid'], 'base_url': base_url,
                      'params': copy.deepcopy(params), 'num': 1},
                callback=self.parse_comment,
                errback=self.request_errback)
        # 两年内的评论
        is_twoyears = response.xpath('//ul[contains(@class,"vote-ul")]')
        if is_twoyears:
            params['is2YearsAgo'] = '0'
            for li in is_twoyears.xpath('./li[@class="vote-li js-vote-li " and not(@data-disease="all")]'):
                diseaseId = li.xpath('./@data-id').extract_first()
                diseasename = li.xpath('./@data-name').extract_first()
                diseasekey = li.xpath('./@data-disease').extract_first()
                params['diseasename'] = diseasename
                params['diseasekey'] = diseasekey
                params['diseaseId'] = diseaseId
                yield scrapy.FormRequest(
                    url=base_url.format(params=params),
                    meta={'hid': response.meta['hid'], 'ddid': response.meta['ddid'], 'base_url': base_url,
                          'params': copy.deepcopy(params), 'num': 1},
                    callback=self.parse_comment,
                    errback=self.request_errback)
        else:
            print '两年内没有获得评论'

以上要将params等信息传递到下一个解析方法,params是一个字典,字典是可变的数据类型,for循环中会对params字典进行修改,然后再进行传递,如果没有对params进行深拷贝的话,会造成params在下一个解析方法中出现数据不对应的情况,因为scrapy是将请求Request对象扔到队列中的,是一个异步采集框架,所以params如果是浅拷贝的话,只是拷贝了对象的引用而没有拷贝数据本身,当scrapy用请求对象发送请求并将返回结果给下一个解析方法后,接收到的meta里的数据是可以被操作修改的,所以params是会被for循环不断的修改,从而接收到的数据是被修改过后的数据。通过深拷贝可以解决该问题。

 

欢迎关注公众号:日常bug,每天写至少一篇技术文章,每天进步一点点。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值