Задание. Асинхронный скрэппер для xkcd.ru
Соберите коллекцию случайных картинок с сайта xkcd.ru.
Постановка задачи
В интернете давно существует веб-комикс XKCD (веб-комикс о романтике, сарказме, математике и языке). Его автор — Рэндэлл Монро, физик и инженер. Существует неофициальный проект по переводу комиксов на русский язык (xkcd.ru).
Задача: получить 40 случайных выпусков комикса с помощью aiohttp.
На странице https://xkcd.ru/num/ находится каталог комиксов со ссылками на каждый. Необходимо получить эту страницу, затем найти там все ссылки на комиксы и взять 40 из них случайным образом (например, можно воспользоваться функцией sample
из модуля random
, её описание есть в документации). После этого нужно асинхронно получить страницу каждого комикса, найти на ней ссылку на картинку комикса и так же асинхронно скачать эту картинку и асинхронно сохранить в файл на диске.
Все 40 комиксов следует скачивать параллельно, то есть создать задачу для скачивания каждого комикса и запустить все эти задачи параллельно с помощью функции asyncio.gather
.
Все файлы следует сохранить в одну папку (любую). В качестве имени файла можно использовать имя файла изображения.
Что понадобится
- Библиотека asyncio
- Библиотека aiohttp
- Библиотека aiofiles
- Библиотека BeautifulSoup4
Возможные проблемы
Отладка
Для отладки ограничьте выборку. Скажем, не 40 изображений, а всего пять.
Защита от блокировки
При получении страниц отдельных комиксов стоит делать небольшую случайную задержку перед запросами, чтобы сайт не решил, что вы пытаетесь устроить атаку типа DoS. Например, вот так:
...
# Функция uniform — как randint, но для чисел с плавающей точкой
from random import uniform
...
...
async def fetch_comics_page(session, url):
await asyncio.sleep(uniform(0.2, 0.7))
resp = await session.get(url)
...
Ошибка SSLCertVerificationError
Вы можете столкнуться с ошибкой такого вот вида при попытке получить ответ от сайта с помощью aiohttp
:
SSL handshake failed on verifying the certificate
......
aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot connect to host
bash.im:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED]
certificate verify failed: self signed certificate in certificate chain (_ssl.c:1056)')]
Ничего страшного, просто сертификат безопасности сайта xkcd.ru не удовлетворяет строгим требованиям SSL
. Чтобы обойти это ограничение, нужно выключить проверку подлинности сертификата при создании сессии, указав соответствующий параметр коннектора:
async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False)) as sess:
...