Python中利用aiohttp制作异步爬虫及简单应用


Posted in Python onNovember 29, 2018

摘要: 简介 asyncio可以实现单线程并发IO操作,是Python中常用的异步处理模块。关于asyncio模块的介绍,笔者会在后续的文章中加以介绍,本文将会讲述一个基于asyncio实现的HTTP框架——aiohttp,它可以帮助我们异步地实现HTTP请求,从而使得我们的程序效率大大提高。

简介

asyncio可以实现单线程并发IO操作,是Python中常用的异步处理模块。关于asyncio模块的介绍,笔者会在后续的文章中加以介绍,本文将会讲述一个基于asyncio实现的HTTP框架——aiohttp,它可以帮助我们异步地实现HTTP请求,从而使得我们的程序效率大大提高。

本文将会介绍aiohttp在爬虫中的一个简单应用。

在原来的项目中,我们是利用Python的爬虫框架scrapy来爬取当当网图书畅销榜的图书信息的。在本文中,笔者将会以两种方式来制作爬虫,比较同步爬虫与异步爬虫(利用aiohttp实现)的效率,展示aiohttp在爬虫方面的优势。

同步爬虫

首先,我们先来看看用一般的方法实现的爬虫,即同步方法,完整的Python代码如下:

'''
同步方式爬取当当畅销书的图书信息
'''
import time
import requests
import pandas as pd
from bs4 import BeautifulSoup
# table表格用于储存书本信息
table = []
# 处理网页
def download(url):
html = requests.get(url).text
# 利用BeautifulSoup将获取到的文本解析成HTML
soup = BeautifulSoup(html, "lxml")
# 获取网页中的畅销书信息
book_list = soup.find('ul', class_="bang_list clearfix bang_list_mode")('li')
for book in book_list:
info = book.find_all('div')
# 获取每本畅销书的排名,名称,评论数,作者,出版社
rank = info[0].text[0:-1]
name = info[2].text
comments = info[3].text.split('条')[0]
author = info[4].text
date_and_publisher = info[5].text.split()
publisher = date_and_publisher[1] if len(date_and_publisher) >= 2 else ''
# 将每本畅销书的上述信息加入到table中
table.append([rank, name, comments, author, publisher])
# 全部网页
urls = ['http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-recent7-0-0-1-%d' % i for i in range(1, 26)]
# 统计该爬虫的消耗时间
print('#' * 50)
t1 = time.time() # 开始时间
for url in urls:
download(url)
# 将table转化为pandas中的DataFrame并保存为CSV格式的文件
df = pd.DataFrame(table, columns=['rank', 'name', 'comments', 'author', 'publisher'])
df.to_csv('E://douban/dangdang.csv', index=False)
t2 = time.time() # 结束时间
print('使用一般方法,总共耗时:%s' % (t2 - t1))
print('#' * 50)

输出结果如下:

##################################################
使用一般方法,总共耗时:23.522345542907715
##################################################

程序运行了23.5秒,爬取了500本书的信息,效率还是可以的。我们前往目录中查看文件,如下:

Python中利用aiohttp制作异步爬虫及简单应用

异步爬虫

接下来我们看看用aiohttp制作的异步爬虫的效率,完整的源代码如下:

'''
异步方式爬取当当畅销书的图书信息
'''
import time
import aiohttp
import asyncio
import pandas as pd
from bs4 import BeautifulSoup
# table表格用于储存书本信息
table = []
# 获取网页(文本信息)
async def fetch(session, url):
async with session.get(url) as response:
return await response.text(encoding='gb18030')
# 解析网页
async def parser(html):
# 利用BeautifulSoup将获取到的文本解析成HTML
soup = BeautifulSoup(html, "lxml")
# 获取网页中的畅销书信息
book_list = soup.find('ul', class_="bang_list clearfix bang_list_mode")('li')
for book in book_list:
info = book.find_all('div')
# 获取每本畅销书的排名,名称,评论数,作者,出版社
rank = info[0].text[0:-1]
name = info[2].text
comments = info[3].text.split('条')[0]
author = info[4].text
date_and_publisher = info[5].text.split()
publisher = date_and_publisher[1] if len(date_and_publisher) >=2 else ''
# 将每本畅销书的上述信息加入到table中
table.append([rank,name,comments,author,publisher])
# 处理网页
async def download(url):
async with aiohttp.ClientSession() as session:
html = await fetch(session, url)
await parser(html)
# 全部网页
urls = ['http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-recent7-0-0-1-%d'%i for i in range(1,26)]
# 统计该爬虫的消耗时间
print('#' * 50)
t1 = time.time() # 开始时间
# 利用asyncio模块进行异步IO处理
loop = asyncio.get_event_loop()
tasks = [asyncio.ensure_future(download(url)) for url in urls]
tasks = asyncio.gather(*tasks)
loop.run_until_complete(tasks)
# 将table转化为pandas中的DataFrame并保存为CSV格式的文件
df = pd.DataFrame(table, columns=['rank','name','comments','author','publisher'])
df.to_csv('E://douban/dangdang.csv',index=False)
t2 = time.time() # 结束时间
print('使用aiohttp,总共耗时:%s' % (t2 - t1))
print('#' * 50)

我们可以看到,这个爬虫与原先的一般方法的爬虫的思路和处理方法基本一致,只是在处理HTTP请求时使用了aiohttp模块以及在解析网页时函数变成了协程(coroutine),再利用aysncio进行并发处理,这样无疑能够提升爬虫的效率。它的运行结果如下:

##################################################
使用aiohttp,总共耗时:2.405137538909912
##################################################

2.4秒,如此神奇!!!再来看看文件的内容:

Python中利用aiohttp制作异步爬虫及简单应用

总结

综上可以看出,利用同步方法和异步方法制作的爬虫的效率相差很大,因此,我们在实际制作爬虫的过程中,也不妨可以考虑异步爬虫,多多利用异步模块,如aysncio, aiohttp。另外,aiohttp只支持3.5.3以后的Python版本。

Python 相关文章推荐
Python用zip函数同时遍历多个迭代器示例详解
Nov 14 Python
Python反转序列的方法实例分析
Mar 21 Python
python Flask 装饰器顺序问题解决
Aug 08 Python
Python判断有效的数独算法示例
Feb 23 Python
Python设置matplotlib.plot的坐标轴刻度间隔以及刻度范围
Jun 25 Python
Flask框架学习笔记之路由和反向路由详解【图文与实例】
Aug 12 Python
Python常用模块logging——日志输出功能(示例代码)
Nov 20 Python
python argparse传入布尔参数false不生效的解决
Apr 20 Python
Python Excel vlookup函数实现过程解析
Jun 22 Python
Python解析m3u8拼接下载mp4视频文件的示例代码
Mar 03 Python
只用50行Python代码爬取网络美女高清图片
Jun 02 Python
python3实现常见的排序算法(示例代码)
Jul 04 Python
Python中logging.NullHandler 的使用教程
Nov 29 #Python
Mac下Anaconda的安装和使用教程
Nov 29 #Python
windows7 32、64位下python爬虫框架scrapy环境的搭建方法
Nov 29 #Python
解决pycharm py文件运行后停止按钮变成了灰色的问题
Nov 29 #Python
pycharm debug功能实现跳到循环末尾的方法
Nov 29 #Python
在PyCharm下打包*.py程序成.exe的方法
Nov 29 #Python
selenium设置proxy、headers的方法(phantomjs、Chrome、Firefox)
Nov 29 #Python
You might like
mysql 性能的检查和优化方法
2009/06/21 PHP
php5.5新数组函数array_column使用
2013/07/08 PHP
php 生成加密公钥加密私钥实例详解
2017/06/16 PHP
PHP7 windows支持
2021/03/09 PHP
IE与Firefox下javascript getyear年份的兼容性写法
2007/12/20 Javascript
jquery 日期分离成年月日的代码
2010/05/14 Javascript
《JavaScript高级程序设计》阅读笔记(一) ECMAScript基础
2012/02/27 Javascript
jquery $(this).attr $(this).val方法使用介绍
2013/10/08 Javascript
jQuery读取和设定KindEditor值的方法
2013/11/22 Javascript
JavaScript错误处理
2015/02/03 Javascript
分享jQuery封装好的一些常用操作
2016/07/28 Javascript
React Native实现简单的登录功能(推荐)
2016/09/19 Javascript
利用JavaScript实现拖拽改变元素大小
2016/12/14 Javascript
js获取当前页的URL与window.location.href简单方法
2017/02/13 Javascript
Vue的v-model的几种修饰符.lazy,.number和.trim的用法说明
2020/08/05 Javascript
Python文件夹与文件的操作实现代码
2014/07/13 Python
Python使用smtp和pop简单收发邮件完整实例
2018/01/09 Python
Python根据指定日期计算后n天,前n天是哪一天的方法
2018/05/29 Python
python中reader的next用法
2018/07/24 Python
python3利用Socket实现通信的方法示例
2019/05/06 Python
Django框架创建mysql连接与使用示例
2019/07/29 Python
python+selenium+PhantomJS抓取网页动态加载内容
2020/02/25 Python
Python操作MongoDb数据库流程详解
2020/03/05 Python
利用Python制作动态排名图的实现代码
2020/04/09 Python
如何使用amaze ui的分页样式封装一个通用的JS分页控件
2020/08/21 HTML / CSS
Big Green Smile德国网上商店:提供各种天然产品
2018/05/23 全球购物
美国渔具店:FishUSA
2019/08/07 全球购物
财务管理专业应届毕业生求职信
2013/09/22 职场文书
电子商务专业在校生实习自我鉴定
2013/09/29 职场文书
大学生村官个人对照检查材料(群众路线)
2014/09/26 职场文书
python 模块重载的五种方法
2021/04/24 Python
Python import模块的缓存问题解决方案
2021/06/02 Python
原生JavaScript实现简单五子棋游戏
2021/06/28 Javascript
实体类或对象序列化时,忽略为空属性的操作
2021/06/30 Java/Android
SQL SERVER存储过程用法详解
2022/02/24 SQL Server
十大最强火系宝可梦,喷火龙上榜,第一名有双火属性
2022/03/18 日漫