利用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 查找list中的某个元素的所有的下标方法
Jun 27 Python
python实现贪吃蛇小游戏
Mar 21 Python
pthon贪吃蛇游戏详细代码
Jan 27 Python
python爬虫基础教程:requests库(二)代码实例
Apr 09 Python
Python3内置模块random随机方法小结
Jul 13 Python
基于python全局设置id 自动化测试元素定位过程解析
Sep 04 Python
使用python把xmind转换成excel测试用例的实现代码
Oct 12 Python
Spy++的使用方法及下载教程
Jan 29 Python
Python数据清洗工具之Numpy的基本操作
Apr 22 Python
Django如何与Ajax交互
Apr 29 Python
详解Django的MVT设计模式
Apr 29 Python
Python实现机器学习算法的分类
Jun 03 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脚本的10个技巧(2)
2006/10/09 PHP
php array_merge下进行数组合并的代码
2008/07/22 PHP
PHP 网络开发详解之远程文件包含漏洞
2010/04/25 PHP
php调用google接口生成二维码示例
2014/04/28 PHP
php遍历解析xml字符串的方法
2016/05/05 PHP
PHP使用星号替代用户名手机和邮箱的实现代码
2018/02/07 PHP
使用Git实现Laravel项目的自动化部署
2019/11/24 PHP
Javascript - HTML的request类
2007/01/09 Javascript
用js实现的抽象CSS圆角效果!!
2007/05/03 Javascript
JavaScript中的View-Model使用介绍
2011/08/11 Javascript
jQuery学习笔记之jQuery.extend(),jQuery.fn.extend()分析
2014/06/09 Javascript
IE9+已经不对document.createElement向下兼容的解决方法
2015/09/14 Javascript
DataTables添加额外的查询参数和删除columns等无用参数实例
2017/07/04 Javascript
前端主流框架vue学习笔记第一篇
2017/07/26 Javascript
iView-admin 动态路由问题的解决方法
2018/10/03 Javascript
Nodejs中怎么实现函数的串行执行
2019/03/02 NodeJs
node(koa2) web应用模块介绍详解
2019/03/29 Javascript
使用vue构建多页面应用的示例
2020/10/22 Javascript
Python标准库os.path包、glob包使用实例
2014/11/25 Python
Python 调用 zabbix api的方法示例
2019/01/06 Python
Python+OpenCV图片局部区域像素值处理详解
2019/01/23 Python
python中提高pip install速度
2020/02/14 Python
Centos7下源码安装Python3 及shell 脚本自动安装Python3的教程
2020/03/07 Python
PythonPC客户端自动化实现原理(pywinauto)
2020/05/28 Python
Python定时任务APScheduler原理及实例解析
2020/05/30 Python
手把手教你如何用Pycharm2020.1.1配置远程连接的详细步骤
2020/08/07 Python
行政经理岗位职责
2013/11/09 职场文书
简历自荐信
2013/12/02 职场文书
简短大学毕业感言
2014/01/18 职场文书
大学辅导员事迹材料
2014/02/05 职场文书
《兰亭集序》教学反思
2014/02/11 职场文书
工程催款通知书
2015/04/17 职场文书
贷款工资证明范本
2015/06/12 职场文书
初中军训感言
2015/08/01 职场文书
公司员工离职感言
2015/08/03 职场文书
nginx服务器的下载安装与使用详解
2021/08/02 Servers