Как использовать мета в правиле терапии
def parse(self,response):
my_item={'test':123,'test2':321}
google_url = 'https://www.google.com/search?q=coffee+cans'
yield Request(url=google_url,callback=self.google,meta={'my_item':my_item})
def google(self,response):
my_item = response.meta['my_item']
rules = (
Rule(LinkExtractor(restrict_xpaths='//div[@class="r"]/a',allow='/dp',allow_domains='chewy.com'),
callback="chewy"),
Rule(LinkExtractor(restrict_xpaths='//div[@class="r"]/a',allow='/p/',allow_domains='homedepot.com'),
process_request=request.meta['my_item']=my_item,callback='homedepot')
)
def homedepot(self,response):
#my_item = response.meta['my_item']
сообщение об ошибке:
Traceback (most recent call last):
File "/home/timmy/.local/bin/scrapy", line 11, in <module>
sys.exit(execute())
File "/home/timmy/.local/lib/python3.6/site-packages/scrapy/cmdline.py", line 149, in execute
cmd.crawler_process = CrawlerProcess(settings)
File "/home/timmy/.local/lib/python3.6/site-packages/scrapy/crawler.py", line 251, in __init__
super(CrawlerProcess, self).__init__(settings)
File "/home/timmy/.local/lib/python3.6/site-packages/scrapy/crawler.py", line 137, in __init__
self.spider_loader = _get_spider_loader(settings)
File "/home/timmy/.local/lib/python3.6/site-packages/scrapy/crawler.py", line 338, in _get_spider_loader
return loader_cls.from_settings(settings.frozencopy())
File "/home/timmy/.local/lib/python3.6/site-packages/scrapy/spiderloader.py", line 61, in from_settings
return cls(settings)
File "/home/timmy/.local/lib/python3.6/site-packages/scrapy/spiderloader.py", line 25, in __init__
self._load_all_spiders()
File "/home/timmy/.local/lib/python3.6/site-packages/scrapy/spiderloader.py", line 47, in _load_all_spiders
for module in walk_modules(name):
File "/home/timmy/.local/lib/python3.6/site-packages/scrapy/utils/misc.py", line 71, in walk_modules
submod = import_module(fullpath)
File "/usr/lib/python3.6/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 994, in _gcd_import
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 674, in exec_module
File "<frozen importlib._bootstrap_external>", line 781, in get_code
File "<frozen importlib._bootstrap_external>", line 741, in source_to_code
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "/home/timmy/scrapy_tut/myproject/spiders/amazon.py", line 62
process_request=request.meta['my_item']=my_item,callback='homedepot')
^
SyntaxError: invalid syntax
Я отредактировал вопрос, чтобы сделать его более тестируемым. Как пройти? my_item
на ссылки, извлеченные из Rule(LinkExtractor...)
(Я переместил правила из инициализации spider, чтобы мне было легче это делать (используйте мета), но я все еще не могу это сделать.
Любая помощь высоко ценится
Я пытался использовать
rules = (
Rule(LinkExtractor(restrict_xpaths='//div[@class="r"]/a',allow='/dp',allow_domains='chewy.com'),
process_request=lambda request:request.meta.update({'my_item':my_item}),callback='chewy'),
Rule(LinkExtractor(restrict_xpaths='//div[@class="r"]/a',allow='/p/',allow_domains='homedepot.com')
,process_request=lambda request:request.meta.update({'my_item':my_item}),callback='homedepot')
)
Это не дает ошибки, но страница не запрашивается
1 ответ
Ваш первый пример - неправильный код Python, как сообщает Python.
Ваш второй пример не работает, потому что ваш обратный вызов для process_request
параметр Rule
, lambda
функция, возвращает None
,
Если вы проверите документацию:
process_request
является вызываемой или строкой (в этом случае будет использоваться метод из объекта-паука с таким именем), который будет вызываться при каждом запросе, извлеченном этим правилом, и должен возвращать запрос или None (чтобы отфильтровать запрос),
Это на самом деле не единственная причина, по которой это не работает. Чтобы использовать основанные на правилах экстракторы ссылок, вы должны:
Подкласс
CrawlSpider
, Из ваших примеров не ясно, делаете ли вы это.Не переопределять
parse
метод в вашем подклассе, как вы делаете в настоящее время. Еслиstart_urls
не достаточно хорош для вас, используйте его в сочетании сparse_start_url
,Правила должны быть объявлены как атрибут класса. Вместо этого вы определяете их как переменные в методе вашего подкласса Spider. Это не сработает.
Пожалуйста, перечитайте документацию по CrawlSpider.
Что касается передачи значения из мета ответа в мета следующего запроса, у вас есть 2 варианта:
Переопределить ваш паук как
Spider
подкласс, а неCrawlSpider
подкласс, вручную выполняя всю логику без экстракторов ссылок на основе правил.Это естественный шаг, когда общий паук, как
CrawlSpider
начинает чувствовать себя слишком ограничительным. Общие подклассы паука хороши для простых случаев использования, но всякий раз, когда вы сталкиваетесь с чем-то нетривиальным, вы должны рассмотреть вопрос о переходе на обычныйSpider
подкласс.Дождитесь выхода Scrapy 1.7, что должно произойти в ближайшее время (вы можете использовать
master
ветвь Scrapy в то же время). Scrapy 1.7 представляет новыйresponse
параметр дляprocess_request
обратные вызовы, которые позволят вам сделать что-то вроде:
def my_request_processor(request, response):
request.meta['item'] = response.meta['item']
return request
class MySpider(CrawlSpider):
# …
rules = (
Rule(
LinkExtractor(
restrict_xpaths='//div[@class="r"]/a',
allow='/p/',
allow_domains='homedepot.com'
),
process_request=my_request_processor,
callback='homedepot'
)
)
# …