python爬取异步加载的网页,Python异步请求

  python爬取异步加载的网页,Python异步请求

  所谓“异步IO”,就是你发起了一个IO操作,却不用等它结束。你可以继续做其他的事情,结束的时候会通知你。

  Asyncio是一种并发方式。对于Python来说,也可以通过线程和多处理来实现并发。

  Asyncio并没有带来真正的并行。当然,由于GIL(全局解释器锁)的存在,Python的多线程并不能带来真正的并行性。

  可以分配给asyncio的任务称为协程。一个进程可以放弃执行并把机会让给其他进程(即放弃或等待)。`

  要定义协同学的定义,需要使用async def语句。

  async def do _ some _ work(x):pass do _ some _ work是一个协同进程。

  确切的说,do_some_work是一个协整函数,可以用asyncio.iscoroutinefunction来验证:

  打印(asyncio。iscoroutinefunction(do _ some _ work))# true这个协同进程没有做任何事情。我们让它休眠几秒钟,以模拟实际工作负载:

  async def do _ some _ work(x):print( waiting str(x))等待asyncio。睡眠(x)在解释wait之前,有必要解释一下协同学能做什么。解成能:

  *等待一个未来结束*等待另一个协程(产生一个结果,或者抛出一个异常)*产生一个结果给等待它的协程*抛出一个异常给协程asyncio.sleep等待它的也是一个协程,所以await asyncio.sleep(x)只是在等待另一个协程。参见asyncio.sleep的文档:

  在给定时间(秒)后完成的Sleep (delay,result=none,*,loop=none)协程。运行协程调用协程函数,协程并没有开始运行,只是返回一个协程对象,可以通过asyncio.iscoroutine验证:

  print(asyncio . isco routine(do _ some _ work(3))# true这里还会引发一个警告:

  Async1.py: 16:运行时警告:协程 do _ some _ work 从未被等待打印(asyncio.is协程(do _ some _ work (3)))有两种方法使此协作对象运行:

  *在另一个已经运行的协程中使用“await”等待它*通过“确保_未来”函数计划它的执行。简单来说,协程只有在loop运行时才能运行。

  我们先获取当前线程的默认循环,然后把协同对象交给loop.run_until_complete,然后协同对象就在循环中运行了。

  loop=asyncio . get _ event _ loop()loop . Run _ until _ complete(do _ some _ work(3))Run _ until _ complete是一个阻塞调用,直到协同进程结束才返回。这从函数名就不难看出。

  run_until_complete的参数是一个未来,但是wrap我们在这里传递给它的是协同对象。之所以会这样,是因为它做了内部检查,通过guarantee _ future函数把协同对象包装到了未来。所以,我们可以写得更清楚:

  loop . run _ until _ Complete(asyncio . guarantee _ future(do _ some _ work(3))完整代码:

  import asyncioasync def do _ some _ work(x):print( waiting str(x))await asyncio . sleep(x)loop=asyncio . get _ event _ loop()loop . Run _ until _ complete(do _ some _ work(3))运行结果。

  等待3三秒钟后,程序将被回调。如果进程是IO读操作,我们希望在它读完数据后得到通知,以便在下一步处理数据。这个要求可以通过给未来增加一个回调来实现。

  DEF done _ callback(FUTU):print( done )futu=asyncio . guarantee _ future(do _ some _ work(3))futu . add _ done _ callback(done _ callback)loop . run _ until _ complete(futu)多个协程为了给循环赋予多个协程,需要asyncio.gather函数。

  循环。run _ until _ complete (asyncio。收集(做一些工作(1),做一些工作(3))或首先将协同放入列表中:

  Coros=[do _ some _ work (1),do _ some _ work(3)]loop . run _ until _ complete(asyncio . gather(* coros))运行结果:

  等待3等待一等待三秒钟完成的这两个协程是并发运行的,所以等待的时间不是1 3=4 秒,而是以耗时较长的那个协程为准。

  参考函数聚集的文档:

  gather(*coros_or_futures,loop=None,return_exceptions=False)

  从给定的协程或将来的返回一个将来的聚合结果。发现也可以传未来给它:

  futus=[asyncio。assure _ future(do _ some _ work(1))、asyncio。assure _ future(do _ some _ work(3))]循环。run _ until _ complete(asyncio。收集(* futus))收集起聚合的作用,把多个未来包装成单个未来,因为循环运行直到完成只接受单个未来。

  运行直到完成和永远奔跑我们一直通过运行直到完成来运行循环,等到将来的完成,运行,直到完成也就返回了。

  async def do _ some _ work(x):print( Waiting str(x))await async io。sleep(x)print( Done )loop=asyncio。get _ event _ loop()coro=do _ some _ work(3)循环。运行直到完成(coro)输出:

  等待3等待三秒钟完成的程序退出现在改用永远奔跑:

  async def do _ some _ work(x):print( Waiting str(x))await async io。sleep(x)print( Done )loop=asyncio。get _ event _ loop()coro=do _ some _ work(3)asyn CIO。确保未来(coro)循环。永远运行()输出:

  等待3等待三秒钟完成的程序没有退出三秒钟过后,未来结束,但是程序并不会退出跑吧_永远会一直运行,直到停止被调用,但是你不能像下面这样调停止:

  循环。run _ forever()循环。停止()运行_永远不返回,停止永远也不会被调用。所以,只能在协程中调停止:

  async def do_some_work(loop,x):print( Waiting str(x))await async io。睡眠(x)打印(“完成”)循环。停止()这样并非没有问题,假如有多个协程在环里运行:

  阿辛西奥。assure _ future(do _ some _ work(loop,1))asyncio。assure _ future(do _ some _ work(loop,3))loop.run_forever()第二个协程没结束,循环就停止了——被先结束的那个协程给停掉的。

  要解决这个问题,可以用聚集把多个协程合并成一个未来,并添加回调,然后在回调里再去停止循环。

  async def do_some_work(loop,x):print( Waiting str(x))await async io。sleep(x)print( Done )def Done _ callback(loop,futu):loop。stop()loop=asyncio。get _ event _ loop()futus=asyncio。gather(do_some_work(loop,1),do_some_work(loop,3))futus。add _ Done _ callback(func工具。partial(Done _ callback,loop))loop.run_forever()其实这基本上就是运行直到完成的实现了,运行,直到完成在内部也是调用永远奔跑。

  闭环?以上示例都没有调用循环关闭,好像也没有什么问题。所以到底要不要调循环关闭呢?

  简单来说,循环只要不关闭,就还可以再运行。

  循环。run _ until _ complete(do _ some _ work(loop,1))循环。run _ until _ complete(do _ some _ work(loop,3))loop.close()但是如果关闭了,就不能再运行了:

  循环。run _ until _ complete(do _ some _ work(loop,1))循环。close()循环。run _ until _ complete(do _ some _ work(loop,3)) #此处异常建议调用循环关闭,以彻底清理环对象防止误用。

  聚集与等待和阿辛西奥,等等功能相似。

  coros=[do_some_work(loop,1),do_some_work(loop,3)]循环。run _ until _ complete(asyncio。等等(科罗斯))具体差别可请参见栈溢出的讨论:Asyncio.gather vs asyncio.wait。

  定时器C升压。澳洲安全情报局提供了超正析象管(图片Orthicon)对象计时器,但是计算机编程语言并没有原生支持计时器,不过可以用睡眠模拟。

  异步定义定时器(x,CB):futu=asyncio。assure _ future(asyncio。睡眠(x))浮图。add _ Done _ callback(CB)await futut=timer(3,lambda futu:print( Done ))循环。运行直到完成(t)

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: