2012-03-12 59 views
2

我正在构建一种网页抓取工具。基本上,软会做的是:Python中的多线程网页抓取/ PySide/PyQt

  1. 用户(我)输入一些数据(IDS) - ID是复杂的,所以不只是数字
  2. 基于这些ID,脚本访问http://localhost/ID

完成此操作的最佳方法是什么?所以我正在寻找20-30个并发连接来完成它。

我在想,会不会是一个简单的循环解决方案?这个循环会启动QThreads(这是一个Qt应用程序),所以它们可以同时运行。

然而,我所看到的循环的问题是如何指示它只使用那些之前没有使用过的ID,即在它刚才执行之前的迭代/线程中?我是否需要某种“委托人”功能来跟踪哪些ID已被使用,并将未使用的委托给QThreads?

现在我已经写了一些代码,但我不知道这是否是正确的:

class GUI(QObject): 

    def __init__(self): 
     print "GUI CLASS INITIALIZED!!!" 
     self.worker = Worker() 

     for i in xrange(300): 
      QThreadPool().globalInstance().start(self.worker) 

class Worker(QRunnable): 

    def run(self): 
     print "Hello world from thread", QThread.currentThread() 

现在我不知道如果这些真正做到我想要的。这实际上是在单独的线程中运行吗?我在问,因为currentThread()每次执行都是一样的,所以它看起来并不那样。

基本上,我的问题归结为如何同时执行几个相同的QThreads?

在此先感谢您的答案!

+0

您应该将逻辑从GUI中分离出来,并且只在GUI中使用QT。抓取器逻辑应该用纯Python编写或重用现有的抓取工具,如[scrapy](http://scrapy.org/) – Dikei 2012-03-12 16:03:03

回答

5

正如Dikei所说,Qt在这里是红鲱鱼。专注于使用Python线程,因为它可以让您的代码更简单。

在下面的代码中,我们有一套,job_queue,包含要执行的作业。我们还有一个函数worker_thread,它从队列中传递一个作业并执行。在这里,它只是随便休息一段时间。这里的关键是set.pop是线程安全的。

我们创建线程对象数组workers,并在每个线程对象创建时调用start。从Python documentation threading.Thread.start在一个单独的控制线程中运行给定的可调用对象。最后,我们遍历每个工作线程并阻塞,直到它退出。

import threading 
import random 
import time 

pool_size = 5 

job_queue = set(range(100)) 

def worker_thread(queue): 
    while True: 
     try: 
      job = queue.pop() 
     except KeyError: 
      break 

     print "Processing %i..." % (job,) 
     time.sleep(random.random()) 

    print "Thread exiting." 

workers = [] 
for thread in range(pool_size): 
    workers.append(threading.Thread(target=worker_thread, args=(job_queue,))) 
    workers[-1].start() 

for worker in workers: 
    worker.join() 

print "All threads exited" 
+1

实际上取决于它。如果线程需要与GUI通信,'QThread'会更好,更简单。 – Avaris 2012-03-12 18:16:20

+0

就像@Avaris说的那样,线程需要和GUI线程进行通信,现有的代码主要写成QThread--所以我需要使用它来代替Python的内置线程模块。无论如何,我为你+1了详细的回应。 – 2012-03-13 08:41:35

+0

什么是使用time.sleep(random.random()) – 2013-03-11 19:52:59