2016-09-11 4 views
8

J'ai essayé de faire une application en Python en utilisant Scrapy qui a les fonctionnalités suivantes:substitut ReactorNotRestartable Python

  • Un reste api (je l'avais fait ce flacon à l'aide) écoute à toutes les demandes ramper/ferraille et retourner la réponse après avoir rampé (la partie en rampant est assez courte, de sorte que la connexion peut être keep-alive jusqu'à ce crawling se terminé.)

Je suis en mesure de le faire en utilisant le code suivant.:

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) 

Maintenant, le problème que je suis confronté est après avoir fait l'arrêt du réacteur (qui me semble nécessaire que je ne veux pas collé à la reactor.run()). Je n'ai pas pu accepter la demande supplémentaire après la première demande. Après la première demande se rempli, je suis l'erreur suivante:

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 

Ce qui est évident, puisque nous ne pouvons pas redémarrer le réacteur.

Mes questions sont les suivantes:

1) Comment pourrais-je fournir un soutien pour les prochaines demandes de ramper?

2) Est-il possible de passer à la ligne suivante après reactor.run() sans l'arrêter?

+0

Est-ce que cela [réponse] (http://stackoverflow.com/a/18924451/1117028) aide? –

+1

Voir les réponses à http://stackoverflow.com/questions/32724537/building-a-restful-flask-api-for-scrapy et http://stackoverflow.com/questions/36384286/how-to-integrate-flask- scrapy? noredirect = 1 & lq = 1. –

+0

@MikhailKorobov Merci de partager les liens, [en utilisant subprocess] (http://stackoverflow.com/questions/36384286/how-to-integrate-flask-scrapy?noredirect=1&lq=1#answer-37270442) fonctionne pour moi, – sagar

Répondre

1

Voici une solution simple à votre problème

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) 

Dans la solution ci-dessus, je suppose que vous êtes en mesure de démarrer votre robot de la ligne de commande en utilisant la commande start_request.py fichier sur shell/ligne de commande.

Maintenant, ce que nous faisons utilise le threading en python pour lancer un nouveau thread pour chaque requête entrante. Maintenant, vous pouvez facilement exécuter votre instance de robot en parallèle pour chaque coup. Contrôlez simplement votre nombre de threads en utilisant threading.activeCount()

1

Je vous recommande d'utiliser un système de file d'attente comme Rq (pour simplifier, mais il y en a peu d'autres).
Vous pourriez avoir une fonction Craw:

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() 

Puis dans votre code principal, utilisez la file d'attente Rq afin de recueillir des exécutions sur chenilles:

# 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) 

Ne pas oublier de lancer un processus de travail rq, travaillant pour le même nom de file d'attente (ici parse). Par exemple, exécuter dans une session de terminal:

rq worker parse