2012-03-12 61 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