python------携程的应用

1:GIL 是什么?
全局解释器锁 (英语: Global Interpreter Lock,缩写GIL)是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行即便在多核心处理器上,使用 GIL 的解释器也只允许同一时间执行一个线程。

2:为什么有GIL这个东西?
原因
简而言之: Python设计初期,为了规避并发问题引入了GIL,现在想去除却去不掉了!

为了解决多线程之间数据完整性和状态同步问题Python中对象的管理

3存在问题

由于GIL的存在
即使电脑有多核CPU
单个时刻也只能使用1个
相比并发加速的C++/JAVA所以慢

4:怎样规避GIL带来的限制?
1、多线程 threading 机制依然是有用的,用于IO密集型计算
因为在 I/0 (read,write,send,recv,etc.)期间,线程会释放GIL,实现CPU和IO的并行因此多线程用于IO密集型计算依然可以大幅提升速度
但是多线程用于CPU密集型计算时,只会更加拖慢速度

2:来到了这里我们开始说异步协程

5:协程

基本步骤

#1:导入包
import asyncio
#2定义协程函数
async def demo(data):
    print(data)

get=demo(1)#协程对象
#3:获取事件循环
loop=asyncio.get_event_loop()
loop.run_until_complete(get)#可以放进去协程对象
"""在python3.7以上提供了更简便的方法"""
#3:获取事件循环
asyncio.run(get)#这一行代码可以代替9,10二行的代码

"""
注意:
执行协程函数创建协程对象,
函数内部代码不会执行,如果想要运行协程函数内部代码
必须要讲协程对象交给事件循环来处理
"""

await的简单介绍:

await后面可以+可以等待的对象(协程对象,Future,Task对象>>>io等待);

等待这个io,当这个io操作完成后代码继续往下走,(没有完成不走下面的代码)

import asyncio
async def others() :
    print("start")
    await asyncio.sleep(2)
    print('end')
    return"返回值"
async def func():
    print("执行协程函数内部代码")
    """
    遇到IO操作挂起当前协程(任务),
    等IO操作完成之后再继续往下执行。
    当前协程挂起时,事件循环可以去执行其他协程 (任务)。
"""
    response1 = await others()
    print("IO请求结束,结果为:",response1)
    response2 = await others()
    print("IO请求结束,结果为:", response2)
asyncio.run(func())

#结果为:
执行协程函数内部代码
start
end
IO请求结束,结果为: 返回值
start
end
IO请求结束,结果为: 返回值

await就是等待对象的值得到结果之后再继续向下走。

task对象的简单介绍:
在事件循环中添加多个任务的.
Tasks用于并发调度协程,通过asyncio.create_task(协程对象)的方式创建Task对象,这样可以让协程加入事件循环中等待被调度执行。除了使用asyncio.create_task(函数以外,还可以用低层级的loop.create_task0或ensure_future(函数。不建议手动实例化 Task 对象。

注意:asyncio.create_task0 函数在 Python 3.7 中被加入。在 Python 3.7之前,可以改用低层级的asyncio.ensure_future()函数

import asyncio
async def func():
    print(1)
    await asyncio.sleep(2)
    print(2)
    return"返回值"
async def main() :
    print("main开始")
    task_Tist =[
    asyncio.create_task(func(),name='n1'),
    asyncio.create_task(func(),name='n2')
    ]
    print("main结束")
    done,pending = await asyncio.wait(task_Tist)
    print(done)
asyncio.run(main())

#结果为:
main开始
main结束
1
1
2
2
{<Task finished name='n1' coro=<func() done, defined at D:/py-work/dasdas.py:41> result='返回值'>, <Task finished name='n2' coro=<func() done, defined at D:/py-work/dasdas.py:41> result='返回值'>}

 await里面不能放列表,所以把他放asyncin.wait()里面

import asyncio
async def func():
    print(1)
    await asyncio.sleep(2)
    print(2)
    return "返回值"
task_list =[
    func() ,
    func()
    ]
done,pending= asyncio.run( asyncio.wait(task_list) )
print(done)

#结果为:
1
1
2
2
({<Task finished name='Task-2' coro=<func() done, defined at D:/py-work/dasdas.py:41> result='返回值'>, <Task finished name='Task-3' coro=<func() done, defined at D:/py-work/dasdas.py:41> result='返回值'>}, set())

案例

import asyncio
import aiohttp #发异步请求的把包
urls = [
    "url1",
    "url2",
    url3,
]
async def aiodownload(url):
    name = url.rsplit('/', 1)[1]#从右往左用“/”切,切1刀,成2份,然后取第2个位置的元素:ptgvyyrnvgn.jpg;使用"/",/做分隔符
    # 因为异步协程,需要用async,又因为request不用close可以用上下文管理器with,所以这么写
    async with aiohttp.ClientSession() as session:#aiohttp.ClientSession()=requests()
        async with session.get(url) as resp:  # 相当于:resp.get()
            # 这里请求成功,开始写入文件
            # resp.content.read()  # 相当于 resp.content
            # resp.text() # 相当于resp.text
            # resp.json() # 相当于resp.json()
            with open(name, mode='wb') as f:
                f.write(await resp.content.read())  # 保存文件,并用await挂起
    print('结束')
    # s = aiohttp.ClientSession  <==> requests    异步协程请求的这相当于requests
    # 发送请求
    # 得到图片
    # 保存内容
    #rsplit将字符串拆分为列表
async def main():
    #tasks = []
    #for url in urls:
        #tasks.append(asyncio.create_task(aiodownload(url)))
    #await asyncio.wait(tasks)

    #或者为下面这个格式也行
    tasks=[asyncio.create_task(aiodownload(url))for url in urls]
    await asyncio.wait(tasks)
if __name__ == '__main__':
    asyncio.run(main())
    #下面这个写法在python3.10中不使用了
    #loop = asyncio.get_event_loop()  # asyncio.get_event_loop():获取一个事件循环
    #loop.run_until_complete(main())  # run_until_complete():将任务放到任务列表

import requests
import asyncio
import aiohttp
import aiofiles #可以使用中创建异步的包
def get_3m3u8(url):
    headers = {
        "user-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.52",

        'referer':"https://vip.dysmz.top/"
    }
    resp=requests.get(url=url,headers=headers).text
    with open ('get_sencod_m3u8',mode='w',encoding='utf-8')as fp:
        fp.write(resp)
    asyncio.run(aiodowblong(resp))
def get_sencod_m3u8(url):
    headers = {
        "user-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.52"
    }
    with open('get_first_m3u8',mode='r',encoding='utf-8')as fp:
        for m3u81 in fp:
            line=m3u81.strip()#移除字符串头尾指定的字符;该方法只能删除开头或是结尾的字符
            if line.startswith("#"):#如果以#开头的话
                continue
    aiodownlong_sencod_M3U8=url+line
    get_3m3u8(aiodownlong_sencod_M3U8)
async def aiodown0(url,name):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            async with aiofiles.open(f"./video/{name}", mode="wb") as fp:
                await fp.write(await resp.content.read())
    print(f"{name}下载完成")
async def aiodowblong(url):#拿所以的下载网站
    tasks=[]
    async with aiofiles.open("get_sencod_m3u8",mode="r",encoding="utf-8")as fp:
        async for line in fp:
            if line.startswith('#'):
                continue
            line=line.strip()
            name=line.split("hls/")[1]
            tasks.append(asyncio.create_task(aiodown0(line,name)))
        await asyncio.wait(tasks)
def get_first_m3u8(url):
    headers = {
        "user-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.52"
    }
    resp=requests.get(url=url,headers=headers).text
    with open("get_first_m3u8",mode="w",encoding="utf-8")as fp:
        fp.write(resp)
if __name__=="__main__":
    url='https://new.qqaku.com/20220819/tHStWHoI/index.m3u8'
    first_m3u8_url=url.split("/20220819/")[0]
    get_first_m3u8(url)
    get_sencod_m3u8(first_m3u8_url)

import requests
import aiohttp
import os
import asyncio
import time
if not os.path.exists('./西游记'):
    os.mkdir('./西游记')
async def aiodownolong(cid,title):
    url="........."
    async with aiohttp.ClientSession()as session:
        async with session.get(url)as resp:
            d=await resp.json()
            with open(f'./西游记/{title}',mode="w",encoding="utf-8")as fp:
                fp.write(d['data']['novel']['content'])
    print(f'{title}爬取成功!!')
async def get_cat(url):
    heard = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.26"
    }
    resp=requests.get(url=url,headers=heard)
    dic=resp.json()
    task=[]
    for item in dic['data']['novel']['items']:
        title=item['title']
        cid=item['cid']
        task.append(asyncio.create_task(aiodownolong(cid,title)))
    await asyncio.wait(task)
if __name__ == '__main__':
    a=time.time()
    url='.......'
    b=time.time()
    asyncio.run(get_cat(url))
    print(b-a)


 

import requests
import os
import asyncio
import aiofiles  #可以创建一个异步的包
import aiohttp
async def tupian(page):


    data = {
        'per_page': '12',
        'page': page,
        'seo_tags': 'true'
    }
    heard={
        "secret-key": 'H2jk9uKnhRmL6WPwh89zBezWvr',
        "referer": "https://www.pexels.com/zh-cn/@tkirkgoz/",
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
    }

    url="..........."

    request=requests.get(url=url,headers=heard,params=data) #params参数
    request.encoding="utf-8"
    request=request.json()
    data_data=request["data"]
    task=[]
    for id in data_data:
        id=id["id"]
        task.append(asyncio.create_task(downlong(id)))
    await asyncio.wait(task)
async def downlong(id):

    # 创建一个文件夹(包)
    if not os.path.exists('./picture'):
        os.mkdir('./picture')
    url=f"https://images.pexels.com/photos/{id}/pexels-photo-{id}.jpeg?auto=compress&cs=tinysrgb&w=150&lazy=load"
    async with aiohttp.ClientSession() as session:
        async with session.get(url=url)as resp:
            async with aiofiles.open(f"./picture/+{id}.jpg",mode="wb")as fp:
                # with open(f"./picture/+{id}.jpg",mode="wb")as fp:
                fp.write(await resp.content.read())
    print(f"{id}下载成功")
def run():

    a=int(input("请输入你要爬取的页数:"))
    for page in range(3,a+1):
        #asyncio.run(tupian(page)) #报错Event loop is closed
        loop = asyncio.get_event_loop()
        loop.run_until_complete(tupian(page))
        """
        总而言之是asyncio.run()会自动关闭循环,
        并且调用_ProactorBasePipeTransport.__del__报错,
        而asyncio.run_until_complete()不会.
        """

if __name__ =="__main__":
    run()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值