Skip to main content

A Python API client for Perekrestok catalog

Project description

Perekrestok API (not official)

Tests Coverage PyPI - Python Version PyPI - Package Version PyPI - Downloads License Discord Telegram

Perekrestok (Перекрёсток) - https://www.perekrestok.ru/

Принцип работы

Библиотека полностью повторяет сетевую работу обычного пользователя на сайте. Основная логика сетевых запросов заложена в api.py, она управляется PerekrestokAPI() в manager.py. Существует вспомогательный модуль abstraction.py хранящий в себе статичные классы, которых принимаю в аргументах некоторые методы в PerekrestokAPI().

Usage / Использование

Базовая структура

import asyncio
from perekrestok_api import PerekrestokAPI, ABSTRACT

async def main():
    ...

if __name__ == "__main__":
    asyncio.run(main())

Работа с геолокацией в сессии:

От геолокации и способа получения (доставка/забрать из магазина) зависит выдача каталога!

async with PerekrestokAPI(
        debug = False, # Включить ли логирование библиотеки
        token_retry_attempts = 3 # Количество попыток авторизации
    ) as Api:
    geopos_handler = await Api.Geolocation.current()
    geopos = geopos_handler.response
    print(f'Текущий город сессии {geopos["content"]["city"]["name"]} ({geopos["content"]["city"]["id"]})')

    # Ищем геолокацию города по названию
    content_handler = await Api.Geolocation.search("нижневартовск")
    content = content_handler.response

    # Ищем магазины в этом городе
    point_in_city_handler = await Api.Geolocation.Shop.on_map(
        # Мы можем выбрать магазины на карте через геопозицию
        position=ABSTRACT.Geoposition(content['content']['items'][0]['location']['coordinates']),
        # Или через ID населенного пункта (особой разницы нет). Эти параметры не противоречат друг другу.
        city_id=content['content']['items'][0]['id'],
        
        # Количество магазинов в ответе
        limit=3,

        # Фильтр особенностей магазина, `4` - это кофепоинт
        # С актуальным списком "особенностей" для магазинов можно ознакомиться в `await Api.Geolocation.Shop.features()`
        features=[4],

        # Сортировка как "самый ближайший"
        sort=ABSTRACT.GeologicationPointSort.Distance.ASC
    )
    point_in_city = point_in_city_handler.response

    # Выбираем первый (по сути центральный, т.к. сортировка по удалению от конкретной точки)
    shop_handler = await Api.Geolocation.Selection.shop(point_in_city['content']['items'][0]['id'])
    shop = shop_handler.response
    print(f'Выбран магазин \"{shop["content"]["shop"]["title"]}\", по адресу {shop["content"]["shop"]["address"]}')

    # Теперь можем проверить, действительно ли сменили геолокацию
    geopos_handler = await Api.Geolocation.current()
    geopos = geopos_handler.response

    print(f'Текущий город сессии {geopos["content"]["city"]["name"]} ({geopos["content"]["city"]["id"]})')
> Текущий город сессии Москва (81)
> Выбран магазин "ТЦ Green Park", по адресу Ханты-Мансийский Автономный округ - Югра, г Нижневартовск, ул Ленина, зд 8
> Текущий город сессии Нижневартовск (73)

Взаимодействие с каталогом

async with PerekrestokAPI() as Api:
    # Получение дерева категорий каталога
    tree_handler = await Api.Catalog.tree()
    tree = tree_handler.response

    # Список для хранения всех обработанных товаров
    products = []

    # Прогресс-бар для отображения процесса обработки
    tq = tqdm.tqdm(tree["content"]["items"], desc='Обработано категорий')

    # Рекурсивная функция для обработки категорий и их подкатегорий
    async def process_sub(tree_items, depth=0):
        # Используем прогресс-бар только на верхнем уровне вложенности
        current_level = tq if depth == 0 else tree_items

        for category_group in current_level:
            category = category_group["category"]

            # Формирование фильтра для запроса каталога
            feed_filter = ABSTRACT.CatalogFeedFilter()
            feed_filter.CATEGORY_ID = category["id"]

            # Запрашиваем товары из текущей категории
            catalog_handler = await Api.Catalog.feed(filter=feed_filter)
            catalog = catalog_handler.response
            page = 1

            # Цикл обработки всех страниц товаров в категории
            while page > 0 and len(catalog["content"]["items"]) > 0:
                for product in catalog["content"]["items"]:
                    # Сохраняем название и ID товара
                    products.append(f'{product["title"]} ({product["id"]})')
                    tq.desc = f'Обработано карточек: {len(products)}'

                # Переход к следующей странице или завершение обработки
                if catalog['content']['paginator']['nextPageExists']:
                    page += 1
                    catalog_handler = await Api.Catalog.feed(filter=feed_filter, page=page)
                    catalog = catalog_handler.response
                else:
                    page = -1

            # Рекурсивно обрабатываем подкатегории
            for child in category_group.get("children", []):
                await process_sub([child], depth + 1)

    # Запуск обработки дерева категорий
    await process_sub(tree["content"]["items"])

    # Вывод итоговой статистики
    print(f'Общее количество встреченных карточек: {len(products)}')
    print(f'Уникальных товаров: {len(set(products))}')
    print(f'Среднее количество повторений карточки: {round(len(products) / len(set(products)), 2)}')
> Обработано карточек: 41620: 100%|█████████████████████████| 29/29 [03:56<00:00,  8.15s/it]
> Общее количество встреченных карточек: 41620
> Уникальных товаров: 17630
> Среднее количество повторений карточки: 2.36

Загрузка изображений

async with PerekrestokAPI() as Api:
    img = await Api.General.download_image("https://cdn-img.perekrestok.ru/i/400x400-fit/xdelivery/files/ae/2a/4f39b2a249768b268ed9f325c155.png")

    with open(img.name, "wb") as f:
        f.write(img.read())

Или параллельная загрузка

async with PerekrestokAPI() as Api:
    tasks = [
        Api.General.download_image("https://cdn-img.perekrestok.ru/i/400x400-fit/xdelivery/files/ae/2a/4f39b2a249768b268ed9f325c155.png"),
        Api.General.download_image("https://cdn-img.perekrestok.ru/i/400x400-fit/xdelivery/files/ae/2a/4f39b2a249768b268ed9f325c155.png")
    ]

    results = await asyncio.gather(*tasks)
    for result in results:
        with open(result.name, "wb") as f:
            f.write(result.read())

Report / Обратная связь

If you have any problems using it / suggestions, do not hesitate to write to the project's GitHub!

Если у вас возникнут проблемы в использовании / пожелания, не стесняйтесь писать на GitHub проекта!

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

perekrestok_api-0.1.6.1.tar.gz (18.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

perekrestok_api-0.1.6.1-py3-none-any.whl (17.8 kB view details)

Uploaded Python 3

File details

Details for the file perekrestok_api-0.1.6.1.tar.gz.

File metadata

  • Download URL: perekrestok_api-0.1.6.1.tar.gz
  • Upload date:
  • Size: 18.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for perekrestok_api-0.1.6.1.tar.gz
Algorithm Hash digest
SHA256 f272d6dfff753e210b0179d9d0c313e4afeeb9925b6ba576c3b17a201c82df6f
MD5 5a881c1b55444ea3e7d38c21d1779a1e
BLAKE2b-256 f839e54329c2e91a748e7c906e9ea0d455b0dc5ae43265bd03e987062ab9d910

See more details on using hashes here.

Provenance

The following attestation bundles were made for perekrestok_api-0.1.6.1.tar.gz:

Publisher: python-publish.yml on Open-Inflation/perekrestok_api

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file perekrestok_api-0.1.6.1-py3-none-any.whl.

File metadata

File hashes

Hashes for perekrestok_api-0.1.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fb446780e1a1d702d7221b0037068fcdf69a5419463de25623290fb5987360d2
MD5 b6ad5a82c8ad221496d638588946075b
BLAKE2b-256 39b8497c97e106602695e5f0103363314cbdeef6b65d82b7b42a7fff097b9f10

See more details on using hashes here.

Provenance

The following attestation bundles were made for perekrestok_api-0.1.6.1-py3-none-any.whl:

Publisher: python-publish.yml on Open-Inflation/perekrestok_api

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page