mirror of https://github.com/scrapy/scrapy.git
Merge ae6cfec7c6 into c9446931a8
This commit is contained in:
commit
bed80fae8b
|
|
@ -0,0 +1,45 @@
|
||||||
|
"""
|
||||||
|
StickyMeta middleware transfers specified meta keys to further
|
||||||
|
requests in spider request chain.
|
||||||
|
|
||||||
|
Sticky meta keys can be configured either by:
|
||||||
|
* Setting STICKY_META_KEYS eg:
|
||||||
|
STICKY_META_KEYS = ['key1', 'key2']
|
||||||
|
* Spider attribute sticky_meta eg:
|
||||||
|
spider.sticky_meta = ['key1','key2']
|
||||||
|
* Meta attribute "sticky" eg:
|
||||||
|
Request(meta={'sticky': ['foo'], 'foo': 'bar'})
|
||||||
|
resolve priority is meta > spider attribute > setting
|
||||||
|
"""
|
||||||
|
from scrapy import Request
|
||||||
|
|
||||||
|
|
||||||
|
class StickyMeta:
|
||||||
|
@classmethod
|
||||||
|
def from_crawler(cls, crawler):
|
||||||
|
return cls(crawler.settings)
|
||||||
|
|
||||||
|
def __init__(self, settings):
|
||||||
|
self.settings_sticky_meta = settings.getlist('STICKY_META')
|
||||||
|
|
||||||
|
def process_spider_output(self, response, result, spider):
|
||||||
|
# without attached request response will not have meta to pass on
|
||||||
|
if not response.request:
|
||||||
|
for value in result:
|
||||||
|
yield value
|
||||||
|
return
|
||||||
|
|
||||||
|
spider_sticky_meta = getattr(spider, 'sticky_meta', None)
|
||||||
|
for request in result:
|
||||||
|
if not isinstance(request, Request):
|
||||||
|
yield request
|
||||||
|
continue
|
||||||
|
# priority: meta > spider attribute > setting
|
||||||
|
sticky = response.meta.get(
|
||||||
|
'sticky',
|
||||||
|
spider_sticky_meta if spider_sticky_meta is not None else self.settings_sticky_meta
|
||||||
|
)
|
||||||
|
for k, v in response.meta.items():
|
||||||
|
if k in sticky and k not in request.meta:
|
||||||
|
request.meta[k] = v
|
||||||
|
yield request
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from scrapy.spidermiddlewares.stickymeta import StickyMeta
|
||||||
|
from scrapy.http import Response, Request
|
||||||
|
from scrapy.spiders import Spider
|
||||||
|
from scrapy.utils.test import get_crawler
|
||||||
|
|
||||||
|
|
||||||
|
class TestStickyMetaMiddleware(TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
crawler = get_crawler(Spider, settings_dict={'STICKY_META': ['settings', 'settings2']})
|
||||||
|
self.spider = crawler._create_spider(name='foobar')
|
||||||
|
self.mw = StickyMeta.from_crawler(crawler)
|
||||||
|
|
||||||
|
def test_process_spider_output(self):
|
||||||
|
# plain, no match
|
||||||
|
resp = Response(
|
||||||
|
'http://scrapytest.org',
|
||||||
|
request=Request(
|
||||||
|
'http://scrapytest.org/',
|
||||||
|
meta={'oh_no': "I'm not sticky! :("}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
reqs = [Request('http://scrapytest.org')]
|
||||||
|
for result in self.mw.process_spider_output(resp, reqs, self.spider):
|
||||||
|
self.assertEqual(result.meta, {})
|
||||||
|
|
||||||
|
# unattached response
|
||||||
|
wild_resp = Response('http://httpbin.org/headers')
|
||||||
|
reqs = [Request('http://scrapytest.org')]
|
||||||
|
for result in self.mw.process_spider_output(wild_resp, reqs, self.spider):
|
||||||
|
self.assertEqual(result.meta, {})
|
||||||
|
|
||||||
|
# setting STICKY_META
|
||||||
|
reqs = [Request('http://scrapytest.org')]
|
||||||
|
resp = Response(
|
||||||
|
'http://scrapytest.org',
|
||||||
|
request=Request(
|
||||||
|
'http://scrapytest.org/',
|
||||||
|
meta={'settings': "I'm sticky!"}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
out = list(self.mw.process_spider_output(resp, reqs, self.spider))
|
||||||
|
self.assertEqual(out[0].meta, {'settings': "I'm sticky!"})
|
||||||
|
|
||||||
|
# meta["sticky"]
|
||||||
|
reqs = [Request('http://scrapytest.org')]
|
||||||
|
resp = Response(
|
||||||
|
'http://scrapytest.org',
|
||||||
|
request=Request(
|
||||||
|
'http://scrapytest.org/',
|
||||||
|
meta={'meta': "I'm sticky!", 'sticky': ['meta']}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
out = list(self.mw.process_spider_output(resp, reqs, self.spider))
|
||||||
|
self.assertEqual(out[0].meta, {'meta': "I'm sticky!"})
|
||||||
|
|
||||||
|
# spider.sticky_meta
|
||||||
|
reqs = [Request('http://scrapytest.org')]
|
||||||
|
resp = Response(
|
||||||
|
'http://scrapytest.org',
|
||||||
|
request=Request(
|
||||||
|
'http://scrapytest.org/',
|
||||||
|
meta={'spider': "I'm sticky!"}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
self.spider.sticky_meta = ['spider']
|
||||||
|
out = list(self.mw.process_spider_output(resp, reqs, self.spider))
|
||||||
|
self.assertEqual(out[0].meta, {'spider': "I'm sticky!"})
|
||||||
|
|
||||||
Loading…
Reference in New Issue