【问题标题】:Multi-threaded web scraping in Python/PySide/PyQtPython/PySide/PyQt 中的多线程网页抓取
【发布时间】:2012-03-28 23:39:41
【问题描述】:

我正在构建一种网络爬虫。基本上,软件会做的是:

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

完成此任务的最佳方法是什么?所以我正在寻找超过 20-30 个并发连接来做到这一点。

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

我在循环中看到的问题是如何指示它仅使用之前未使用的那些 ID,即在之前执行的迭代/线程中?我是否需要某种“委托人”函数来跟踪已使用的 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?

提前感谢您的回答!

【问题讨论】:

  • 您可能应该将逻辑与 GUI 分开,并且仅将 QT 用于 GUI。爬虫逻辑应该用纯python编写或重用现有的爬虫,如scrapy

标签: python multithreading pyqt pyside


【解决方案1】:

正如 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"

【讨论】:

  • 这实际上取决于。如果线程需要与 GUI 通信,QThreads 会更好更简单。
  • 就像@Avaris 说的那样,线程需要和GUI 线程通信,而现有的代码大部分都写成QThread——所以我需要使用它来代替Python 内置的线程模块。无论如何,我为你 +1 了,以获得详细的回复。
  • 使用 time.sleep(random.random()) 有什么好处
  • 这有助于使示例更加真实,每个线程不必花费相同的时间来完成它们的工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-17
  • 2018-02-15
相关资源
最近更新 更多