Scrapy:如何从其他python脚本运行两次或更多蜘蛛?

时间:2016-04-05 06:03:08

标签: python python-2.7 scrapy twisted

Scrapy版本:1.0.5

我已经搜索了很长时间,但大多数解决方法在当前的Scrapy版本中都不起作用。

我的蜘蛛是在jingdong_spider.py中定义的,接口(通过Scrapy Documentation了解它)来运行蜘蛛是在下面:

# interface
def search(keyword):
    configure_logging({'LOG_FORMAT': '%(levelname)s: %(message)s'})
    runner = CrawlerRunner()
    d = runner.crawl(JingdongSpider,keyword)
    d.addBoth(lambda _: reactor.stop())
    reactor.run() # the script will block here until the crawling is finished

然后在temp.py中我会调用上面的search(keyword)来运行蜘蛛。

现在出现了问题:我曾经调用了一次搜索(关键字),但效果很好。但是我把它调了两次,例如,

在temp.py中

search('iphone')
search('ipad2')

报道:

  

Traceback(最近一次调用最后一次):文件   “C:/Users/jiahao/Desktop/code/bbt_climb_plus/temp.py”,第7行,在          搜索('ipad2')文件“C:\ Users \ jiahao \ Desktop \ code \ bbt_climb_plus \ bbt_climb_plus \ spiders \ jingdong_spider.py”,   第194行,在搜索中       reactor.run()#脚本将在此处阻止,直到爬行完成File   “C:\ Python27 \ lib \ site-packages \ twisted \ internet \ base.py”,第1193行,   在奔跑       self.startRunning(installSignalHandlers = installSignalHandlers)文件“C:\ Python27 \ lib \ site-packages \ twisted \ internet \ base.py”,line   1173,在startRunning中       ReactorBase.startRunning(self)文件“C:\ Python27 \ lib \ site-packages \ twisted \ internet \ base.py”,第684行,in   startRunning       提高error.ReactorNotRestartable()twisted.internet.error.ReactorNotRestartable

第一次搜索(关键字)成功,但后者出错了。

你可以帮忙吗?

2 个答案:

答案 0 :(得分:5)

在您的代码示例中,您正在调用twisted.reactor,在每次函数调用时启动它。这是行不通的,因为每个进程只有一个反应器而你不能start it twice

有两种方法可以解决您的问题,两者都在documentation here中描述。要么坚持import socket import sys import select class Server: class Handler: def handle(self, message): pass def __init__(self, serialNo): self.serialNo = serialNo def _setAddress(self, socket, message, address): self.message = message self.address = address self.socket = socket def send(self, message): self.socket.sendto(message, self.address) def getSerialNo(self): return self.serialNo def __init__(self, port, handler): self.ss = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.ss.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.ss.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) self.handler = handler try: self.ss.bind(("0.0.0.0", int(port))) except: self.ss.close() raise RuntimeError("Create socket error") def loop(self): while True: try: print "Listening for broadcast..." data_input,data_output,data_except = select.select([self.ss],[],[], 60) if (data_input != []): (message, address) = self.ss.recvfrom(2048) print "Got request from %s:%s" % (address, message) self.handler._setAddress(self.ss, message, address) self.handler.handle(message) else: print "no data within 60 seconds" except (KeyboardInterrupt, SystemExit): raise except: sys.exc_info()[0] ,要将CrawlerRunner移到reactor.run()函数之外,以确保只调用一次。或者使用search(),然后致电CrawlerProcess。第二种方法更容易,您的代码看起来像这样:

crawler_process.start()

答案 1 :(得分:4)

正如Pawel Miech所说

  

在您的代码示例中,您正在调用twisted.reactor start   它在每个函数调用。这是行不通的,因为只有   每个过程一个反应堆,你不能启动两次。

我找到了解决问题的方法。只需使用多处理。

它会像:

from multiprocessing import Process
def run_spider(keyword):
    if __name__ == '__main__':
        p = Process(target=jingdong_spider.search, args=(keyword.encode('utf-8'),))
        p.start()
        p.join()

如果每个人都在使用python-multiprocessing时遇到问题。更好地了解python文档。