我一直在尝试第一次尝试线程脚本。它最终将成为一个网络抓取工具,希望比我之前制作的原始线性抓取脚本运行得更快一些。
经过几个小时的阅读和使用一些示例代码后。我仍然不确定就实现而言什么被认为是正确的。
目前我正在使用以下代码:
from Queue import Queue
import threading
def scrape(queue):
global workers
print worker.getName()
print queue.get()
queue.task_done()
workers -= 1
queue = Queue(maxsize=0)
threads = 10
workers = 0
with open('test.txt') as in_file:
for line in in_file:
queue.put(line)
while not (queue.empty()):
if (threads != workers):
worker = threading.Thread(target=scrape, args=(queue,))
worker.setDaemon(True)
worker.start()
workers += 1
这个想法是我在 test.txt 文件中有一个 URL 列表。我打开该文件并将所有 URL 放入队列中。从那里我得到 10 个正在运行的线程,它们从队列中拉出并抓取网页,或者在本例中只是打印出拉出的行。
函数完成后,我会删除一个“工作线程”,然后用一个新的线程替换它,直到队列为空。
在我的现实世界实现中,有时我必须从函数抓取中获取数据并将其写入 .csv 文件。但是,现在我只是想了解如何正确实现线程。
我见过类似上面使用“线程”的示例...并且我还见过利用继承类的“线程”示例。我只是想知道我应该使用什么以及管理它的正确方法。
这里对我宽容一些,我只是一个试图理解线程的初学者......是的,我知道它可能会变得非常复杂。但是,我认为第一次尝试这应该很容易......
最佳答案
在 Python 2.x 上 multiprocessing.dummy (使用线程)是一个不错的选择,因为它易于使用(在 Python 3.x 中也可以)
如果您发现抓取受到 CPU 限制,并且您有多个 CPU 核心,那么您可以非常简单地切换到真实的 multiprocessing可能会获得很大的加速。
(由于 performance optimization,Python 通常无法从具有线程的多个 CPU 中获益,而不是从多个进程中获益 - 您必须自己找出在您的情况下哪个更快)
使用 mutliprocessing.dummy 你可以做到
from multiprocessing.dummy import Pool
# from multiprocessing import Pool # if you want to use more cpus
def scrape(url):
data = {"sorted": sorted(url)} # normally you would do something more interesting
return (url, data)
urls=[]
threads = 10
if __name__=="__main__":
with open('test.txt') as in_file:
urls.extend(in_file) # lines
p=Pool(threads)
results=list(p.imap_unordered(scrape,urls))
p.close()
print results # normally you would process your results here
在 Python 3.x 上,concurrent.futures可能是更好的选择。
关于Python 线程/线程实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38660815/