Сейчас будет самый простой пример асинхронного запроса. На полноценный парсер это ещё не похоже, так как выполняется всего один запрос, но для старта нам подойдёт.
Первым делом необходимо создать сессию. Сессия обладает набором параметров по умолчанию, которые передаются серверу с каждым запросом в рамках этой сессии. Самый важный параметр — это cookies, которые являются общими для всех запросов сессии.
В коде ниже мы создали сессию при помощи менеджера контекста with. Это нужно для того, чтобы после выполнения всех запросов aiohttp очистил все ресурсы.
Если у вас не запускается код ниже, то удалите следующую строку.
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
import aiohttp import asyncio async def main(): #------------------------------------start block 2------------------------------------ async with aiohttp.ClientSession(trust_env=True) as session: async with session.get('https://mob25.com/') as response: print(await response.text()) #------------------------------------end block 2------------------------------------ #------------------------------------start block 1------------------------------------ asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) asyncio.run(main()) #------------------------------------end block 1------------------------------------
При выполнении этого кода происходит следующее. Интерпретатор, проходя по коду сверху вниз, инициализирует нашу корутину async def main() в блоке №2; на этом этапе запуск ещё не происходит. Когда интерпретатор доходит до блока №1, он применяет политику, по правилам которой будет работать цикл событий. Это происходит в первой строке первого блока, о чём мы говорили в разделе про event loop. Когда интерпретатор доходит до второй строки блока №1, где мы передаём нашу корутину на выполнение в цикл событий asyncio.run(main()), именно в этот момент происходит её выполнение.
Вся магия асинхронного запроса происходит в блоке №2. Первая строка этого блока создаёт с помощью менеджера контекста with асинхронную сессию, которая может быть передана в другую корутину. Но в этом примере она используется в той же корутине. Во второй строке второго блока мы используем метод .get(url=»») для передачи этой сессии ссылки для асинхронного запроса. В следующих разделах мы поговорим о том, как передать в него целый список ссылок и как обработать их асинхронно.
На этом этапе уже можно понять, как мы будем использовать bs4 для извлечения нужных элементов со страницы, но об этом чуть позже.
В третьей строке мы печатаем всё содержимое ответа. У вас может появиться справедливый вопрос: почему мы написали await в функции print()? Поскольку response работает с сетью, возвращая нам результат своей работы через устройство ввода/вывода, то есть через HDD/SSD/M2 и т. д., код вынужден ждать, пока произойдёт эта операция. Если бы у нас было больше запросов, чем один, в этом месте произошло бы переключение контекста на другой запрос.
Как можно заметить, переменная response ведёт себя почти так же, как и в синхронной библиотеке requests, о чём мы и поговорим в следующем абзаце.
Какое содержимое мы можем получить от переменной response?
await response.text() — возвращает содержимое страницы, весь HTML.
response.content (без использования await) — возвращает размер содержимого в байтах
<StreamReader 7875 bytes eof>
response.status (без использования await) — возвращает статус код ответа.
response.url (без использования await) — возвращает текущий URL на который выполнялся запрос.
await response.read() — возвращает содержимое страницы в байтовом виде, на примере тега title это наглядно видно.
<title>\xd0\xa3\xd1\x87\xd0\xb8\xd0\xbc\xd1\x81\xd1\x8f \xd0\xbf\xd0\xb0\xd1\x80\xd1\x81\xd0\xb8\xd1\x82\xd1\x8c</title>
await response.json() — возвращает результат в формате JSON, в том случае, если сервер готов нам его отдать.
response.headers (без использования await) — возвращает заголовок страницы.
response.cookies — возвращает объект <class ‘http.cookies.SimpleCookie’> , т.к. у нас создается сессия, мы можем получить куки, которые были выданы сервером, для дальнейшего использования. С кукисами в этом формате можно работать как со словарем, используя методы items() , value(), get() и другие методы словарей.
- кукисы полученные этим способом имеют вид
Set-Cookie: GPS=1; Domain=youtube.com; expires=Tue, 06-Sep-2022 10:50:55 GMT; HttpOnly; Path=/; Secure Set-Cookie: VISITOR_INFO1_LIVE=1v9mQ2FgdTM; Domain=youtube.com; expires=Sun, 05-Mar-2023 10:20:55 GMT; HttpOnly; Path=/; SameSite=none; Secure Set-Cookie: YSC=UIIiWEGDShE; Domain=youtube.com; HttpOnly; Path=/; SameSite=none; Secure
response.charset (без использования await) — возвращает текущую кодировку данных ответа от сервера.
response.reason (без использования await) — возвращает строковое значение «OK» если статус код меньше 400, вернёт Not Found если статус код больше 400, или оповестить другой ошибкой.
response.host (без использования await) — вернёт имя домена.
response.request_info (без использования await) — вернёт информацию о запросе, на примере кода выше ответ будет
RequestInfo(url=URL('https://mob25.com/'), method='GET', headers=<CIMultiDictProxy('Host': 'mob25.com', 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Python/3.10 aiohttp/3.8.1')>, real_url=URL('https://mob25.com/'))
Это были основные методы и функции для извлечения данных о запросе. Более подробно можно изучить в документации.