aiohttp | aiohttp.ClientSession()实现session持久化操作


前言

对于某一个站点,我们通常会发送多个请求,为了保存请求参数(cookies,headers),就必须用到session来保持会话,以便接下来的操作正常执行。尤其是在某些站点需要登录的时候,我们就不得不使用session来保持会话了。
试了网络上流传的方法,似乎都不好使。
这篇文章主要介绍如何实现aiohttp.ClientSession()持久化。


避坑

  • 文章一
  • 文章二
  • 在类方法中,手动创建session,再把session传到类属性中。(如果方法没有被声明为async类型,执行后会出现警告,让你去把ClientSession写到协程函数中;如果方法被声明为async类型,执行后会出现错误——这个函数没有使用await)
  • 还有一种,找不到网址了,贴在文章后面

解决方案

在自定义的爬虫类中,创建一个异步函数执行的总入口

import asyncio
import aiohttp
class Spider(object):
    def __init__(self):
    	# 起始url
        self.start_url ="https://www.baidu.com/"
    async def param(self,session):
        '''
        发起请求并解析文本
        :param session: 传入的session
        :return:
        '''
        resp=await session.get(self.start_url)
    async def main(self):
        # 持久化session
        async with aiohttp.ClientSession() as session:
            # 创建并添加协程任务,传session
            param_task = asyncio.create_task(self.param(session))
            # 挂起协程任务
            await param_task
if __name__ == '__main__':
    sp = Spider()
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(sp.main())

基于此,以后的协程任务,都需要在async with aiohttp.ClientSession() as session:中创建。


大坑

import os
import asyncio
import aiohttp
import logging

session_list = {}
logger = logging.getLogger(__name__)

class Req:
    @property
    def set_session(self):
        try:
            loop = asyncio.get_running_loop()
        except:
            loop = asyncio.get_event_loop()
            asyncio.set_event_loop(loop)
        session = aiohttp.ClientSession(loop=loop)
        # 利用pid标记不同进程的session
        session_list.update({os.getpid(): session})
        return session

    def __init__(self):
        if session_list.get(os.getpid()):
            self.session = session_list.get(os.getpid())
            logger.info("复用session")
        else:
            self.session = self.set_session
            logger.info(f"PID: {os.getpid()} 初次生成")

    async def test(self):
        if session_list:
            session = session_list.get(os.getpid())
            if session and session.closed:
                session_list.pop(os.getpid())
                session = self.set_session
                logger.info("session不可用,重新生成session")
            elif not session:
                logger.info(f"[{os.getpid()}] session_list为空,创建一个session")
                session = self.set_session

        if not session or not session.loop.is_running():
            session = self.set_session
            logger.error("session异常")
        resp = await session.get("http://www.baidu.com")
        return resp.status
req = Req()
req.test()

完事!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值