python爬虫之多线程、多进程爬虫

一、原因

多线程对爬虫的效率提高是非凡的,当我们使用python的多线程有几点是需要我们知道的:

1.Python的多线程并不如java的多线程,其差异在于当python解释器开始执行任务时,受制于GIL(全局解释所),Python 的线程被限制到同一时刻只允许一个程执行这样一个执行模型。

2.Python 的线程更适用于处理 I/O 和其他需要并发行的阻塞操作(比如等待 I/O、等待从数据库获取数据等等),而不是需要多处理器行的计算密集型任务。幸运的是,爬虫大部分时间在网络交互上,所以可以使用多线程来编写爬虫。

3.这点其实和多线程关系不大,scrapy的并发并不是采用多线程来实现,它是一个twisted应用,通过异步非阻塞来达到并发。

4.Python中当你想要提高执行效率,大部分开发者是通过编写多进程来提高运行效率,使用multiprocessing进行并行编程,当然,你可以编写多进程爬虫来爬取信息,缺点是每个进程都会有自己的内存,数据多的话,内存会吃不消。

5.使用线程有什么缺点呢,缺点就是你在编写多线程代码时候,要注意死锁的问题、阻塞的问题、以及需要注意多线程之间通信的问题(避免多个线程执行同一个任务)。

二、了解threading

我们通过 threading 模块来编写多线程代码,或者你可以使用 from concurrent.futures import ThreadPoolExecutor (线程池)也可以达到同样的目的,线程池的知识我会在后续讲。

我们先看怎么编写线程代码,以及它如何使用,简单的示例:


 

import time
from threading import Thread

def countdown(n):
	while n > 0:
		print('T-minus', n)
		n -= 1
		time.sleep(5)
	
t = Thread(target=countdown, args=(10,))
t.start()

countdown是一个计数的方法,正常执行它,我们一般使用countdown(10),就可以达到执行的目的,当你通过线程去调用它时,首先你需要从threading模块中引入Thread,然后,t = Thread(target=countdown, args=(10,)),当你创建好一个线程对象后,该对象并不会立即执行,除非你调用它的 start方法(当你调用 start() 方法时,它会调用你传递进来的函数,并把你传递进来的数传递给该函数),这就是一个简单的线程执行的例子。

你可以查询一个线程对象的状态,看它是否还执行:

if t.is_alive():
	print('Still running')
else:
	print('Completed, Go out !')

Python 解释器直到所有线程都终止前仍保持运行。对于需要长时间运行的线程或 者需要一直运行的后台任务,你应当考虑使用后台线程。

t = Thread(target=countdown, args=(10,), daemon=True)
t.start()

 如果你需要终止线程,那么这个线程必须通过编程在某个特定点轮询来退 出。你可以像下边这样把线程放入一个类中:

class CountDownTask:
    def __init__(self):
        self._running = True

    def terminate(self):
        self._running = False

    def run(self, n):
        while self._running and n > 0:
            print('T-minus', n)
            n -= 1
            time.sleep(5)

if __name__ == '__main__':
    c = CountDownTask()
    t = Thread(target=c.run, args=(10,))
    t.start()
    c.terminate()
    t.join()

 

三、多线程初体验

上面的代码都是单线程,下面我们来看看多线程,并使用它来编写多线程爬虫,不过,在真正编写多线程爬虫之前,我们还要为编写多线程做准备,如何保持各线程之间的通信,在这里,

你可能感兴趣的:(后端,python,python,爬虫,开发语言,学习,pycharm)