Nin*_*ina 12 python pipeline scrapy
我有一个Spider,它会抓取无法保存在一个项目类中的数据.
为了说明,我有一个配置文件项,每个配置文件项可能有未知数量的注释.这就是我想要实现Profile Item和Comment Item的原因.我知道我可以简单地通过使用yield将它们传递给我的管道.
但是,我不知道具有一个parse_item函数的管道如何处理两个不同的项类?
或者是否可以使用不同的parse_item函数?
或者我必须使用几个管道?
或者是否可以将Iterator写入Scrapy项目字段?
comments_list=[]
comments=response.xpath(somexpath)
for x in comments.extract():
comments_list.append(x)
ScrapyItem['comments'] =comments_list
Run Code Online (Sandbox Code Playgroud)
Rej*_*ted 12
默认情况下,每个项目都经过每个管道.
例如,如果您产生a ProfileItem和a CommentItem,它们都将通过所有管道.如果您有跟踪项类型的管道设置,那么您的process_item方法可能如下所示:
def process_item(self, item, spider):
self.stats.inc_value('typecount/%s' % type(item).__name__)
return item
Run Code Online (Sandbox Code Playgroud)
当一个ProfileItem通过时,'typecount/ProfileItem'会增加.当一个CommentItem通过时,'typecount/CommentItem'会增加.
但是,如果处理该项类型是唯一的,则可以通过在继续之前检查项类型来使一个管道句柄只有一种类型的项请求:
def process_item(self, item, spider):
if not isinstance(item, ProfileItem):
return item
# Handle your Profile Item here.
Run Code Online (Sandbox Code Playgroud)
如果您process_item在不同的管道中设置了上述两种方法,则该项目将遍历这两种方法,进行跟踪和处理(或在第二种方法中忽略).
此外,您可以使用一个管道设置来处理所有"相关"项:
def process_item(self, item, spider):
if isinstance(item, ProfileItem):
return self.handleProfile(item, spider)
if isinstance(item, CommentItem):
return self.handleComment(item, spider)
def handleComment(item, spider):
# Handle Comment here, return item
def handleProfile(item, spider):
# Handle profile here, return item
Run Code Online (Sandbox Code Playgroud)
或者,您可以使它更复杂,并开发一个类型委托系统,它加载类并调用默认处理程序方法,类似于Scrapy处理中间件/管道的方式.这取决于您需要它的复杂程度以及您想要做的事情.
定义多个项目当您导出数据时,如果它们具有关系(例如,配置文件1 - N注释),那么它是一个棘手的事情,并且您必须将它们一起导出,因为管道在不同时间处理了每个项目.此方案的另一种方法是定义自定义Scrapy字段,例如:
class CommentItem(scrapy.Item):
profile = ProfileField()
class ProfileField(scrapy.item.Field):
# your business here
Run Code Online (Sandbox Code Playgroud)
但鉴于您必须拥有2个项目的场景,强烈建议为这些类型的项目以及不同的导出器实例使用不同的管道,以便您在不同的文件中获取此信息(如果您使用的是文件):
settings.py
ITEM_PIPELINES = {
'pipelines.CommentsPipeline': 1,
'pipelines.ProfilePipeline': 1,
}
Run Code Online (Sandbox Code Playgroud)
pipelines.py
class CommentsPipeline(object):
def process_item(self, item, spider):
if isinstance(item, CommentItem):
# Your business here
class ProfilePipeline(object):
def process_item(self, item, spider):
if isinstance(item, ProfileItem):
# Your business here
Run Code Online (Sandbox Code Playgroud)
最直接的方法是让解析器包含两个子解析器,每个解析器对应一种数据类型。主解析器确定输入的类型并将字符串传递给适当的子例程。
第二种方法是按顺序包含解析器:一个解析配置文件并忽略其他所有内容;第二个解析 Comments 并忽略其他所有内容(与上面的原理相同)。
这会推动你前进吗?