Использование aiohttp для получения статуса нескольких веб-сайтов - PullRequest
1 голос
/ 01 ноября 2019

У меня есть этот код, который я использую, чтобы получить статус списка веб-сайтов.

import aiohttp
import asyncio
import json
import sys
import time


async def get_statuses(websites):
    statuses = {}
    tasks = [get_website_status(website) for website in websites]
    for status in await asyncio.gather(*tasks):
        if not statuses.get(status):
            statuses[status] = 0
        statuses[status] += 1
    print(json.dumps(statuses))


async def get_website_status(url):
    response = await aiohttp.get(url)
    status = response.status
    response.close()
    return status


if __name__ == '__main__':
    with open(sys.argv[1], 'r') as f:
        websites = f.read().splitlines()
    t0 = time.time()
    loop = asyncio.get_event_loop()
    loop.run_until_complete(get_statuses(websites))
    t1 = time.time()
    print("getting website statuses took {0:.1f} seconds".format(t1-t0))

и, поскольку get устарела await aiohttp.get(url) я отредактировал код как таковой

import aiohttp
import asyncio
import json
import sys
import time

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def get_statuses(websites):
    statuses = {}
    tasks = [get_website_status(website) for website in websites]
    for status in await asyncio.gather(*tasks):
        if not statuses.get(status):
            statuses[status] = 0
        statuses[status] += 1
    print(json.dumps(statuses))


async def get_website_status(url):
 async with aiohttp.ClientSession() as session:
    response = await fetch(session, url)
    #response = await aiohttp.get(url)
    status = response.status
    response.close()
    return status


if __name__ == '__main__':
    with open(sys.argv[1], 'r') as f:
        websites = f.read().splitlines()
    t0 = time.time()
    loop = asyncio.get_event_loop()
    loop.run_until_complete(get_statuses(websites))
    t1 = time.time()
    print("getting website statuses took {0:.1f} seconds".format(t1-t0))

Я скопировал сессионный код из документов https://aiohttp.readthedocs.io/en/stable/

Однако, когда я запускаю свой код, я получаю эту ошибку:

c:\asyncio>a.py list.txt
Traceback (most recent call last):
  File "C:\asyncio\a.py", line 35, in <module>
    loop.run_until_complete(get_statuses(websites))
  File "C:\Users\user\AppData\Local\Programs\Python\Python37\lib\asyncio\base_ev
ents.py", line 579, in run_until_complete
    return future.result()
  File "C:\asyncio\a.py", line 14, in get_statuses
    for status in await asyncio.gather(*tasks):
  File "C:\asyncio\a.py", line 25, in get_website_status
    status = response.status
AttributeError: 'str' object has no attribute 'status'

c:\asyncio>

вот пример list.txt

https://facebook.com/
https://twitter.com/
https://google.com/
https://youtube.com/
https://linkedin.com/
https://instagram.com/
https://pinterest.com/

1 Ответ

2 голосов
/ 01 ноября 2019

get_website_status рутинные делегаты вызывают функцию fetch, которая возвращает текстовое содержимое response.text(), а не сам response.
Вот почему в дальнейшем response.status выдает очевидную ошибку.

Если содержимое ответа не требуется, чтобы исправить ошибку, измените функцию fetch, чтобы она возвращала объект response:

async def fetch(session, url):
    response = await session.get(url)
    return response
...