## Типы данных ``` Project = dict[str, str] ``` ## Функции ### get_kwork_projects(max_pages: int = 1) → list[Project] Собирает проекты со списка страниц категории. **Назначение**: Автоматический обход страниц проектов с извлечением данных из карточек. **Вход**: - `max_page`: `int` - количество страниц для обработки (по умолчанию 1) **Выход**: ``` [ { "title": String, "price": String, "url": String, "description": String } ] ``` --- ### get_project_details(url: str) → Optional[dict] Парсит детальную страницу одного проекта. **Назначение**: Извлечение полной информации о проекте по прямой ссылке. **Вход**: - `url`: `str` - полная ссылка на страницу проекта **Выход**: ``` { "url": String, "title": String, "description": String, "budget": { "desired": String, "maximum": String }, "buyer": { "name": String, "total_projects": String, "hired_percent": String }, "stats": { "offers": String, "time_left": String } } ``` или None при ошибке --- ### normalize_text(text: str) → str Очищает текст от множественных пробелов и переносов. **Выход**: `String` --- ### first_line(text: str) → str Возвращает первую строку текста. **Выход**: `String` --- ### normalize_url(href: str) → str Преобразует относительную ссылку в абсолютную для **Kwork.ru**. **Выход**: `String` --- ### safe_inner_text(locator: Locator, default: str = "") → str Безопасно извлекает текст элемента с таймаутом. **Выход**: `String` --- ### first_text(root: Locator, selectors: list[str], default: str = "") → str Пробует селекторы по очереди, возвращает текст первого найденного. **Выход**: `String` --- ### get_card_root(page: Page, href: str) → Locator Находит корневой контейнер карточки по ссылке проекта. **Выход**: `Locator` --- ### extract_price(card: Locator) → str Извлекает информацию о бюджете из карточки. **Выход**: `String` **Пример:** ``` ("до 5000 ₽ | Допустимый: до 10000 ₽" или "По договоренности") ``` --- ### extract_description(card: Locator) → str Извлекает краткое описание проекта из карточки. **Выход**: `String` --- ### extract_kwork_project(page: Page, title_block: Locator) → Optional[Project] Экстрактор данных одной карточки по блоку заголовка. **Выход**: `Project` или `None` --- ### clean(text: str) → str Очищает текст от неразрывных пробелов и лишних символов. **Выход**: `String` --- ### get_text(page: Page, selector: str) → str Извлекает текст по CSS-селектору. **Выход**: `String` ## Использование ```python import asyncio from main import get_kwork_projects, get_project_details # Список проектов projects = asyncio.run(get_kwork_projects(max_pages=3)) # Детали проекта details = asyncio.run(get_project_details("https://kwork.ru/projects/123")) ```