Язык программирования Python

Курс IT-Академии Сухорукова

Декабрь 2019 - январь 2020

Этот курс закончился

Задание. Асинхронный скрэппер для xkcd.ru

Соберите коллекцию случайных картинок с сайта xkcd.ru.

Постановка задачи

В интернете давно существует веб-комикс XKCD (веб-комикс о романтике, сарказме, математике и языке). Его автор — Рэндэлл Монро, физик и инженер. Существует неофициальный проект по переводу комиксов на русский язык (xkcd.ru).

Задача: получить 40 случайных выпусков комикса с помощью aiohttp.

На странице https://xkcd.ru/num/ находится каталог комиксов со ссылками на каждый. Необходимо получить эту страницу, затем найти там все ссылки на комиксы и взять 40 из них случайным образом (например, можно воспользоваться функцией sample из модуля random, её описание есть в документации). После этого нужно асинхронно получить страницу каждого комикса, найти на ней ссылку на картинку комикса и так же асинхронно скачать эту картинку и асинхронно сохранить в файл на диске.

Все 40 комиксов следует скачивать параллельно, то есть создать задачу для скачивания каждого комикса и запустить все эти задачи параллельно с помощью функции asyncio.gather.

Все файлы следует сохранить в одну папку (любую). В качестве имени файла можно использовать имя файла изображения.

Что понадобится

Возможные проблемы

Отладка

Для отладки ограничьте выборку. Скажем, не 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:
    ...