Python的多线程爬虫只能运行在单核上,各个线程以并发的方法运行。由于GIL(全局解释器锁)的存在,多线程爬虫并不能充分地发挥多核CPU的资源。
作为提升Python网络爬虫速度的另一种方法,多进程爬虫则可以利用CPU的多核,进程数取决于计算机CPU的处理器个数。由于运行在不同的核上,各个进程的运行是并行的。在Python中,如果我们要用多进程,就要用到multiprocessing这个库。
使用multiprocessing库有两种方法,一种是使用Process + Queue的方法,另一种方法是使用Pool + Queue的方法。
multiprocessing对于习惯使用threading多线程的用户非常友好,因为它的理念是像线程一样管理进程,和threading很像,而且对于多核CPU的利用率比threading高得多。
当进程数量大于CPU的内核数量时,等待运行的进程会等到其他进程运行完毕让出内核为止。因此,如果CPU是单核,就无法进行多进程并行。
我们可以通过下面的函数了解我们电脑CPU的核心数量:
from multiprocessing import cpu_count
print(cpu_count())
结果是8,说明我的电脑是8核。
from multiprocessing import Process, Queue
import time
import requests
link_list = []
with open('alexa.txt', 'r') as file:
file_list = file.readlines()
for eachone in file_list:
link = eachone.split('\t')[1]
link = link.replace('\n','')
link_list.append(link)
start = time.time()
#MyProcess继承Process类
class MyProcess(Process):
def __init__(self, q):
Process.__init__(self)
self.q = q
def run(self):
print("Starting ", self.pid)
while not self.q.empty():
crawler(self.q)
print("Exiting ", self.pid)
def crawler(q):
url = q.get(timeout=2)
try:
r = requests.get(url, timeout=5)
print(q.qsize(),r.status_code, url)
except Exception as e:
print(q.qsize(), url, 'Error: ', e)
if __name__ == '__main__':
workQueue = Queue(1000)
#填充队列
for url in link_list:
workQueue.put(url)
for i in range(0, 8):
p = MyProcess(workQueue)
p.daemon = True`
p.run()
p.join()
end = time.time()
print('Process + Queue多进程爬虫的总时间为:', end-start)
print('Main process Ended!')
在上述代码中,我们在多进程中设置了daemon,p.daemon = True
,在多进程中,每个进程都可以单独设置它的属性,如果将daemon设置为True,当父进程结束后,子进程就会自动被终止。