Cod*_*eyB 72 python web-crawler scrapy
我有一个包含多个蜘蛛的scrapy项目.有什么方法可以定义哪些管道用于哪个蜘蛛?并非我所定义的所有管道都适用于每个蜘蛛.
谢谢
Ran*_*ngh 99
只需从主设置中删除所有管道,然后在蜘蛛内部使用它.
这将为每个蜘蛛定义用户的管道
class testSpider(InitSpider):
    name = 'test'
    custom_settings = {
        'ITEM_PIPELINES': {
            'app.MyPipeline': 400
        }
    }
mst*_*ger 35
基于Pablo Hoffman的解决方案,您可以在process_itemPipeline对象的方法上使用以下装饰器,以便它检查pipeline蜘蛛的属性是否应该执行.例如:
def check_spider_pipeline(process_item_method):
    @functools.wraps(process_item_method)
    def wrapper(self, item, spider):
        # message template for debugging
        msg = '%%s %s pipeline step' % (self.__class__.__name__,)
        # if class is in the spider's pipeline, then use the
        # process_item method normally.
        if self.__class__ in spider.pipeline:
            spider.log(msg % 'executing', level=log.DEBUG)
            return process_item_method(self, item, spider)
        # otherwise, just return the untouched item (skip this step in
        # the pipeline)
        else:
            spider.log(msg % 'skipping', level=log.DEBUG)
            return item
    return wrapper
为使此装饰器正常工作,spider必须具有一个管道属性,其中包含要用于处理项目的Pipeline对象的容器,例如:
class MySpider(BaseSpider):
    pipeline = set([
        pipelines.Save,
        pipelines.Validate,
    ])
    def parse(self, response):
        # insert scrapy goodness here
        return item
然后在一个pipelines.py文件中:
class Save(object):
    @check_spider_pipeline
    def process_item(self, item, spider):
        # do saving here
        return item
class Validate(object):
    @check_spider_pipeline
    def process_item(self, item, spider):
        # do validating here
        return item
所有Pipeline对象仍然应该在ITEM_PIPELINES中的设置中定义(按照正确的顺序 - 更改将很好,以便也可以在Spider上指定顺序).
eLR*_*uLL 12
这里给出的其他解决方案都很好,但我认为它们可能很慢,因为我们实际上并没有使用每个蜘蛛的管道,而是每次返回一个项目时检查是否存在管道(在某些情况下,这可能会达到百万).
完全禁用(或启用)每个蜘蛛的功能的好方法是使用custom_setting和from_crawler所有扩展,如下所示:
pipelines.py
from scrapy.exceptions import NotConfigured
class SomePipeline(object):
    def __init__(self):
        pass
    @classmethod
    def from_crawler(cls, crawler):
        if not crawler.settings.getbool('SOMEPIPELINE_ENABLED'):
            # if this isn't specified in settings, the pipeline will be completely disabled
            raise NotConfigured
        return cls()
    def process_item(self, item, spider):
        # change my item
        return item
settings.py
ITEM_PIPELINES = {
   'myproject.pipelines.SomePipeline': 300,
}
SOMEPIPELINE_ENABLED = True # you could have the pipeline enabled by default
spider1.py
class Spider1(Spider):
    name = 'spider1'
    start_urls = ["http://example.com"]
    custom_settings = {
        'SOMEPIPELINE_ENABLED': False
    }
当您检查时,我们已指定custom_settings将覆盖指定的内容settings.py,并且我们正在禁用SOMEPIPELINE_ENABLED此蜘蛛.
现在当你运行这个蜘蛛时,请检查以下内容:
[scrapy] INFO: Enabled item pipelines: []
现在scrapy已经完全禁用了管道,并没有为整个运行而烦恼.检查这也适用于scrapy extensions和middlewares.
Fra*_*ila 10
我至少可以想到四种方法:
scrapy settings在每次调用spider之间更改管道设置default_settings['ITEM_PIPELINES']命令类定义到您希望该命令的管道列表.见本例的第6行.process_item()检查它正在运行的蜘蛛是什么,如果该蜘蛛应该被忽略则不执行任何操作.请参阅使用每个蜘蛛资源的示例来帮助您入门.(这似乎是一个丑陋的解决方案,因为它紧密地耦合了蜘蛛和物品管道.你可能不应该使用这个.)您可以name在管道中使用spider 的属性
class CustomPipeline(object)
    def process_item(self, item, spider)
         if spider.name == 'spider1':
             # do something
             return item
         return item
以这种方式定义所有管道可以实现您想要的.
最简单有效的解决方案是在每个蜘蛛本身中设置自定义设置。
custom_settings = {'ITEM_PIPELINES': {'project_name.pipelines.SecondPipeline': 300}}
之后,您需要在 settings.py 文件中设置它们
ITEM_PIPELINES = {
   'project_name.pipelines.FistPipeline': 300,
   'project_name.pipelines.SecondPipeline': 400
}
这样每个蜘蛛都会使用各自的管道。
小智 6
您可以像这样在蜘蛛内部设置项目管道设置:
class CustomSpider(Spider):
    name = 'custom_spider'
    custom_settings = {
        'ITEM_PIPELINES': {
            '__main__.PagePipeline': 400,
            '__main__.ProductPipeline': 300,
        },
        'CONCURRENT_REQUESTS_PER_DOMAIN': 2
    }
然后,我可以通过向加载器/返回的项目添加一个值来拆分管道(甚至使用多个管道),该值标识蜘蛛的哪个部分发送了项目。这样我就不会得到任何 KeyError 异常,我知道哪些项目应该可用。
    ...
    def scrape_stuff(self, response):
        pageloader = PageLoader(
                PageItem(), response=response)
        pageloader.add_xpath('entire_page', '/html//text()')
        pageloader.add_value('item_type', 'page')
        yield pageloader.load_item()
        productloader = ProductLoader(
                ProductItem(), response=response)
        productloader.add_xpath('product_name', '//span[contains(text(), "Example")]')
        productloader.add_value('item_type', 'product')
        yield productloader.load_item()
class PagePipeline:
    def process_item(self, item, spider):
        if item['item_type'] == 'product':
            # do product stuff
        if item['item_type'] == 'page':
            # do page stuff
| 归档时间: | 
 | 
| 查看次数: | 20718 次 | 
| 最近记录: |