多线程学习笔记

提高爬取效率

线程  进程

线程:执行单位(例子:公司里的员工)

进程:资源单位(例子:公司里的资源)

一个进程至少里一个线程

d46f743f3e954b57ae4248ffa7436b90.png

启动一个程序 默认一个主线程

多线程

第一套写法

if __name__=='__main__':

当程序是主程序运行时 才运行

例如 被当作模块导入 其他程序时 其下代码不会运行

导入库

from threading import Thread

创建线程并安排任务

def cc():    for i in range(20):        print(i)t=Thread(target=cc())#创建一个进程  安排任务为target函数t.start()#多线程设为可以开始的状态,具体开始的时间由cpu决

例子

def cc():    for i in range(20):        print('第一个',i)cc()for ii in range(5):    print('第二个',ii)

这个程序    他是先执行第一个 再执行第二个   

使用多线程

from threading import Threaddef cc():    for i in range(1000):        print('第一个',i)t=Thread(target=cc)# 注意只有函数名  没有括号t.start()for ii in range(1000):    print('第二个',ii)

会发现  第一个 夹杂着第二个(target调用时注意函数不要加括号)

原理图

f6cdabd651d04a579d836f0e00f4d4e2.png两个线程

t2   t3.......可以启用多个线程

创建线程  任务函数的参数传递

from threading import Threaddef cc(name):    for i in range(1000):        print(name,i)t=Thread(target=cc,args=('周杰伦',))# 注意只有函数名  没有括号t.start()

 通过 arg参数 传递参数  

记住参数必须是元组    一个参数就加上括号

第二套写法

 继承  定义子类

from threading import Threadclass MyThread(Thread):    def run(self):        for i in range(1000):            print('子进程',i)t=MyThread()t.start()#默认执行run   记住千万不要t.run() 那样相当于调用还是单线程、#主进程for ii in range(1000):    print('主进程',ii)

记住千万不能  t.run()  那样相当于调用 是单线程

多进程

开创多进程 消耗的资源大于多线程

导入库

from multiprocessing import Process

创建子进程

同子线程

from multiprocessing import Processdef func():    for i in range(1000):        print('子进程',i)if __name__=='__main__':    t = Process(target=func)  # 创建子进程    t.start()    for ii in range(1000):        print('主进程', ii)

执行结果  同多线程

线程池与进程池

线程池:一次开辟一些线程  用户直接给线程池提交任务

线程任务交给线程池  我们不用管

导入线程,进程池 库

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor

线程池的创建

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutordef fn(name):#创建一个任务    for i in range(1000):        print(name,'  ',i)with ThreadPoolExecutor(50) as t:#创建一个50个线程的线程池    for ii in range(100):#分配100个任务        t.submit(fn,name="线程{0}".format(ii))#提交任务的函数print('123')#外面的程序 只有等到线程任务执行完才执行

 多线程一次性提交多个任务用for 循环

实战

农业网     1单个页面如何提取

                 2多个页面如何提取

思路 重要

定义函数   参入url参数可以爬取  url

再用线程池执行

适合多页的数据

代码

#爬取多页数据   效率高用线程池from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutorfrom lxml import etreeimport requestsdef pachon(url):#这是一个功能函数    # 爬取电影天堂 2019必看热片为例    reqs = requests.get(url)    reqs.encoding = 'gb2312'    tree = etree.HTML(reqs.text)    res = tree.xpath('//*[@id="content"]/div/div/div/div[1]/div[2]/div/table/tbody/tr')    jishu = 0  # 计数器控制每行11个书名    for i in res:        name = i.xpath('./td[2]/div/a[1]/text()')        print(name)        with open('xiaoshuo.txt', 'a') as fp:            fp.write(str(name))            if jishu == 5:                fp.write('
')                jishu = 0        jishu += 1#线程池with ThreadPoolExecutor(5) as t:#创建一个5个线程的线程池    for ii in range(1,6):#爬取前5页数据        url = 'http://www.quannovel.com/shuku/0_0_0_0_0_' + str(ii) + '_0.html'        t.submit(pachon,url)        print(url,'已经完成')

注意这是多个线程同时进行的 所以顺序可能会乱

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值