Aiohttp异步会话请求

时间:2019-03-19 21:42:07

标签: python python-3.x python-asyncio aiohttp pytest-aiohttp

因此,我一直在使用会话来抓取带有请求的网站(www.cardsphere.com)受保护的页面,例如:

import requests

payload = {
            'email': <enter-email-here>,
            'password': <enter-site-password-here>
          }

with requests.Session() as request:
   requests.get(<site-login-page>)
   request.post(<site-login-here>, data=payload)
   request.get(<site-protected-page1>)
   save-stuff-from-page1
   request.get(<site-protected-page2>)
   save-stuff-from-page2
   .
   .
   .
   request.get(<site-protected-pageN>)
   save-stuff-from-pageN
the-end

现在,由于页面很多,我想使用Aiohttp + asyncio来加快速度...但是我缺少了一些东西。我已经能够或多或少地使用它来刮掉不受保护的页面,就像这样:

import asyncio
import aiohttp

async def get_cards(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            data = await resp.text()
            <do-stuff-with-data>

urls  = [
         'https://www.<url1>.com'
         'https://www.<url2>.com'
         .
         .
         . 
         'https://www.<urlN>.com'
        ]

loop = asyncio.get_event_loop()
loop.run_until_complete(
    asyncio.gather(
        *(get_cards(url) for url in urls)
    )
)

那给出了一些结果,但是对于需要登录的页面我该怎么做呢?我尝试在异步函数中添加session.post(<login-url>,data=payload),但显然效果不佳,它将一直保持登录状态。是否可以在循环函数之前“设置” aiohttp ClientSession?由于我需要先登录,然后在同一会话中,使用asyncio + aiohttp从一堆受保护的链接中获取数据?

对于python来说还是很新的东西,所以异步甚至更多,这里我缺少一些关键概念。如果有人能指出正确的方向,我将不胜感激。

1 个答案:

答案 0 :(得分:2)

这是我能想到的最简单的方法,具体取决于您在<do-stuff-with-data>中的操作,您可能会遇到其他一些关于并发的麻烦,您可能会遇到麻烦……只是在开玩笑,有点将头,承诺和任务四处走动会更加复杂,但是一旦获得,它就像顺序编程一样简单

import asyncio
import aiohttp


async def get_cards(url, session, sem):
    async with sem, session.get(url) as resp:
        data = await resp.text()
        # <do-stuff-with-data>


urls = [
    'https://www.<url1>.com',
    'https://www.<url2>.com',
    'https://www.<urlN>.com'
]


async def main():
    sem = asyncio.Semaphore(100)
    async with aiohttp.ClientSession() as session:
        await session.get('auth_url')
        await session.post('auth_url', data={'user': None, 'pass': None})
        tasks = [asyncio.create_task(get_cards(url, session, sem)) for url in urls]
        results = await asyncio.gather(*tasks)
        return results


asyncio.run(main())