Как узнать, был ли CloseSpider поднят на уровне CrawlerProcessPython

Программы на Python
Ответить
Anonymous
 Как узнать, был ли CloseSpider поднят на уровне CrawlerProcess

Сообщение Anonymous »

Мне нужно запускать парсеры в цикле, но если в пауке возникают определенные ошибки, я хотел бы иметь возможность вызвать CloseSpiderи для этого отфильтровать функцию цикла и остановить цикл.< /p>
Вот мой код, который отлично работает с полностью функционирующим пауком, но я создал небольшой MRE для проверки варианта использования CloseSpider.

Код: Выделить всё

from __future__ import print_function

import multiprocessing as mp
import traceback
from time import sleep
from typing import Type

from scrapy import Spider
from scrapy.crawler import CrawlerProcess
from scrapy.exceptions import CloseSpider

class MyTestSpider(Spider):
name = "my_test_spider"

def __init__(self) -> None:
raise CloseSpider

class Process(mp.Process):
def __init__(self, target: callable, *args, **kwargs):
mp.Process.__init__(self, target=target, *args, **kwargs)

self._pconn, self._cconn = mp.Pipe()
self._exception = None

def run(self):
try:
mp.Process.run(self)

self._cconn.send(None)

except Exception as e:
tb = traceback.format_exc()

self._cconn.send(tb)

@property
def exception(self):
if self._pconn.poll():
self._exception = self._pconn.recv()

return self._exception

def run_crawler_loop(
spider: Type[Spider],
loop_wait_secs: int,
**kwargs,
) -> None:
while True:
run_crawler_reactor_safe(spider=spider, **kwargs)

sleep(loop_wait_secs)

def run_crawler_reactor_safe(spider: Type[Spider], **kwargs) -> None:
process = Process(target=run_crawler, kwargs={"spider": spider} | kwargs)

process.start()
process.join()

if process.exception:
error, traceback = process.exception

# send an email here

raise error # close the loop

def run_crawler(spider: Type[Spider], **kwargs) -> None:
process = CrawlerProcess()

crawler = process.create_crawler(spider)

process.crawl(crawler_or_spidercls=crawler, **kwargs)

process.start()

# how would I tell here if the spider was closed due to raising a CloseSpider exception?
# I'd like to raise that exception here so I can stop the loop by raising an error in run_crawler_reactor_safe

if __name__ == "__main__":
run_crawler_loop(spider=MyTestSpider, loop_wait_secs=0)
При выполнении этой команды создаются две записи журнала в скрученном виде:

Код: Выделить всё

Unhandled error in Deferred:
2024-10-09 09:39:01 [twisted] CRITICAL: Unhandled error in Deferred:

Traceback (most recent call last):
File "/Users/myusername/opt/miniconda3/envs/myenv/lib/python3.11/site-packages/scrapy/crawler.py", line 265, in crawl
return self._crawl(crawler, *args, **kwargs)
File "/Users/myusername/opt/miniconda3/envs/myenv/lib/python3.11/site-packages/scrapy/crawler.py", line 269, in _crawl
d = crawler.crawl(*args, **kwargs)
File "/Users/myusername/opt/miniconda3/envs/myenv/lib/python3.11/site-packages/twisted/internet/defer.py", line 2260, in unwindGenerator
return _cancellableInlineCallbacks(gen)
File "/Users/myusername/opt/miniconda3/envs/myenv/lib/python3.11/site-packages/twisted/internet/defer.py", line 2172, in _cancellableInlineCallbacks
_inlineCallbacks(None, gen, status, _copy_context())
---   ---
File "/Users/myusername/opt/miniconda3/envs/myenv/lib/python3.11/site-packages/twisted/internet/defer.py", line 2003, in _inlineCallbacks
result = context.run(gen.send, result)
File "/Users/myusername/opt/miniconda3/envs/myenv/lib/python3.11/site-packages/scrapy/crawler.py", line 155, in crawl
self.spider = self._create_spider(*args, **kwargs)
File "/Users/myusername/opt/miniconda3/envs/myenv/lib/python3.11/site-packages/scrapy/crawler.py", line 169, in _create_spider
return self.spidercls.from_crawler(self, *args, **kwargs)
File "/Users/myusername/opt/miniconda3/envs/myenv/lib/python3.11/site-packages/scrapy/spiders/__init__.py", line 62, in from_crawler
spider = cls(*args, **kwargs)
File "/Users/myusername/GitHub/polgara_v2/so__capture_SpiderClose.py", line 17, in __init__
raise CloseSpider
scrapy.exceptions.CloseSpider:

2024-10-09 09:39:01 [twisted] CRITICAL:
Traceback (most recent call last):
File "/Users/myusername/opt/miniconda3/envs/myenv/lib/python3.11/site-packages/twisted/internet/defer.py", line 2003, in _inlineCallbacks
result = context.run(gen.send, result)
File "/Users/myusername/opt/miniconda3/envs/myenv/lib/python3.11/site-packages/scrapy/crawler.py", line 155, in crawl
self.spider = self._create_spider(*args, **kwargs)
File "/Users/myusername/opt/miniconda3/envs/myenv/lib/python3.11/site-packages/scrapy/crawler.py", line 169, in _create_spider
return self.spidercls.from_crawler(self, *args, **kwargs)
File "/Users/myusername/opt/miniconda3/envs/myenv/lib/python3.11/site-packages/scrapy/spiders/__init__.py", line 62, in from_crawler
spider = cls(*args, **kwargs)
File "/Users/myusername/GitHub/polgara_v2/so__capture_SpiderClose.py", line 17, in __init__
raise CloseSpider
scrapy.exceptions.CloseSpider
Однако эти ошибки, похоже, обрабатываются здесь и фактически не возникают снова каким-либо образом, который можно было бы отследить дальше. Я просмотрел экземпляры искателя и процесса, когда процесс.start() завершается в run_crawler(), но не могу найти никаких признаков того, что паук позволяет только сообщение об ошибке.
Я также пытался просмотреть пакет Twisted и сообщение о SO (остановка Twisted от проглатывания исключений), но быстро заблудился...< /p>
Есть идеи, как мне добиться того, чего я хочу?

Подробнее здесь: https://stackoverflow.com/questions/790 ... lerprocess
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»