Aiothhp高并发抓取 Aiohttp抓取小说排行榜页面

鳄鱼君

发表文章数:531

Vieu四代商业主题

高扩展、安全、稳定、响应式布局多功能模板。

¥69 现在购买
首页 » Python教程 » Aiothhp高并发抓取 Aiohttp抓取小说排行榜页面

Aiohttp简介及使用

Aiohttp是Python的一个第三方网络编程模块,它可以开发服务端和客户端。服务端也就是网站服务器;客户端就是访问网站的API接口,常用与接口测试,也可以用于开发网络爬虫。Aiohttp是基于Asyncio实现的HTTP框架,Asyncio是从Python 3.4开始引入的标准库,它是因协程的该能而生,这是官方推荐高并发模块之一。

Asyncio具有高并发的特性,因此Aiohttp继承了Asyncio的特性,是的Aiohttp非常适合开发网络爬虫。在使用Aiohttp之前肯定是需要安装的喽!使用pip命令:pip install aiohttp,也可以下载whl安装包进行安装:pip install aiohttp‑3.6.2‑cp37‑cp37m‑win_amd64.whl

在这篇文章里,只介绍如何使用Aiohttp的客户端功能,通过客户端功能趋势线网络爬虫的开发。首先要建立一个Session,然后利用会话对象session去访问页面,基本用法如下:

import aiohttp
import asyncio
async def World(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            response=await response.text()
            print(response)
if __name__ == '__main__':
    url="http://www.e1yu.com"
    loop=asyncio.get_event_loop()
    loop.run_until_complete(World(url))

以上代码是使用Aiohttp和Asyncio模块访问鳄鱼君Ba的网站。函数World()加入了Python内置的关键词async和await,这是将函数设置为异步操作,这是Aiohttp的使用方式;函数World()的调用和运行需要借助Asyncio模块,Aiohttp只实现网站的访问方式,而代码的执行过程则有Asyncio模块实现。

Aiohttp在发送HTTP请求的时候,还可以设置HTTP请求的请求头、超时、Cookies和代理。请求头和代理IP是在发送HTTP请求的过程中分别设置参数headers和proxy,而超时和Cookies是在会话对象session里分别设置参数cookies和timeout实现,具体代码参考:

from aiohttp import ClientSession
import aiohttp
URL="https://www.e1yu.com"
# 设置请求头
headers={
    "User-Agent":"Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
}
async with ClientSession() as session:
    async with session.get(URL,headers=headers) as response:
        response=await response.text()

# 在会话中设置超时时间
timeout=aiohttp.ClientTimeout(total=60)
async with ClientSession(timeout=timeout) as session:
    async with session.get(URL) as response:
        response=await response.text()
 
# 在请求头中设置超时
async with ClientSession() as session:
    async with session.get(URL,timeout=timeout) as response:
        response=await response.text()

# 设置Cookies
cookies={"cookies_name":"cookies_value"}
async with ClientSession(Cookies=cookies) as session:
    async with session.get(URL) as response:
        response=await response.text()

# 设置代理IP
proxy="http://127.0.0.1:8080"
async with ClientSession() as session:
    async with session.get(URL,proxy=proxy) as response:
        response=await response.text()

# 支持付费代理授权
async with ClientSession() as session:
    proxy_auth=aiohttp.BasicAuth("user","password")
    async with session.get(URL,
            proxy=proxy,
            proxy_auth=proxy_auth) as response:
        response=await response.text()

Aiohttp定义了多种HTTP请求方法,例如GET、POST、OPTIONS、HEAD、PUT、PATCH、DELETE方法。最常用的就是GET和POST方法。GET请求有两种形式,分别是不带参数和带参数,使用方法参考:

# 不带参数
URL="https://www.e1yu.com"
async with ClientSession() as session:
    async with session.get(URL) as response:
        response=await response.text()

# 通过URL携带参数
URL="https://www.e1yu.com/?s=python"
async with ClientSession() as session:
    async with session.get(URL) as response:
        response=await response.text()

# 设置请求参数params
URL="https://www.e1yu.com"
params={"s":"python"}
async with ClientSession() as session:
    async with session.get(URL,params=params) as response:
        response=await response.text()

一般情况下,发送POST请求都会带有请求参数,参数值会包含在请求体中,一并发送给网站服务器。参数值的数据格式可以为字典、JSON、字符串和字节流,同的数据格式实现不同的功能,代码参考:

# 以字典格式写入
URL='http://httpbin.org/post'
data={"key":"python"}
async with ClientSession() as session:
    async with session.post(URL,data=data) as response:
        response=await response.text()

# 以JSON格式写入
URL='http://httpbin.org/post'
data={"key":"python"}
async with ClientSession() as session:
    async with session.post(URL,json=data) as response:
        response=await response.text()

# 以字符串格式写入
URL='http://httpbin.org/post'
data="python"
async with ClientSession() as session:
    async with session.post(URL,data=data) as response:
        response=await response.text()

# 以字节流的格式写入
URL='http://httpbin.org/post'
data={"file":open('1.txt','rb')} 
async with ClientSession() as session:
    async with session.post(URL,data=data) as response:
        response=await response.text()

不管是GET还是POST请求,最终都要从请求中获取响应的内容,从上面的代码可以看到,响应的内容可以通过text()方法获取。除此之外,Aiothhp还提供了多种获取响应内容的方法

# 设置编码格式
response=await response.text(encoding='utf-8')
# 以字节流格式返回
response=await response.read()
# 以JSON格式返回
response=await response.json()
# 获取响应的状态码
status=response.status
# 获取响应的请求头
headers=response.headers
# 获取URL地址
url=response.url

可以发现Aiohttp跟Requests的使用有相似之处,而且能够轻松实心高并发爬虫,有关Aiohttp的使用,有兴趣的可以查看官方文档继续学习。

Aiohttp异步抓取

通过一个简单的例子来具体了解如何使用Aiohttp,案例实现过程如下:

1.爬取对象:起点小说网24小时热销榜
2.数据清洗使用第三方模块:XPATH
3.数据将以CSV文件进行存储

网页的结构非常清晰,没有专门做反爬虫机制,所以很好抓取,这里直接给出代码参考:

import asyncio
from aiohttp import ClientSession
import csv
from lxml import etree
async def getData(url,headers):
    # 创建会话对象session
    async with ClientSession() as session:
        # 发送GET请求,并设置请求头
        async with session.get(url,headers=headers) as response:
            # 返回相应的内容
            return await response.text()
def saveData(result):
    for d in result:
        html=etree.HTML(d)
        item={}
        for i in html.xpath('//div[@class="book-img-text"]/ul/li'):
            item['title']=i.xpath('./div[@class="book-mid-info"]/h4/a/text()')[0]
            item['author']=''.join(i.xpath('./div[@class="book-mid-info"]/p[1]//text()')).strip()
            item['info']=''.join(i.xpath('./div[@class="book-mid-info"]/p[2]/text()')).strip()
            item['update']=''.join(i.xpath('./div[@class="book-mid-info"]/p[3]//text()')).strip()
            csvFlie= open('./24hour_novel.csv', 'a', newline='', encoding='utf-8')
            write = csv.writer(csvFlie)
            write.writerow([item['title'],item['author'],item['info'], item['update']])
            csvFlie.close()
def run():
    for i in range(1,100):
        # 构建不同的URL并传给getData函数,最后由asyncio模块执行
        task=asyncio.ensure_future(getData(url.format(i),headers))
        # 将所有请求加入到列表tasks
        tasks.append(task)
    # 等待所有请求执行完毕,一并返回全部的响应数据
    result=loop.run_until_complete(asyncio.gather(*tasks))
    saveData(result)
if __name__ == '__main__':
    headers={
        "User-Agent":"Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
    }
    tasks=[]
    url='https://www.qidian.com/rank/hotsales?page={}'
    # 创建get_event_loop对象
    loop=asyncio.get_event_loop()
    # 调用主函数
    run()

以上代码中,定义了三个函数和运行函数__main__,各个函数实现的功能说明如下:

(1)getData()是使用Aiohttp模块发送HTTP请求,参数url和headers分别代表请求地址和请求头,函数将响应内容作为返回值。

(2)savaData()是将响应内容进行数据清洗处理,从数据中提取小说信息并写入CSV文件,参数result代表排行榜所有分页的网页内容。

(3)run()是遍历25次来构建不同的URL地址,每次遍历是由Asyncio调用函数getData(),然后传入当前的URL地址,生成任务对象task,每次遍历所生成的任务对象task都会写入列表tasks,最后由Asyncio调度执行任务列表,将全部的执行结果(响应内容)以列表返回,赋值给变量result。

(4)运行函数__main__是定义请求头、格式化URL地址、创建get_event_loop对象和调用函数run(),这是为函数getData()和run()的变量进行初始化处理。

我们在PyCharm里运行上述代码,可以看到效率非常快,这要归功于Aiohttp的异步并发特性。虽然Aiohttp的异步并发可以提高爬虫的爬取效率,但也会因为爬取速度过快而被网站判为爬虫机器人,从而引一些列的反爬虫机制,但是还好我们演示的这个网站没有反爬虫机制!

未经允许不得转载:作者:鳄鱼君, 转载或复制请以 超链接形式 并注明出处 鳄鱼君
原文地址:《Aiothhp高并发抓取 Aiohttp抓取小说排行榜页面》 发布于2020-05-27

分享到:
赞(1) 赏杯咖啡

评论 抢沙发

9 + 4 =


文章对你有帮助可赏作者一杯咖啡

支付宝扫一扫打赏

微信扫一扫打赏

Vieu4.6主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。
切换注册

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录
切换登录

注册