2021-08-20

今天学习的是异步爬取图片。接下来先把异步的大体框架写一下

"""
input()程序也是处于阻塞状态
request.get(url)在网络请求返回数据之前,程序也是处于阻塞状态的
一般情况下,当程序处于I/O操作的时候,线程就会处于阻塞状态
"""
import asyncio

"""
协程:当程序遇见了IO操作的时候,可以选择性的切换到其他任务上。
在微观上,是一个任务一个任务的进行切换,切换条件一般就是IO操作
在宏观上,我们能看到的其实是多个任务一起执行
多任务异步操作

#都是在单线程的条件下
"""
import time
"""def func():
    print("你好")
    time.sleep(3)#让当前的线程处于阻塞状态。cpu是不为我工作的
    print("你真的好吗?")

if __name__ == '__main__':
    func()"""

#python编写协程的程序(4种方法)
"""import asyncio
async def fun():
    print("你好啊,我叫赛利亚")
if __name__ == '__main__':
    g=fun()#函数是异步协程函数,此时函数执行得到的是一个协程对象
    print(g)
    asyncio.run(g)#协程程序运行需要asyncio模块的支持"""

import time

"""async def fun1():
    print("妖孽1")
    #time.sleep(4)#当程序出现了同步操作的时候,异步就中断了
    await asyncio.sleep(4)#异步操作的代码
    print("妖孽2")
async def fun2():
    print("只在1")
    # time.sleep(3)#当程序出现了同步操作的时候,异步就中断了
    await asyncio.sleep(3)  # 异步操作的代码
    print("只在2")
async def fun3():
    print("夜里哭1")
    # time.sleep(2)#当程序出现了同步操作的时候,异步就中断了
    await asyncio.sleep(2)  # 异步操作的代码
    print("夜里哭2")
if __name__ == '__main__':
    f1=fun1()
    f2=fun2()
    f3=fun3()
    tasks=[
        f1,f2,f3
    ]
    #一次性启动1多个任务(协程)
    t1=time.time()
    asyncio.run(asyncio.wait(tasks))
    t2=time.time()
    print(t2-t1)"""

async def fun1():
    print("妖孽1")
    await asyncio.sleep(4)#异步操作的代码
    print("妖孽2")
async def fun2():
    print("只在1")
    await asyncio.sleep(3)  # 异步操作的代码
    print("只在2")
async def fun3():
    print("夜里哭1")
    await asyncio.sleep(2)  # 异步操作的代码
    print("夜里哭2")
async def main():
    """
    第一种写法
    f1=func1()
    await f1 一般await挂起操作放在协程对象前面
    """
    #第二种写法
    tasks=[
        asyncio.create_task(fun1()),#变成task对象
        asyncio.create_task(fun2()),
        asyncio.create_task(fun3())
    ]
    await asyncio.wait(tasks)

if __name__ == '__main__':
    t1=time.time()
    asyncio.run(main())
    t2=time.time()
    print(t2-t1)

"""
在爬虫领域的应用
async def dowmload():
    print("准备开始下载")
    await asyncio.sleep(2)
    print("下载完成")
async def main():
    urls=[
        "",
        "",
        ""
    ]
    tasks=[]
    for url in urls:
        d=dowmload(url)#这是一个协程对象
        tasks.append(d)
    await asyncio.wait(tasks)
if __name__ == '__main__':
    asyncio.run(main())

 
"""

在我的理解中,就是先写一个爬取数据的函数,然后根据url的不同循环调用该函数,然后创建这些封装在tasks,最后在运行。(粗糙表达一下我自己的逻辑)

接下来用这个逻辑爬取几张图片。

#requests.get()同步的代码->异步操作aiohttp

import aiohttp
import asyncio

urls=[
    'http://kr.shanghai-jiuxin.com/file/2020/1031/191468637cab2f0206f7d1d9b175ac81.jpg',
    'http://kr.shanghai-jiuxin.com/file/2020/1031/a2c58d6d726fb7ef29390becac5d8643.jpg',
    'http://kr.shanghai-jiuxin.com/file/2020/1031/563337d07af599a9ea64e620729f367e.jpg'
]

async def aiodownload(url):
    name=url.rsplit("/",1)[1]#rsplit() 方法从右侧开始将字符串拆分为列表。
    #s=aiohttp.ClientSession()等同于requests.session()
    #requests.get(),requests.post()
    #s.get(),s.post()
    async with aiohttp.ClientSession()as session:
        async with session.get(url) as resp:#等价于resp=requests.get()
            #resp.content.read()等价于原来的resp.content
            #请求完毕写入文件
            #可以自己去学习aiofiles模块
            with open(name,mode="wb") as f:
                f.write(await resp.content.read())#读取内容是异步的,需要await挂起
    print(name,"打印完毕")

    """
    发送请求
    得到图片内容
    保存文件
    """

async def main():
    tasks=[]
    for url in urls:
        d=asyncio.create_task(aiodownload(url))
        tasks.append(d)
        #tasks.append(aiodownload(url))

    await asyncio.wait(tasks)




if __name__ == '__main__':
    loop=asyncio.get_event_loop()#获取当前事件循环。
    loop.run_until_complete(main())#运行直到 future ( Future 的实例 ) 被完成。一个 Future 代表一个异步运算的最终结果。

然后遇到的问题是:RuntimeError: Event loop is closed意思是RuntimeError:事件循环已关闭

参考文献:

https://blog.csdn.net/weixin_45787528/article/details/115450809
https://www.w3school.com.cn/python/ref_string_rsplit.asp

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值