利用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基于urllib实现按照百度音乐分类下载mp3的方法
May 25 Python
python实用代码片段收集贴
Jun 03 Python
详解python时间模块中的datetime模块
Jan 13 Python
Python的消息队列包SnakeMQ使用初探
Jun 29 Python
Python系统监控模块psutil功能与经典用法分析
May 24 Python
python 基本数据类型占用内存空间大小的实例
Jun 12 Python
学生信息管理系统python版
Oct 17 Python
提升Python程序性能的7个习惯
Apr 14 Python
Python使用type关键字创建类步骤详解
Jul 23 Python
Python任务自动化工具tox使用教程
Mar 17 Python
python让函数不返回结果的方法
Jun 22 Python
方法汇总:Python 安装第三方库常用
Apr 26 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
IIS环境下快速安装、配置和调试PHP5.2.0
2006/12/17 PHP
PHP提取数据库内容中的图片地址并循环输出
2010/03/21 PHP
php数组对百万数据进行排除重复数据的实现代码
2010/06/08 PHP
QQ登录 PHP OAuth示例代码
2011/07/20 PHP
谈谈关于php的优点与缺点
2013/04/11 PHP
PHP正则替换函数preg_replace和preg_replace_callback使用总结
2014/09/22 PHP
PHP中的闭包(匿名函数)浅析
2015/02/07 PHP
浅谈laravel aliases别名的原理
2019/10/24 PHP
js+css实现tab菜单切换效果的方法
2015/01/20 Javascript
基于jQuery+JSON的省市二三级联动效果
2015/06/05 Javascript
jQuery实现简单的点赞效果
2020/05/29 Javascript
bootstrap滚动监控器使用方法解析
2017/01/13 Javascript
angularjs+bootstrap菜单的使用示例代码
2017/03/07 Javascript
详解js动态获取浏览器或页面等容器的宽高
2019/03/13 Javascript
详解vue 在移动端体验上的优化解决方案
2019/05/20 Javascript
JS highcharts动态柱状图原理及实现
2020/10/16 Javascript
[01:15:16]DOTA2-DPC中国联赛 正赛 Elephant vs Aster BO3 第一场 1月26日
2021/03/11 DOTA
Python 的 with 语句详解
2014/06/13 Python
python实现在windows下操作word的方法
2015/04/28 Python
CentOS 7下安装Python 3.5并与Python2.7兼容并存详解
2017/07/07 Python
在CMD命令行中运行python脚本的方法
2018/05/12 Python
对python判断ip是否可达的实例详解
2019/01/31 Python
python TCP包注入方式
2020/05/05 Python
python list的index()和find()的实现
2020/11/16 Python
HTML5离线缓存在tomcat下部署可实现图片flash等离线浏览
2012/12/13 HTML / CSS
实例讲解使用SVG制作loading加载动画的方法
2016/04/05 HTML / CSS
德国隐形眼镜店:LuckyLens
2018/07/29 全球购物
比利时家具购买网站:Home24
2019/01/03 全球购物
爱尔兰电脑、家电和家具购物网站:Buy It Direct
2019/07/09 全球购物
采购内勤岗位职责
2013/12/10 职场文书
校庆接待方案
2014/03/18 职场文书
机关保密承诺书
2014/06/03 职场文书
学校捐书活动总结
2015/05/08 职场文书
个人借条范本
2015/05/25 职场文书
经典法律座右铭(50句)
2019/08/15 职场文书
python神经网络学习 使用Keras进行回归运算
2022/05/04 Python