Scrapy,在管道中发出http请求
Scrapy, make http request in pipeline
假设我有一个看起来像这样的抓取项目
{
name: "Foo",
country: "US",
url: "http://..."
}
在管道中,我想向 url 发出 GET 请求并检查一些 headers,例如 content_type 和状态。当 headers 不满足某些条件时我想丢弃该项目。喜欢
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
简单的方法
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 Request,您可以这样做:
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
假设我有一个看起来像这样的抓取项目
{
name: "Foo",
country: "US",
url: "http://..."
}
在管道中,我想向 url 发出 GET 请求并检查一些 headers,例如 content_type 和状态。当 headers 不满足某些条件时我想丢弃该项目。喜欢
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
简单的方法
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 Request,您可以这样做:
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