利用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中正则表达式的用法实例汇总
Aug 18 Python
python实现百度语音识别api
Apr 10 Python
Python3连接SQLServer、Oracle、MySql的方法
Jun 28 Python
Python设计模式之享元模式原理与用法实例分析
Jan 11 Python
利用Python进行图像的加法,图像混合(附代码)
Jul 14 Python
python函数的作用域及关键字详解
Aug 20 Python
Python urlopen()和urlretrieve()用法解析
Jan 07 Python
pyinstaller打包找不到文件的问题解决
Apr 15 Python
Python 如何对文件目录操作
Jul 10 Python
Python 添加文件注释和函数注释操作
Aug 09 Python
python 基于opencv 实现一个鼠标绘图小程序
Dec 11 Python
python 基于pygame实现俄罗斯方块
Mar 02 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中opendir函数用法实例
2014/11/15 PHP
PHP上传图片、删除图片简单实例
2016/11/12 PHP
PHP Trait代码复用类与多继承实现方法详解
2019/06/17 PHP
HR vs CL BO3 第二场 2.13
2021/03/10 DOTA
解析JavaScript中的不可见数据类型
2013/12/02 Javascript
JavaScript中具名函数的多种调用方式总结
2014/11/08 Javascript
Javascript节点关系实例分析
2015/05/15 Javascript
基于Bootstrap3表格插件和分页插件实例详解
2016/05/17 Javascript
javascript 内置对象及常见API详细介绍
2016/11/01 Javascript
利用BootStrap的Carousel.js实现轮播图动画效果
2016/12/21 Javascript
AngularJS基于MVC的复杂操作实例讲解
2017/12/31 Javascript
React手稿之 React-Saga的详解
2018/11/12 Javascript
Puppeteer 爬取动态生成的网页实战
2018/11/14 Javascript
js实现图片放大并跟随鼠标移动特效
2019/01/18 Javascript
React如何实现浏览器打印部分内容详析
2019/05/19 Javascript
nodeJs的安装与npm全局环境变量的配置详解
2020/01/06 NodeJs
整理Python中的赋值运算符
2015/05/13 Python
Python的Django REST框架中的序列化及请求和返回
2016/04/11 Python
详解Python中的文件操作
2016/08/28 Python
Django项目中model的数据处理以及页面交互方法
2018/05/30 Python
在pycharm中设置显示行数的方法
2019/01/16 Python
Python 中Django安装和使用教程详解
2019/07/03 Python
Python 面向对象部分知识点小结
2020/03/09 Python
Python绘制K线图之可视化神器pyecharts的使用
2021/03/02 Python
突袭HTML5之Javascript API扩展3—本地存储全新体验
2013/01/31 HTML / CSS
Abe’s of Maine:自1979以来销售相机和电子产品
2016/11/21 全球购物
介绍一下如何利用路径遍历进行攻击及如何防范
2014/01/19 面试题
行政专员岗位职责
2014/01/02 职场文书
《一本男孩子必读的书》教学反思
2014/02/19 职场文书
党员教师工作决心书
2014/03/13 职场文书
成龙霸王洗发水广告词
2014/03/14 职场文书
民用住房租房协议书
2014/10/29 职场文书
中秋节感想
2015/08/10 职场文书
励志语录:只有自己足够强大,才能不被别人践踏
2020/01/09 职场文书
nginx限制并发连接请求数的方法
2021/04/01 Servers
MySQL基础(一)
2021/04/05 MySQL