利用PyCharm Profile分析异步爬虫效率详解


Posted in Python onMay 08, 2019

今天比较忙,水一下

下面的代码来源于这个视频里面提到的,github 的链接为:github.com/mikeckenned…(本地下载)

第一个代码如下,就是一个普通的 for 循环爬虫。原文地址。

import requests
import bs4
from colorama import Fore


def main():
 get_title_range()
 print("Done.")


def get_html(episode_number: int) -> str:
 print(Fore.YELLOW + f"Getting HTML for episode {episode_number}", flush=True)

 url = f'https://talkpython.fm/{episode_number}'
 resp = requests.get(url)
 resp.raise_for_status()

 return resp.text


def get_title(html: str, episode_number: int) -> str:
 print(Fore.CYAN + f"Getting TITLE for episode {episode_number}", flush=True)
 soup = bs4.BeautifulSoup(html, 'html.parser')
 header = soup.select_one('h1')
 if not header:
  return "MISSING"

 return header.text.strip()


def get_title_range():
 # Please keep this range pretty small to not DDoS my site. ;)
 for n in range(185, 200):
  html = get_html(n)
  title = get_title(html, n)
  print(Fore.WHITE + f"Title found: {title}", flush=True)


if __name__ == '__main__':
 main()

这段代码跑完花了37s,然后我们用 pycharm 的 profiler 工具来具体看看哪些地方比较耗时间。

点击Profile (文件名称)

利用PyCharm Profile分析异步爬虫效率详解

之后获取到得到一个详细的函数调用关系、耗时图:

利用PyCharm Profile分析异步爬虫效率详解

可以看到 get_html 这个方法占了96.7%的时间。这个程序的 IO 耗时达到了97%,获取 html 的时候,这段时间内程序就在那死等着。如果我们能够让他不要在那儿傻傻地等待 IO 完成,而是开始干些其他有意义的事,就能节省大量的时间。

稍微做一个计算,试用asyncio异步抓取,能将时间降低多少?

get_html这个方法耗时36.8s,一共调用了15次,说明实际上获取一个链接的 html 的时间为36.8s / 15 = 2.4s。**要是全异步的话,获取15个链接的时间还是2.4s。**然后加上get_title这个函数的耗时0.6s,所以我们估算,改进后的程序将可以用 3s 左右的时间完成,也就是性能能够提升13倍。

再看下改进后的代码。原文地址。

import asyncio
from asyncio import AbstractEventLoop

import aiohttp
import requests
import bs4
from colorama import Fore


def main():
 # Create loop
 loop = asyncio.get_event_loop()
 loop.run_until_complete(get_title_range(loop))
 print("Done.")


async def get_html(episode_number: int) -> str:
 print(Fore.YELLOW + f"Getting HTML for episode {episode_number}", flush=True)

 # Make this async with aiohttp's ClientSession
 url = f'https://talkpython.fm/{episode_number}'
 # resp = await requests.get(url)
 # resp.raise_for_status()

 async with aiohttp.ClientSession() as session:
  async with session.get(url) as resp:
   resp.raise_for_status()

   html = await resp.text()
   return html


def get_title(html: str, episode_number: int) -> str:
 print(Fore.CYAN + f"Getting TITLE for episode {episode_number}", flush=True)
 soup = bs4.BeautifulSoup(html, 'html.parser')
 header = soup.select_one('h1')
 if not header:
  return "MISSING"

 return header.text.strip()


async def get_title_range(loop: AbstractEventLoop):
 # Please keep this range pretty small to not DDoS my site. ;)
 tasks = []
 for n in range(190, 200):
  tasks.append((loop.create_task(get_html(n)), n))

 for task, n in tasks:
  html = await task
  title = get_title(html, n)
  print(Fore.WHITE + f"Title found: {title}", flush=True)


if __name__ == '__main__':
 main()

同样的步骤生成profile 图:

利用PyCharm Profile分析异步爬虫效率详解

可见现在耗时为大约3.8s,基本符合我们的预期了。

利用PyCharm Profile分析异步爬虫效率详解

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python实现博客文章爬虫示例
Feb 26 Python
关于Python 3中print函数的换行详解
Aug 08 Python
Python实现的归并排序算法示例
Nov 21 Python
浅谈Python实现Apriori算法介绍
Dec 20 Python
python实现自动发送邮件发送多人、群发、多附件的示例
Jan 23 Python
浅谈Pandas Series 和 Numpy array中的相同点
Jun 28 Python
python可视化实现KNN算法
Oct 16 Python
Python ArgumentParse的subparser用法说明
Apr 20 Python
Python学习笔记之装饰器
Aug 06 Python
利用python+ffmpeg合并B站视频及格式转换的实例代码
Nov 24 Python
pytorch锁死在dataloader(训练时卡死)
May 28 Python
Python中的嵌套循环详情
Mar 23 Python
Python数据类型之String字符串实例详解
May 08 #Python
Python数据类型之List列表实例详解
May 08 #Python
Python3使用TCP编写一个简易的文件下载器功能
May 08 #Python
详解Python的三种可变参数
May 08 #Python
Python数据类型之Tuple元组实例详解
May 08 #Python
基于腾讯云服务器部署微信小程序后台服务(Python+Django)
May 08 #Python
python中正则表达式与模式匹配
May 07 #Python
You might like
php 广告调用类代码(支持Flash调用)
2011/08/11 PHP
Admin generator, filters and I18n
2011/10/06 PHP
php curl模拟post提交数据示例
2013/12/31 PHP
php+ajax实时输入自动搜索匹配的方法
2014/12/26 PHP
在WordPress中获取数据库字段内容和添加主题设置菜单
2016/01/11 PHP
PHP实现普通hash分布式算法简单示例
2018/08/06 PHP
jQuery的实现原理的模拟代码 -1 核心部分
2010/08/01 Javascript
javascript数据结构与算法之检索算法
2015/04/04 Javascript
jquery实现仿Flash的横向滑动菜单效果代码
2015/09/17 Javascript
jQuery简单获取键盘事件的方法
2016/01/22 Javascript
js 截取或者替换字符串中的数字实现方法
2016/06/13 Javascript
Three.js学习之几何形状
2016/08/01 Javascript
jquery Easyui Datagrid实现批量操作(编辑,删除,添加)
2017/02/20 Javascript
基于Bootstrap的网页设计实例
2017/03/01 Javascript
使用svg实现动态时钟效果
2018/07/17 Javascript
微信小程序MUI侧滑导航菜单示例(Popup弹出式,左侧不动,右侧滑动)
2019/01/23 Javascript
javascript function(函数类型)使用与注意事项小结
2019/06/10 Javascript
jQuery 选择器用法基础入门示例
2020/01/04 jQuery
vue滑动吸顶及锚点定位的示例代码
2020/05/10 Javascript
python3实现TCP协议的简单服务器和客户端案例(分享)
2017/06/14 Python
详解Tensorflow数据读取有三种方式(next_batch)
2018/02/01 Python
Django框架模板文件使用及模板文件加载顺序分析
2019/05/23 Python
django-rest-swagger对API接口注释的方法
2019/08/29 Python
PyCharm2019安装教程及其使用(图文教程)
2019/09/29 Python
OpenCV利用python来实现图像的直方图均衡化
2020/10/21 Python
CAT鞋美国官网:CAT Footwear
2017/11/27 全球购物
美国婚礼装饰和活动用品批发供应商:Event Decor Direct
2018/10/12 全球购物
财务管理个人自荐书范文
2013/11/24 职场文书
小学运动会口号
2014/06/07 职场文书
拓展训练激励口号
2014/06/17 职场文书
贷款委托书
2014/08/01 职场文书
新生入学欢迎词
2015/01/26 职场文书
酒店开业主持词
2015/07/02 职场文书
学校教学管理制度
2015/08/06 职场文书
《颐和园》教学反思
2016/02/19 职场文书
导游词之凤凰古城
2019/10/22 职场文书