如何提取数据并将其附加到 scrapy 中的当前对象?
How can I extract data and append it to current object in scrapy?
所以我的问题是:
我有一个包含产品列表的网页。
每个产品在每个 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
我感觉我不明白 self.item 是如何更新的,一些数据是从以前的 运行 中保留下来的,也许吧?
更新:
这很奇怪。
如果我使用此代码:
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})
它不再起作用了。 Item 和我上面传递的字典是一样的。
因为 item
作为引用传递给 Request 的元数据,并且它所引用的内存在所有产品之间重复使用,所以一直被覆盖。
要修复在构造函数中删除声明 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']:
...
所以我的问题是: 我有一个包含产品列表的网页。 每个产品在每个 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
我感觉我不明白 self.item 是如何更新的,一些数据是从以前的 运行 中保留下来的,也许吧?
更新: 这很奇怪。 如果我使用此代码:
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})
它不再起作用了。 Item 和我上面传递的字典是一样的。
因为 item
作为引用传递给 Request 的元数据,并且它所引用的内存在所有产品之间重复使用,所以一直被覆盖。
要修复在构造函数中删除声明 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']:
...