专栏首页数据结构笔记实战:异步爬取之初识异步

实战:异步爬取之初识异步

一、为什么要用异步?

许多之前没有听说过异步地朋友可能看到标题地第一反应就是:什么是异步?为什么要用异步?

我们先来讲讲为什么要用异步,对于爬虫来说,在能够爬取到数据地前提下当然是越快越好,显然传统地同步代码不能满足我们对速度地需求。

这时候我们想到了多线程,虽然多线程能够提高速度,但是单论效率来说多线程是不如同步代码的,因为还要花费资源来管理线程

而且多线程还有资源竞争的问题,这就不得不使用资源锁来保证同一时间只有一个线程访问,而这使得多线程的速度更加慢,这也是为什么在上一篇我们使用十个线程却只达到 9倍速度的原因。

而异步却没有这些问题,异步虽然被称作异步,但本质上异步代码都是同步的,它们都运行在一个线程里,这样就不需要考虑线程管理和资源竞争的问题了。

并且异步的速度非常快,为什么是非常快而不是很快?因为异步真的太快了。

不说废话,我们拿数据说事:

正常情况下我们请求一个页面大概是 0.3到 0.8秒左右(带宽 100m)

也就是说如果我们请求同一个页面 100次的话,最少也得花费 30秒

如果换成异步呢?

使用异步如果只请求一个页面的话,和同步差不多,也是在 0.3到 0.8之间

但是如果请求同一个页面 100次的话,只需要要 3秒左右

国外有人做过测试:

请求次数

花费时间

100

3.48s

1000

7s

10k

23s

100k

53s

1000k

9 min 3s

(数据来源:Making 1 million requests with python-aiohttp)

从表中的数据可以看出来异步的最大速度可以达到 100k每分钟,可以说是非常快了。

在我的的测试中,最快达到了 2k每分钟,与上面的数据相差较大(难道是我的打开方式不对?)。

不过不管怎样,我们能够确定异步很快。

对于一些异步的基本概念不了解的朋友可以去看这篇文章: 深入理解 Python 异步编程(上)

下面我们以一个简单的例子来了解一下异步的使用

二、异步的简单使用

在开始之前,大家要牢记异步是单线程的,所以代码中不能有非异步的 I/O 操作。

像 requests、文件写入等 耗时的 I/O操作都不能直接使用。

不过这些库都有对应的异步版本,比如 requests就可以使用 aiohttp代替。

下面我们来看一个简单的例子,来感受一下异步的速度:

首先我们使用 requests库来请求百度首页一次:

import time
import requests


def getBaiduPage():
    url = 'https://www.baidu.com/'
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36'
    }

    r = requests.get(url, headers=headers)

    print(r.status_code)


start = time.time()

getBaiduPage()

end = time.time()

print(f'用时{end - start} s')

输出:

200
用时0.5322993278503418 s

我们再试试请求 10次:

start = time.time()

for i in range(10):
    getBaiduPage()
    
end = time.time()

print(f'用时{end - start} s')

输出:

200
...
200
用时3.976729393005371 s

我们再来看看异步:

请求一次:

import time

import asyncio
import aiohttp


async def getBaiduPageAsync():
    url = 'https://www.baidu.com/'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36'
    }
    async with aiohttp.ClientSession() as session:
        async with session.get(url, headers=headers) as response:
            print(response.status)


start = time.time()


loop = asyncio.get_event_loop()

loop.run_until_complete(asyncio.ensure_future(getBaiduPageAsync()))


end = time.time()

print(f'用时{end - start} s')

输出:

200
用时0.599806547164917 s

用异步请求 10次:

start = time.time()

loop = asyncio.get_event_loop()

tasks = []
for i in range(10):
    tasks.append(asyncio.ensure_future(getBaiduPageAsync()))

loop.run_until_complete(asyncio.wait(tasks))

end = time.time()

print(f'用时{end - start} s')

输出:

200
...
200
用时0.512629508972168 s

我们列个表格来看看,requests和 aiohttp之间的区别:

请求一次

请求十次

requests

0.5322993278503418 s

3.976729393005371 s

aiohttp

0.599806547164917 s

0.512629508972168 s

通过表格我们不难发现,在请求一次的时候 requests和 aiohttp相差不大,但是在请求十次的时候 requests和 aiohttp相差巨大,甚至 aiohttp请求十次所用的时间和请求一次的时间相当。

其实这还不能体现出异步真正的速度,让我们来看看使用异步请求 100次:

start = time.time()

loop = asyncio.get_event_loop()

tasks = []
for i in range(100):
    tasks.append(asyncio.ensure_future(getBaiduPageAsync()))

loop.run_until_complete(asyncio.wait(tasks))

end = time.time()

print(f'用时{end - start} s')

输出:

200
...
200
用时1.6467080116271973 s

好像异步请求的页面越多速度越快(⊙o⊙)。

别想多了ε=ε=ε=( ̄ ̄),其实异步的速度是有个上限的,从我们的第一个表格来看,这个上限是 100k每分钟。

这里只写了一个简单的示例来测试异步请求的速度,关于异步的详细使用我们留到下一篇。

想了解为什么异步如此快,可以阅读: 深入理解 Python 异步编程(上)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 华为加班到底有多恐怖?

    “我先说一下我的吧。昨天晚上好不容易11点之前搞完上线回到家,刚开门媳妇就叫到:你TMD给我站到阳台去!”

    哲洛不闹
  • 编程,从来都不晚:来自日本的82岁APP开发者

    82岁的若宮正子第一次工作时,还是使用算盘来进行计算——而如今,她是世界上年纪最大的iPhone应用开发者之一,也是使得智能手机走入老年人生活的先驱者。

    哲洛不闹
  • 电商平台分账交易是怎么做的?

    另一篇文章讲到了电商平台的“二清”模式,在实际中,很多互联网电商平台需要分账给上面的平台商户或者其他角色,如果从严格的“二清”界定上来讲部分是属于违规进行了“信...

    金融民工小曾
  • 面试中单例模式有几种写法

    纠结单例模式有几种写法有用吗?有点用,面试中经常选择其中一种或几种写法作为话头,考查设计模式和coding style的同时,还很容易扩展到其他问题。这里讲解几...

    哲洛不闹
  • 自定义控件基础 之 3.4 ViewGroup的测量 & 3.5 ViewGroup的绘制

    之前分析中说了,ViewGroup会去管理其子View,其中一个管理项目就是负责子View的显示大小。当ViewGroup的大小为wrap_content时,V...

    凌川江雪
  • 华为、腾讯、阿里、网易员工下班时间大曝光,为什么赢不了他们

    这年头,不加班都不好意思说自己是上班族的。但有一种行业的疯狂加班程度,已经逐渐成为加班领域的一颗新星——互联网行业从事者!

    哲洛不闹
  • 盲式出轨,上流社会边缘人士,2018朋友圈流行词,哪个词说中了你?

    哲洛不闹
  • 这些拍案惊奇的智障桥段,分明是在蔑视我作为程序员的debug

    作为在网络高速发展的时代背景下成长起来的一代人,网络文学几乎伴随着我们的整个青春。

    一墨编程学习
  • 我的编码习惯 - 参数校验和国际化规范

    今天我们说说参数校验和国际化,这些代码没有什么技术含量,却大量充斥在业务代码上,很可能业务代码只有几行,参数校验代码却有十几行,非常影响代码阅读,所以很有必要把...

    哲洛不闹
  • 博君一笑

    哲洛不闹

扫码关注云+社区

领取腾讯云代金券