python3网络爬虫aiohttp实战案例

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本文介绍了使用aiohttp库实现异步爬虫爬取网站图书的评论,及其代码的详细解释(案例来源于python3网络爬虫开发实战,本人对其进行了改编)


一、观察需要爬取的页面的数据包

1、通过观察发现页面的数据包是ajax数据包,而且我们需要的组成详情页的url的id也在ajax数据包的响应当中
在这里插入图片描述
2、进入详情页中,页面的数据还是一个ajax数据包,我们想要的评论数据也在ajax数据包的响应当中。
在这里插入图片描述
在这里插入图片描述
这里注意一个问题:详情页的url和ajax数据包的url是不一样的
在这里插入图片描述

二、基本配置

1、引入需要使用的库

import aiohttp
import asyncio
import nest_asyncio
import time
import json
import logging##这个是日志文件的库,可以记录程序运行的过程

2、定义必要的信息

nest_asyncio.apply()##jupyter notebook上不加此句话会报错
logging.basicConfig(level=logging.INFO,format='%(asctime)s-%(levelname)s:%(message)s')
index_url='https://spa5.scrape.center/api/book/?limit=18&offset={offset}'#索引页的url
detail_url= 'https://spa5.scrape.center/api/book/{id}'#详情页的url
page_size=18#一页有18本图书
page_number=2#设置爬取的页数是2页
concurrency=5#设置最大的并大数量是5

``

三、生成不同页面的url,并获取响应数据

1、抓取ajax数据包中的响应数据

async def scrape_api(url):
    async with semaphore:
        try:
            logging.info('scraping %s',url)
            async with session.get(url) as response:
                return await response.json()
        except aiohttp.ClientError:
            logging.error('error occured while scraping %s',url,exc_info=True)

2、由于需要爬取不同页面的图书信息,所以url在参数上会有不同,不同页面的url也不同

##得到不同页面的url
async def scrape_index(page):
    url=index_url.format(offset=page_size*(page-1))##拼接成完整的详情页的url
    return await scrape_api(url)

四、获得评论信息和数据储存

#处理获取到的响应数据
async def save_file(data):
    list_content=data.get('comments')
    for item in list_content:
         with open('comment.txt',mode='a',encoding='utf-8') as fp:
            fp.write(item.get('content'))
            fp.write('\r\n')
#获取详情页的评论信息   
async def scrape_detail(id):
    url=detail_url.format(id=id)
    data=await scrape_api(url)
    await save_file(data)

五、主函数调用

async def main():
    global session
    session=aiohttp.ClientSession()#创建一个ClientSession对象,用于获得网页响应,类似于使用get
    scrape_index_tasks=[asyncio.ensure_future(scrape_index(page)) for page in range(1,page_number+1)]#获取爬取页面的任务
    results=await asyncio.gather(*scrape_index_tasks)##将任务进行聚合,相当于放到一个队列中
    logging.info('results %s',json.dumps(results,ensure_ascii=False,indent=2))
    ids=[]
    for index_data in results:
        if not index_data:
            continue
        for item in index_data.get('results'):#获取数据包的响应数据是一个字典,字典的值是一个列表
            ids.append(item.get('id'))#列表中又是一个字典,找到id
    scrape_detail_tasks=[asyncio.ensure_future(scrape_detail(id)) for id in ids]##创建获取详情页的任务
    await asyncio.wait(scrape_detail_tasks)##这里是io操作比较密集的地方,需要挂起
    await session.close()
    
if __name__=='__main__':
    asyncio.run(main())

六、运行结果

在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值