600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 爬虫-python -(8) 多线程与多进程操作以及线程池 异步操作

爬虫-python -(8) 多线程与多进程操作以及线程池 异步操作

时间:2021-03-07 07:28:30

相关推荐

爬虫-python -(8) 多线程与多进程操作以及线程池 异步操作

文章目录

1.通过异步操作提高爬虫效率2.多线程3.多进程4.线程池与进程池5.线程池实例-新发地菜价保存6.总结

1.通过异步操作提高爬虫效率

一般爬虫过程为,请求网页-响应请求-从响应中提取数据-保存有用数据,每次都是这样,如果有大量的网站,重复这样操作肯定很慢。

现在可以通过异步操作,提高爬虫的效率。

这里异步操作可以是多线程,多进程以及协程。

这里有存在两个容易混淆的定义,线程和进程

进程是资源单位(某几块地方) 每个进程必须包含至少一个线程

线程是执行单位 (这块地方工作的人)

2.多线程

创建多线程有两种方法,第一种是直接调用函数thread函数,将需要创建的新进程函数和传参放入,然后start,就可以开始执行。

import threadingdef fun (n,m):for i in range(n):print('子线程',i+m)if __name__=='__main__':n=100m=200T=threading.Thread(target=fun,args=(n,m)) #创建一个新的线程并安排任务 通过args传递参数 只剩下一个参数时候后面的逗号必须要T.start() #可以开始工作,后面要看cpu是否给他分配for i in range(n):print('主线程',i)

也可以通过类的继承方法,创建一个继承thread的类,直接调用新类,即可。

class MyThread(threading.Thread):def __init__(self,funs,args):threading.Thread.__init__(self) #不要忘记调用Thread的初始化方法self.funs=funsself.args=argsdef run(self): #这里需要写成固定的run 因为线程执行时候被执行的就是runself.funs(*self.args)def fun(m): for i in range(100):print('子线程1',i+m)def fun1(m): for i in range(m):print('子线程2',i)if __name__ == '__main__':T=MyThread(fun,(100,)) #继承thread类的方法T2=MyThread(fun1,(200,)) #继承thread类的方法T.start()T2.start()T.join() #等待t这个线程执行完毕 再执行下面的线程for i in range(100):print('主线程',i)

3.多进程

多进程和多线程使用过程很相似,但是里面实现过程,完全不同,因为多进程用的比较少,所以就简单了解下

from multiprocessing import Processdef fun(m):for i in range(m):print('子进程',i)if __name__=='__main__':P=Process(target=fun,args=(100,))P1=Process(target=fun,args=(100,)) P.start()P1.start()for i in range(100):print('主进程',i)

4.线程池与进程池

由于用的时候可能要创建很多线程,但是要不浪费线程,要重复使用这些线程,就出现了线程池和进程池的概念。

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutordef fun(name):for i in range(100):print(name,i)if __name__=='__main__':with ThreadPoolExecutor(5) as T:#线程池创建5个线程for i in range(20):#给线程池20个任务T.submit(fun,name=f'线程{i}') #提交任务#必须等以上结束下面才会执行 with 里面相当于有start 和join的功能print('over!!')

5.线程池实例-新发地菜价保存

新发地菜价

import requestsfrom concurrent.futures import ThreadPoolExecutorimport csvimport timefrom collections import dequeurl = '/getPriceData.html'data_queue = deque([])def getPriceData(pagenumber):data={'limit': 20,'current': pagenumber}reap = requests.post(url= url,data=data)reapcontent= reap.json()['list']reap.close()data_queue.append(['PG-%d'%pagenumber])for i in reapcontent:data_queue.append([i['prodCat'],i['prodName'],i['avgPrice'],i['highPrice'],i['lowPrice'],i['place'],i['pubDate']])#print(pagenumber,'over!!') def dataStorage(): #保存数据with open('新发地菜价.csv',mode='w+',encoding='utf-8',newline='') as f: #保存文件csvWrite = csv.writer(f)while True:try:dataer = data_queue.popleft()csvWrite.writerow(dataer) #将结果保存到csvexcept:print('数据已经全部保存!')breakif __name__=='__main__':time_start = time.time() #开始计时with ThreadPoolExecutor(20) as t: #进程池里面进程数量为10for i in range(200): #给进程池100个任务 打开200个t.submit(getPriceData,pagenumber=i+1)dataStorage()print('over!!')time_end = time.time() #结束计时time_c= time_end - time_start #运行所花时间print('time cost', time_c, 's')

6.总结

今天的多线程其实用途蛮大,对其他语言也有启发性,挺好的,今天就看这么多把。明天继续。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。