scrapy 我如何提取数据并将其附加到当前对象中?

voase2hg  于 2022-11-09  发布在  其他
关注(0)|答案(1)|浏览(123)

所以我的问题是:我有一个产品列表的网页。每个产品都有很多定义在每个div的属性中的东西。但是,其中一个字段是模糊的,所以我决定打开产品页面,并从那里得到它,我还发现了一些其他的数据,我认为可能是有用的,在我的分析。但是,当我合并数据,一些列是相同的,而其他似乎是更新。
下面是代码:

import scrapy
from scrapy.utils.response import open_in_browser

class getSalesData(scrapy.Spider):
    name = 'getsalesdata'

    start_urls = ['https://link']

    def __init__(self):
        self.params = ['data-id-cod', 'id', 'data-name','data-area' ,'data-zone' ,'data-items','data-ssellertype' ,
                       'data-surface' ,'price' ,'tva' ,'mobile-container-url']

        self.item = { "id_cod"              : 'null',
                      "id"                  : 'null',
                      "tip_prop"            : 'null',
                      "area"                : 'null',
                      "zone"                : 'null',
                      "no_items"            : 'null',
                      "seller_type"         : 'null',
                      "surface"             : 'null',
                      "surface_orig"        : 'null',
                      "price"               : 'null',
                      "currency"            : 'null',
                      "url"                 : 'null'
        }

        self.columns = { "data-id-cod"          : 'id_cod',
                         "id"                   : 'id',
                         "data-name"            : 'tip_prop',
                         "data-area"            : 'area',
                         "data-zone"            : 'zone',
                         "data-items"           : 'nr_items',
                         "data-ssellertype"     : 'seller_type',
                         "data-surface"         : 'surface',
                         "price"                : 'price',
                         "tva"                  : 'valuta',
                         "mobile-container-url" : 'url'
        }

    def parse(self, response):
        item = self.item
        for listing in response.css("div.box-an"):
            if not 'box-an ' in listing.attrib['class']:
                for parameter in self.params:
                    if parameter in ['price', 'tva']:
                        item[self.columns[parameter]] = \
                            (listing.css('span.' + parameter + '::text').get()).replace('.','') \
                                if (parameter in listing.get()) else item[self.columns[parameter]]

                    elif parameter in 'mobile-container-url':
                        url = listing.css('a.visible-xs.' + parameter).attrib['href'] \
                                if (parameter in listing.get()) else item[self.columns[parameter]]

                        #self.logger.info('----->>> At URL : ' + url)

                        item[self.columns[parameter]] = url

                    elif parameter in 'data-surface':
                        item['surface'] = str(int(listing.attrib[parameter])/100) \
                            if (int(listing.attrib[parameter])>1000) else listing.attrib[parameter]
                        item['surface_orig'] = listing.attrib[parameter] \
                            if (parameter in listing.get()) else item[self.columns[parameter]]

                    else:
                        item[self.columns[parameter]] = \
                            listing.attrib[parameter] if (parameter in listing.get()) else item[self.columns[parameter]]

            request = scrapy.Request(url=item['url'],
                                     callback=self.parseNextPage,
                                     meta={'item' : item})

            yield request

    def parseNextPage(self, response):
        item = response.meta['item']

        self.logger.info('Running on : ' + item['url'])

        #for spec in response.css('li.list-group-item.specificatii-oferta__lista--item'):
        for spec in response.css('ul.list-tab'):
            for lst in spec.css('li'):
                field = lst.css('li::text').get()
                #self.logger.info('Adding ' + field + '\n')
                item[field] = lst.css('span::text').get()

        return item

以下是数据(请参见带星号的相同项目):

id_cod          id          tip_prop    no_items surface    surface_all

* A2Q00LMBUS9    *XA2Q0001E  *prodType1  2        41,21 mp   *46.89 mp
* A2Q00LMBUS9    *XA2Q0001E  *prodType1  3        140 mp     *46.89 mp

我有一种感觉,我不明白如何自我。项目是更新和一些数据是从以前的运行被保留,也许?
更新:这是奇怪的。如果我使用这个代码:

request = scrapy.Request(url=item['url'],
                             callback=self.parseNextPage,
                             meta={'item' : {'id'     : item['id'] ,
                                             'id_cod' : item['id_cod'],
                                             'area'  : item['area'],
                                             'nr_items' : item['nr_items'],
                                             'seller_type'      : item['seller_type'],
                                             'surface' : item['suprafata'],
                                             'tip_prop' : item['tip_prop'],
                                             'url'             : item['url'],
                                             'currency'          : item['valuta'],
                                             'area'            : item['zona']
                                             }
                                   }
                             )

它工作正常。但如果我使用以下代码:

request = scrapy.Request(url=item['url'],
                         callback=self.parseNextPage,
                         meta={'item' : item})

它不再起作用了。项和我上面传递的字典是相同的。

raogr8fs

raogr8fs1#

因为item作为引用传递给Request的 meta,并且它所引用的内存在所有产品之间重用,所以它一直被覆盖。
要解决此问题,请删除在构造函数中声明self.item,并在循环中创建新项:

...    
def init_item(self):
    return { "id_cod"              : 'null',
             "id"                  : 'null',
             "tip_prop"            : 'null',
             "area"                : 'null',
             "zone"                : 'null',
             "no_items"            : 'null',
             "seller_type"         : 'null',
             "surface"             : 'null',
             "surface_orig"        : 'null',
             "price"               : 'null',
             "currency"            : 'null',
             "url"                 : 'null'
    }

def parse(self, response):
    for listing in response.css("div.box-an"):
        item = self.init_item()
        if not 'box-an ' in listing.attrib['class']:
...

相关问题