Как передать данные между последовательными пауками - PullRequest
0 голосов
/ 27 октября 2019

У меня есть два паука, которые работают в последовательном порядке в соответствии с https://docs.scrapy.org/en/latest/topics/practices.html#running-multiple-spiders-in-the-same-process. Теперь я хочу передать некоторую информацию от первого паука второму (веб-драйверу селена или информации о его сеансе).

Я довольно новичок в scrapy, но в другом посте было предложено сохранить данные в БД и извлечь их оттуда. Кажется, это слишком много для передачи одной переменной, другого пути нет? (Я знаю, что в этом примере я мог бы просто превратить это в одного длинного паука, но позже я хотел бы запустить первого паука один раз, а второго паука несколько раз.)

class Spider1(scrapy.Spider):
    # Open a webdriver and get session_id

class Spider2(scrapy.Spider):
    # Get the session_id  and run spider2 code
    def __init__(self, session_id):
        ...

configure_logging()
runner = CrawlerRunner()

@defer.inlineCallbacks
def crawl():
    yield runner.crawl(Spider1)
    # TODO How to get the session_id?
    # session_id = yield runner.crawl(Spider1) returns None
    # Or adding return statement in Spider 1, actually breaks 
    # sequential processing and program sleeps before running Spider1

    time.sleep(2)

    yield runner.crawl(Spider2(session_id))
    reactor.stop()

crawl()
reactor.run() # the script will block here until the last crawl call is finished

Я хотел бы передатьпеременная в конструктор второго паука, но я не могу получить данные из первого. Если я просто запустил первый сканер, чтобы вернуть переменную, он, очевидно, нарушает последовательную структуру. Если я попытаюсь получить доход, результат будет Нет.

Я полностью слепой? Я не могу поверить, что это должно быть такой сложной задачей.

Ответы [ 2 ]

1 голос
/ 28 октября 2019

Вы можете передать очередь обоим паукам и разрешить spider2 блокировать queue.get (), поэтому нет необходимости в time.sleep(2).

# globals.py

queue = Queue()
# run.py

import globals


class Spider1(scrapy.Spider):
    def __init__(self):
        # put session_id to `globals.queue` somewhere in `Spider1`, so `Spider2` can start.
        ...

class Spider2(scrapy.Spider):
    def __init__(self):
        session_id = globals.queue.get()

configure_logging()
runner = CrawlerRunner()

@defer.inlineCallbacks
def crawl():
    yield runner.crawl(Spider1)
    yield runner.crawl(Spider2)
    reactor.stop()

crawl()
reactor.run() 
0 голосов
/ 30 октября 2019

Вы также можете просто создать веб-драйвер и передать его в качестве аргументов. Когда я попробовал это изначально, это не сработало, потому что я неправильно передал аргументы (см. Мой комментарий к записи).

class Spider1(scrapy.Spider):
    def __init__(self, driver=None):
        self.driver = driver # Do whatever with the driver

class Spider2(scrapy.Spider):
   def __init__(self, driver=None):
       self.driver = driver # This is the same driver as Spider 1 used


configure_logging()
runner = CrawlerRunner()

@defer.inlineCallbacks
def crawl():
    driver = webdriver.Chrome()

    yield runner.crawl(Spider1, driver=driver)
    yield runner.crawl(Spider2, driver=driver)

    reactor.stop()

crawl()
reactor.run() # the script will block here until the last crawl call is finished
...