2016-09-11 3 views
8

Я пытался сделать приложение в Python с использованием Scrapy, который имеет следующие функциональные возможности:Python Scrapy ReactorNotRestartable заменить

  • апи остальные (я сделал, что с помощью флягу) прослушивает все запросы ползать/лом и возвращает ответ после обхода (ползучая часть достаточно коротка, поэтому соединение может быть держать-живо до ползать будет завершено.)

Я могу сделать это, используя следующий код.:

items = [] 
def add_item(item): 
    items.append(item) 

# set up crawler 
crawler = Crawler(SpiderClass,settings=get_project_settings()) 
crawler.signals.connect(add_item, signal=signals.item_passed) 

# This is added to make the reactor stop, if I don't use this, the code stucks at reactor.run() line. 
crawler.signals.connect(reactor.stop, signal=signals.spider_closed) #@UndefinedVariable 
crawler.crawl(requestParams=requestParams) 
# start crawling 
reactor.run() #@UndefinedVariable 
return str(items) 

Теперь проблема я столкнулся после создания реактора остановки (который, кажется, мне надо, так как я не хочу, чтобы прилипла к reactor.run()). Я не мог принять дальнейший запрос после первого запроса. По завершении первого запроса я получил следующую ошибку:

Traceback (most recent call last): 
    File "c:\python27\lib\site-packages\flask\app.py", line 1988, in wsgi_app 
    response = self.full_dispatch_request() 
    File "c:\python27\lib\site-packages\flask\app.py", line 1641, in full_dispatch_request 
    rv = self.handle_user_exception(e) 
    File "c:\python27\lib\site-packages\flask\app.py", line 1544, in handle_user_exception 
    reraise(exc_type, exc_value, tb) 
    File "c:\python27\lib\site-packages\flask\app.py", line 1639, in full_dispatch_request 
    rv = self.dispatch_request() 
    File "c:\python27\lib\site-packages\flask\app.py", line 1625, in dispatch_request 
    return self.view_functions[rule.endpoint](**req.view_args) 
    File "F:\my_workspace\jobvite\jobvite\com\jobvite\web\RequestListener.py", line 38, in submitForm 
    reactor.run() #@UndefinedVariable 
    File "c:\python27\lib\site-packages\twisted\internet\base.py", line 1193, in run 
    self.startRunning(installSignalHandlers=installSignalHandlers) 
    File "c:\python27\lib\site-packages\twisted\internet\base.py", line 1173, in startRunning 
    ReactorBase.startRunning(self) 
    File "c:\python27\lib\site-packages\twisted\internet\base.py", line 684, in startRunning 
    raise error.ReactorNotRestartable() 
ReactorNotRestartable 

Это очевидно, поскольку мы не можем перезапустить реактор.

Так что мои вопросы:

1) Как я мог обеспечить поддержку следующих запросов к сканированию?

2) Есть ли способ перейти к следующей строке после завершения реактора.run(), не останавливая его?

+0

Помогает ли это [ответить] (http://stackoverflow.com/a/18924451/1117028)? –

+1

См. Ответы на http://stackoverflow.com/questions/32724537/building-a-restful-flask-api-for-scrapy и http://stackoverflow.com/questions/36384286/how-to-integrate-flask- SCRAPY? noredirect = 1 & LQ = 1. –

+0

@MikhailKorobov Спасибо за обмен ссылками, [используя подпроцесс] (http://stackoverflow.com/questions/36384286/how-to-integrate-flask-scrapy?noredirect11&lq=1#answer-37270442) работает для меня, – sagar

ответ

1

Вот простое решение вашей проблемы

from flask import Flask 
import threading 
import subprocess 
import sys 
app = Flask(__name__) 

class myThread (threading.Thread): 
    def __init__(self,target): 
     threading.Thread.__init__(self) 
     self.target = target 
    def run(self): 
     start_crawl() 

def start_crawl(): 
    pid = subprocess.Popen([sys.executable, "start_request.py"]) 
    return 


@app.route("/crawler/start") 
def start_req(): 
    print ":request" 
    threadObj = myThread("run_crawler") 
    threadObj.start() 
    return "Your crawler is in running state" 
if (__name__ == "__main__"): 
    app.run(port = 5000) 

В приведенном выше решении я предполагаю, что вы можете начать свой искатель из командной строки с помощью команды start_request.py в командной строке.

Теперь мы используем потоки в python для запуска нового потока для каждого входящего запроса. Теперь вы можете легко запускать свой экземпляр искателя параллельно для каждого попадания. Просто контролируйте количество потоков, используя threading.activeCount()

1

Я рекомендую вам использовать систему очередей, такую ​​как Rq (для простоты, но есть и другие).
Вы мог бы иметь функцию зоба:

from twisted.internet import reactor 
import scrapy 
from scrapy.crawler import CrawlerRunner 
from scrapy.utils.log import configure_logging 
from scrapy.utils.project import get_project_settings 

from spiders import MySpider 

def runCrawler(url, keys, mode, outside, uniqueid): 

    runner = CrawlerRunner(get_project_settings()) 

    d = runner.crawl(MySpider, url=url, param1=value1, ...) 

    d.addBoth(lambda _: reactor.stop()) 
    reactor.run() 

Затем в основном коду, используйте очередь Rq для того, чтобы собрать гусеничную казнь:

# other imports 
pool = redis.ConnectionPool(host=REDIS_HOST, port=REDIS_PORT, db=your_redis_db_number) 
redis_conn =redis.Redis(connection_pool=pool) 

q = Queue('parse', connection=redis_conn) 

# urlSet is a list of http:// or https:// like url's 
for url in urlSet: 
    job = q.enqueue(runCrawler, url, param1, ... , timeout=600) 

Не забудьте запустить рабочий процесс RQ, работая для того же имени очереди (здесь разобрать). Например, выполнить в терминальной сессии:

rq worker parse