【发布时间】:2014-03-05 15:22:21
【问题描述】:
免责声明:我对 Scrapy 还很陌生。
直截了当地提出我的问题:如何从页面上的链接中检索 Item 属性并将结果返回到同一个 Item 中?
给定以下示例蜘蛛:
class SiteSpider(Spider):
site_loader = SiteLoader
...
def parse(self, response):
item = Place()
sel = Selector(response)
bl = self.site_loader(item=item, selector=sel)
bl.add_value('domain', self.parent_domain)
bl.add_value('origin', response.url)
for place_property in item.fields:
parse_xpath = self.template.get(place_property)
# parse_xpath will look like either:
# '//path/to/property/text()'
# or
# {'url': '//a[@id="Location"]/@href',
# 'xpath': '//div[@class="directions"]/span[@class="address"]/text()'}
if isinstance(parse_xpath, dict): # place_property is at a URL
url = sel.xpath(parse_xpath['url_elem']).extract()
yield Request(url, callback=self.get_url_property,
meta={'loader': bl, 'parse_xpath': parse_xpath,
'place_property': place_property})
else: # parse_xpath is just an xpath; process normally
bl.add_xpath(place_property, parse_xpath)
yield bl.load_item()
def get_url_property(self, response):
loader = response.meta['loader']
parse_xpath = response.meta['parse_xpath']
place_property = response.meta['place_property']
sel = Selector(response)
loader.add_value(place_property, sel.xpath(parse_xpath['xpath'])
return loader
我正在针对多个站点运行这些蜘蛛,其中大多数都在一个页面上拥有我需要的数据,并且运行良好。但是,某些网站在子页面上具有某些属性(例如,“获取路线”链接中存在的“地址”数据)。
“yield Request”行确实是我遇到问题的地方。我看到这些项目通过管道移动,但它们缺少在其他 URL 中找到的那些属性(IOW,那些到达“yield Request”的属性)。 get_url_property 回调基本上只是在新的 response 变量中查找 xpath,并将其添加到项目加载器实例中。
有没有办法做我正在寻找的事情,或者有更好的方法吗?我想避免进行同步调用来获取我需要的数据(如果这甚至可能在这里),但如果这是最好的方法,那么也许这就是正确的方法。谢谢。
【问题讨论】:
-
parse() 如果未完全填充,则不应生成项目。应该将部分填充的项目传递给 get_url_property 并且应该从那里返回/生成。另见:stackoverflow.com/questions/9334522/…
-
我明白这一点,但我怎样才能得到一个 Request 对象来解析和处理回调而不从 parse() 产生?我也不能保证每个项目都会涉及请求其他 URL。他们中的大多数不会。
-
也许你应该看看 CrawlSpider。然后,您可以通过添加回调函数来设置蜘蛛应如何处理不同链接的一些规则。
-
我试过 CrawlSpider,但也适用类似的规则。项目仍然是分开处理的,在某些情况下,我必须通过多个 URL 将单个项目传递到链中。无论哪种方式,我都阅读了@JanWrobel 在其他地方发布的评论,这给了我一个想法。这是希望......