Scrapy,在管道中发出http请求

问题描述 投票:3回答:1

假设我有一个看似这样的刮取项目

{
    name: "Foo",
    country: "US",
    url: "http://..."
}

在管道中,我想对URL发出GET请求,并检查一些标题,如content_type和status。当标题不符合某些条件时,我想删除该项目。喜欢

class MyPipeline(object):
    def process_item(self, item, spider):
        request(item['url'], function(response) {
           if (...) {
             raise DropItem()
           }
           return item
        }, function(error){ 
            raise DropItem()
        })

使用管道不可能闻到这样的气味。你怎么看?任何想法如何实现这一目标?

蜘蛛:

import scrapy
import json

class StationSpider(scrapy.Spider):
    name = 'station'
    start_urls = ['http://...']

    def parse(self, response):
        jsonResponse = json.loads(response.body_as_unicode())
        for station in jsonResponse:
            yield station
scrapy scrapy-pipeline
1个回答
6
投票

简单的方法

import requests

def process_item(self, item, spider):
    response = requests.get(item['url'])
    if r.status_code ...:
        raise DropItem()
    elif response.text ...:
        raise DropItem()
    else:
        return item

Scrapy方式

现在我认为你不应该在管道内执行此操作,你应该在蜘蛛内部处理它而不是产生一个项目而是一个请求然后产生该项目。

现在,如果您仍想在管道中包含scrapy请求,您可以执行以下操作:

class MyPipeline(object):

    def __init__(self, crawler):
        self.crawler = crawler

    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler)

    def process_item(self, item, spider):
        ...
        self.crawler.engine.crawl(
                    Request(
                        url='someurl',
                        callback=self.custom_callback,
                    ),
                    spider,
                )

        # you have to drop the item, and send it again after your check
        raise DropItem()
    # YES, you can define a method callback inside the same pipeline
    def custom_callback(self, response):
        ...
        yield item

检查我们是否在管道内模拟蜘蛛回调的相同行为。当你想要做一个额外的请求时,你需要找出一种总是丢弃项目的方法,并且只需传递那些额外的回调。

一种方法是发送不同类型的项目,并在管道的process_item内检查它们:

def process_item(self, item, spider):
    if isinstance(item, TempItem):
        ...
    elif isinstance(item, FinalItem):
        yield item
© www.soinside.com 2019 - 2024. All rights reserved.