首页 > 解决方案 > 刮印最后输出三遍而不是三遍

问题描述

我已经使用scrapy 编写了一个脚本来解析网站上的一些内容。要从该站点访问数据的相关部分,我需要在有效负载中使用一些 id。

我正在一个接一个地尝试在有效负载中使用这三个 id,如24842,1990220154. 但是,我正在尝试根据我使用的 id 检查有效负载是否已更新,但我注意到有效负载正在使用最后一个 id,如201543 次。

为了更清楚,我想得到如下输出:

{'language': 'en', 'region': 'ww', 'networks': 'Internet', '$top': '20', 'productNodePath': '/24842/'}
{'language': 'en', 'region': 'ww', 'networks': 'Internet', '$top': '20', 'productNodePath': '/19902/'}
{'language': 'en', 'region': 'ww', 'networks': 'Internet', '$top': '20', 'productNodePath': '/20154/'}

我得到的是:

{'language': 'en', 'region': 'ww', 'networks': 'Internet', '$top': '20', 'productNodePath': '/20154/'}
{'language': 'en', 'region': 'ww', 'networks': 'Internet', '$top': '20', 'productNodePath': '/20154/'}
{'language': 'en', 'region': 'ww', 'networks': 'Internet', '$top': '20', 'productNodePath': '/20154/'}

我试过:

import scrapy
from urllib.parse import urlencode
from scrapy.crawler import CrawlerProcess

class SiemensSpider(scrapy.Spider):
    name = 'siemens'

    start_link = "https://support.industry.siemens.com/webbackend/api/ProductSupport/ProductSearch?"

    payload = {
        'language': 'en',
        'region': 'ww',
        'networks': 'Internet',
        '$top': '20'
    }

    def start_requests(self):
        for item_id in ['24842','19902','20154']:
            self.payload['productNodePath'] = f"/{item_id}/" #should be updated here
            first_req = f'{self.start_link}{urlencode(self.payload)}'
            yield scrapy.Request(first_req,callback=self.parse)
        
    def parse(self,response):
        print(self.payload)

if __name__ == "__main__":
    c = CrawlerProcess({
        'USER_AGENT': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36',
        'LOG_LEVEL':'ERROR'
    })
    c.crawl(SiemensSpider)
    c.start()

我怎样才能实现第一个输出?

标签: pythonpython-3.xweb-scrapingscrapy

解决方案


在这种情况下,您必须deepcopy结合meta请求中的数据使用。

您正在获取蜘蛛的属性并仅覆盖其中一个值,因此您会得到问题中提到的重复数据。

工作示例:

import scrapy
from urllib.parse import urlencode
from scrapy.crawler import CrawlerProcess
from copy import deepcopy


class SiemensSpider(scrapy.Spider):
    name = 'siemens'

    start_link = "https://support.industry.siemens.com/webbackend/api/ProductSupport/ProductSearch?"

    payload = {
        'language': 'en',
        'region': 'ww',
        'networks': 'Internet',
        '$top': '20'
    }

    def start_requests(self):
        for item_id in ['24842', '19902', '20154']:
            data = deepcopy(self.payload)
            data['productNodePath'] = f"/{item_id}/"  # should be updated here
            first_req = f'{self.start_link}{urlencode(data)}'
            yield scrapy.Request(first_req, callback=self.parse, meta={'payload': data})

    def parse(self, response):
        payload = response.meta.get('payload')
        print(payload)


if __name__ == "__main__":
    c = CrawlerProcess({
        'USER_AGENT': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36',
        'LOG_LEVEL': 'ERROR'
    })
    c.crawl(SiemensSpider)
    c.start()

推荐阅读