利用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爬虫之爬虫编写全记录
Nov 06 Python
常见的在Python中实现单例模式的三种方法
Apr 08 Python
Python自动化开发学习之三级菜单制作
Jul 14 Python
python编程测试电脑开启最大线程数实例代码
Feb 09 Python
python实现隐马尔科夫模型HMM
Mar 25 Python
python简单鼠标自动点击某区域的实例
Jun 25 Python
python 机器学习之支持向量机非线性回归SVR模型
Jun 26 Python
Python自动化测试笔试面试题精选
Mar 12 Python
python文件及目录操作代码汇总
Jul 08 Python
python进度条显示之tqmd模块
Aug 22 Python
通过代码实例了解Python异常本质
Sep 16 Python
Python try except else使用详解
Jan 12 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
解密ThinkPHP3.1.2版本之独立分组功能应用
2014/06/19 PHP
yii的CURD操作实例详解
2014/12/04 PHP
微信开发之网页授权获取用户信息(二)
2016/01/08 PHP
JQuery CheckBox(复选框)操作方法汇总
2015/04/15 Javascript
JavaScript中eval函数的问题
2016/01/31 Javascript
完美解决jQuery符号$与其他javascript 库、框架冲突的问题
2016/08/09 Javascript
JS实现“隐藏与显示”功能(多种方法)
2016/11/24 Javascript
JS拉起或下载app的实现代码
2017/02/22 Javascript
微信小程序页面传值实例分析
2017/04/19 Javascript
浅谈angular4.0中路由传递参数、获取参数最nice的写法
2018/03/12 Javascript
vue构建动态表单的方法示例
2018/09/22 Javascript
微信小程序点击图片实现长按预览、保存、识别带参数二维码、转发等功能
2019/07/20 Javascript
vuex实现像调用模板方法一样调用Mutations方法
2019/11/06 Javascript
[01:12:08]LGD vs OG 2019国际邀请赛淘汰赛 胜者组 BO3 第一场 8.24
2019/09/10 DOTA
使用Python的内建模块collections的教程
2015/04/28 Python
Python3基础教程之递归函数简单示例
2019/06/07 Python
python模式 工厂模式原理及实例详解
2020/02/11 Python
Python图片处理模块PIL操作方法(pillow)
2020/04/07 Python
python查询MySQL将数据写入Excel
2020/10/29 Python
python分布式爬虫中消息队列知识点详解
2020/11/26 Python
Python 中Operator模块的使用
2021/01/30 Python
深入CSS3 动画效果的总结详解
2013/05/09 HTML / CSS
Rockport乐步美国官网:风靡美国的白宫鞋
2016/11/24 全球购物
英国高级百货公司:Harvey Nichols
2017/01/29 全球购物
给水排水工程专业毕业生推荐信
2013/10/28 职场文书
20年同学聚会感言
2014/02/03 职场文书
三严三实对照检查材料思想汇报
2014/09/28 职场文书
工作检讨书怎么写
2014/10/10 职场文书
营业用房租赁协议书
2014/11/26 职场文书
中学推普周活动总结
2015/05/07 职场文书
幼儿园园务工作总结2015
2015/05/18 职场文书
乡镇科协工作总结2015
2015/05/19 职场文书
2016年会开场白台词
2015/06/01 职场文书
2016春季运动会通讯稿
2015/07/18 职场文书
最新动漫情报:2022年7月新番定档超过30部, OVERLORD骨王第四季也在其中噢
2022/05/04 日漫
MySQL一劳永逸永久支持输入中文的方法实例
2022/08/05 MySQL