Бывает так, что нужно быстро вытащить статью с Хабра, сдернуть с нее чистый текст, разметку и картинки. И желательно сделать это без разворачивания огромных парсеров и сложных сетапов. Мне нужен был простой инструмент, который делает ровно одну задачу: берет ID статьи, забирает весь контент, скачивает медиа и при желании сохраняет все в аккуратный Markdown. Так появился habraloader.
В этой статье коротко расскажу, как устроена библиотека и как выложить свой маленький Python-проект на PyPI, чтобы не наступить на типичные грабли с пакетами.
Что умеет библиотека
Под капотом работает связка из requests для сетевых запросов и BeautifulSoup4 для разбора HTML. Библиотека находит основной блок статьи (#post-content-body), изолирует его от служебных элементов сайта, вытаскивает метаданные и парсит ссылки на изображения.
Основные возможности:
-
Получение заглавия, автора, даты публикации и текста статьи.
-
Выкачивание всех картинок из поста с сохранением оригинальных расширений.
-
Экспорт статьи в готовый
.mdфайл. -
Уважение к лимитам: встроенная обработка таймаутов и стандартных заголовков браузера.
Быстрый старт
Установка из официального репозитория PyPI:
pip install habraloader
Пример использования в скрипте:
from habraloader import HabrParser# Тут инициализируем парсерparser = HabrParser()article = parser.get_article(668378)print(f"Заголовок: {article.title}")print(f"Автор: {article.author}")# Сохранение статьи в Markdownfile_path = article.save_md()print(f"Статья успешно сохранена в файл: {file_path}")# Скачиваем картинки (если они вообще там есть)saved_files = article.save_images(target_dir="downloaded_images")print(f"Успешно сохранено картинок: {len(saved_files)}")
Как это устроено внутри
Архитектура библиотеки состоит из двух ключевых компонентов: датакласса Article и самого класса парсера HabrParser.
Объект статьи хранит распарсенные данные и предоставляет методы для сохранения локально:
def save_md(self, target_dir: str | Path = ".") -> Path: target_path = Path(target_dir) target_path.mkdir(parents=True, exist_ok=True) file_path = target_path / f"{self.id}.md" content = ( f"# {self.title}\n\n" f"**Author:** {self.author}\n" f"**Published:** {self.published_at}\n\n" f"---\n\n" f"{self.content_text}\n" ) with open(file_path, "w", encoding="utf-8") as f: f.write(content) return file_path
Метод создает нужную директорию, формирует Markdown-разметку с метаданными статьи (заголовок, автор, дата публикации) и сохраняет чистый текст статьи в UTF-8
Ссылки
ссылка на оригинал статьи https://habr.com/ru/articles/1073164/