当前位置: 首页 > 科技观察

人工制品!比requests更易用的高效Python爬虫框架!

时间:2023-03-20 10:17:09 科技观察

最近公司的Python后台项目进行了重构,整个后台逻辑基本改成了“异步”协程。看着满屏的用asyncawait(协程在Python中的实现)装饰的代码,顿时感到迷茫和茫然。虽然之前知道什么是“协程”,但一直没有深入探讨,所以就趁着这个机会学习一下。让我们开始什么是协程?简单的说,协程是一个基于线程的,但是比线程更轻量级的存在。对于系统内核来说,协程是不可见的,所以这种由程序员自己管理的轻量级线程通常被称为“用户空间线程”。协程比多线程好在哪里?1、线程的控制权在操作系统手中,协程的控制权完全在用户手中。因此,使用协程可以减少程序运行时的上下文切换,有效提高程序的运行效率。2、创建线程时,默认分配给线程的栈大小为1M,协程更轻,接近1K,所以同一块内存可以开更多的协程。3、由于协程的本质不是多线程而是单线程,所以不需要多线程的锁机制。因为只有一个线程,所以不存在同时写变量引起的冲突。协程中不需要加锁来控制共享资源,只需要判断状态即可。所以协程的执行效率远高于多线程,也有效避免了多线程中的竞争关系。协程的适用&不适用场景适用场景:协程适用于阻塞和需要大量并发的场景。不适用场景:协程不适合计算量大的场景(因为协程的本质是单线程来回切换)。如果遇到这种情况,应该使用其他方式解决。异步http框架httpx初探至此我们应该对“协程”有了一个大概的了解,但是故事讲到这里,相信有小伙伴还是满心疑惑:“协程”是如何帮助接口测试的?别着急,答案就在下方。相信用过Python进行过接口测试的朋友对requests库都不陌生。requests中实现的http请求是同步请求,但实际上基于http请求的IO阻塞特性,非常适合使用协程实现“异步”的http请求,以提高测试效率。相信很久以前就有人注意到了这一点,于是在Github上一番摸索之后,果不其然,终于找到了一个支持协程“异步”调用的开源库:http:httpx.什么是httpxhttpx是一个开源库,几乎继承了requests的所有特性,支持“异步”http请求。简单的说,httpx可以认为是re??quests的加强版。接下来大家可以跟着小编一起来体验httpx的强大。httpx的安装非常简单,Python3.6以上环境即可执行。pipinstallhttpx最佳实践俗话说,效率决定成败。我使用了httpx异步和同步方式来对比批量http请求的耗时。让我们来看看结果。首先我们看一下同步http请求的耗时表现:)}:{sign}2+1{response}')sync_start=time.time()[sync_main(url='http://www.baidu.com',sign=i)foriinrange(200)]sync_end=time.time()print(sync_end-sync_start)代码比较简单,可以看到在sync_main中,同步http访问百度200次。运行后输出如下(截取了部分关键输出...):sync_main:<_MainThread(MainThread,started4471512512)>:192:200sync_main:<_MainThread(MainThread,started4471512512)>:193:200sync_main:<_MainThread(MainThread,启动4471512512)>:194:200sync_main:<_MainThread(MainThread,启动4471512512)>:195:200sync_main:<_MainThread(MainThread,启动4471512512)>:196:200sync_main:<_MainThread:24525,启动197:200sync_main:<_MainThread(MainThread,started4471512512)>:198:200sync_main:<_MainThread(MainThread,started4471512512)>:199:20016.56578803062439可以看到在上面的输出中,主线程还没有切换(因为它是单线程。嘿!)请求是顺序执行的(因为它是一个同步请求)。该程序总共花费了16.6秒来运行。让我们尝试一个“异步”的http请求:threading.current_thread()}:{sign}:{status_code}')loop=asyncio.get_event_loop()tasks=[async_main(url='http://www.baidu.com',sign=i)foriinrange(200)]async_start=time.time()loop.run_until_complete(asyncio.wait(tasks))async_end=time.time()loop.close()print(async_end-async_start)上面的代码使用async_main中的asyncawaitkeyword实现“异步”http,通过asyncio(异步io库请求百度首页200次,打印耗时)。运行代码后,可以看到如下输出(截取了部分关键输出...)。async_main:<_MainThread(MainThread,启动4471512512)>:56:200async_main:<_MainThread(MainThread,启动4471512512)>:99:200async_main:<_MainThread(MainThread,启动4471512512)>:67:200MainThread,启动(:93:200ASYNC_MAIN:<_MainThread(Mainthread,开始4471512512)>:125:200SASYNC_MAIN:<_mainthread:<_mainthread(mainthread,开始,开始4471512512)可以看到虽然顺序乱了(56,99,67...)(这是因为程序在不断的在协程之间切换),但是主线程并没有切换(协程本质上还是单线程的).该程序总共耗时4.5秒。这比同步请求所用的16.6秒快了近73%!俗话说,一步一个脚印,一步一个脚印。在耗时上,“异步”httpx确实比同步http快很多。当然,“协程”不仅可以在请求效率方面赋能接口测试,掌握“协程”之后,相信小伙伴们的技术水平也能更上一层楼,从而设计出更好的测试框架.好了,今天分享的内容就这些了,喜欢的话就点个赞吧~