@@ -14,167 +14,45 @@ Perekrestok (Перекрёсток) - https://www.perekrestok.ru/
1414### Принцип работы
1515
1616> Библиотека полностью повторяет сетевую работу обычного пользователя на сайте.
17- Основная логика сетевых запросов заложена в ` api.py ` , она управляется ` PerekrestokAPI() ` в ` manager.py ` .
18- Существует вспомогательный модуль ` abstraction.py ` хранящий в себе статичные классы, которых принимаю в аргументах некоторые методы в ` PerekrestokAPI() ` .
19-
2017
2118
2219# Usage / Использование
23- ### Базовая структура
24- ``` py
25- import asyncio
26- from perekrestok_api import PerekrestokAPI, ABSTRACT
2720
28- async def main ():
29- ...
21+ ``` py
22+ from perekrestok_api import PerekrestokAPI
23+ from perekrestok_api import abstraction
24+
25+
26+ def main ():
27+ with PerekrestokAPI() as Api:
28+ geopos_handler = Api.Geolocation.current()
29+ geopos = geopos_handler.json()
30+ print (f ' Текущий город сессии { geopos[" content" ][" city" ][" name" ]} ( { geopos[" content" ][" city" ][" id" ]} ) ' )
31+
32+ # Получаем список категорий
33+ categories = Api.Catalog.tree()
34+ cat = categories.json()
35+ print (f ' Список категорий: { len (cat[" content" ][" items" ])} ' )
36+
37+ # Выводим первую категорию
38+ print (f ' Категория: { cat[" content" ][" items" ][0 ][" category" ][" title" ]} ( { cat[" content" ][" items" ][0 ][" category" ][" id" ]} ) ' )
39+ # Получаем список товаров
40+ filter = abstraction.CatalogFeedFilter()
41+ filter .CATEGORY_ID = cat[" content" ][" items" ][0 ][" category" ][" id" ]
42+ products = Api.Catalog.feed(filter = filter )
43+ prod = products.json()
44+
45+ # Выводим первый товар
46+ print (f ' Первый товар: { prod[" content" ][" items" ][0 ][" title" ]} ( { prod[" content" ][" items" ][0 ][" id" ]} ) ' )
3047
3148if __name__ == " __main__" :
32- asyncio.run(main())
33- ```
34-
35- ---
36-
37- ### Работа с геолокацией в сессии:
38- * От геолокации и способа получения (доставка/забрать из магазина) зависит выдача каталога!*
39- ``` py
40- async with PerekrestokAPI(
41- debug = False , # Включить ли логирование библиотеки
42- token_retry_attempts = 3 # Количество попыток авторизации
43- ) as Api:
44- geopos_handler = await Api.Geolocation.current()
45- geopos = geopos_handler.response
46- print (f ' Текущий город сессии { geopos[" content" ][" city" ][" name" ]} ( { geopos[" content" ][" city" ][" id" ]} ) ' )
47-
48- # Ищем геолокацию города по названию
49- content_handler = await Api.Geolocation.search(" нижневартовск" )
50- content = content_handler.response
51-
52- # Ищем магазины в этом городе
53- point_in_city_handler = await Api.Geolocation.Shop.on_map(
54- # Мы можем выбрать магазины на карте через геопозицию
55- position = ABSTRACT .Geoposition(content[' content' ][' items' ][0 ][' location' ][' coordinates' ]),
56- # Или через ID населенного пункта (особой разницы нет). Эти параметры не противоречат друг другу.
57- city_id = content[' content' ][' items' ][0 ][' id' ],
58-
59- # Количество магазинов в ответе
60- limit = 3 ,
61-
62- # Фильтр особенностей магазина, `4` - это кофепоинт
63- # С актуальным списком "особенностей" для магазинов можно ознакомиться в `await Api.Geolocation.Shop.features()`
64- features = [4 ],
65-
66- # Сортировка как "самый ближайший"
67- sort = ABSTRACT .GeologicationPointSort.Distance.ASC
68- )
69- point_in_city = point_in_city_handler.response
70-
71- # Выбираем первый (по сути центральный, т.к. сортировка по удалению от конкретной точки)
72- shop_handler = await Api.Geolocation.Selection.shop(point_in_city[' content' ][' items' ][0 ][' id' ])
73- shop = shop_handler.response
74- print (f ' Выбран магазин \" { shop[" content" ][" shop" ][" title" ]} \" , по адресу { shop[" content" ][" shop" ][" address" ]} ' )
75-
76- # Теперь можем проверить, действительно ли сменили геолокацию
77- geopos_handler = await Api.Geolocation.current()
78- geopos = geopos_handler.response
79-
80- print (f ' Текущий город сессии { geopos[" content" ][" city" ][" name" ]} ( { geopos[" content" ][" city" ][" id" ]} ) ' )
49+ main()
8150```
8251``` bash
8352> Текущий город сессии Москва (81)
84- > Выбран магазин " ТЦ Green Park" , по адресу Ханты-Мансийский Автономный округ - Югра, г Нижневартовск, ул Ленина, зд 8
85- > Текущий город сессии Нижневартовск (73)
86- ```
87-
88- ---
89-
90- ### Взаимодействие с каталогом
91-
92- ``` py
93- async with PerekrestokAPI() as Api:
94- # Получение дерева категорий каталога
95- tree_handler = await Api.Catalog.tree()
96- tree = tree_handler.response
97-
98- # Список для хранения всех обработанных товаров
99- products = []
100-
101- # Прогресс-бар для отображения процесса обработки
102- tq = tqdm.tqdm(tree[" content" ][" items" ], desc = ' Обработано категорий' )
103-
104- # Рекурсивная функция для обработки категорий и их подкатегорий
105- async def process_sub (tree_items , depth = 0 ):
106- # Используем прогресс-бар только на верхнем уровне вложенности
107- current_level = tq if depth == 0 else tree_items
108-
109- for category_group in current_level:
110- category = category_group[" category" ]
111-
112- # Формирование фильтра для запроса каталога
113- feed_filter = ABSTRACT .CatalogFeedFilter()
114- feed_filter.CATEGORY_ID = category[" id" ]
115-
116- # Запрашиваем товары из текущей категории
117- catalog_handler = await Api.Catalog.feed(filter = feed_filter)
118- catalog = catalog_handler.response
119- page = 1
120-
121- # Цикл обработки всех страниц товаров в категории
122- while page > 0 and len (catalog[" content" ][" items" ]) > 0 :
123- for product in catalog[" content" ][" items" ]:
124- # Сохраняем название и ID товара
125- products.append(f ' { product[" title" ]} ( { product[" id" ]} ) ' )
126- tq.desc = f ' Обработано карточек: { len (products)} '
127-
128- # Переход к следующей странице или завершение обработки
129- if catalog[' content' ][' paginator' ][' nextPageExists' ]:
130- page += 1
131- catalog_handler = await Api.Catalog.feed(filter = feed_filter, page = page)
132- catalog = catalog_handler.response
133- else :
134- page = - 1
135-
136- # Рекурсивно обрабатываем подкатегории
137- for child in category_group.get(" children" , []):
138- await process_sub([child], depth + 1 )
139-
140- # Запуск обработки дерева категорий
141- await process_sub(tree[" content" ][" items" ])
142-
143- # Вывод итоговой статистики
144- print (f ' Общее количество встреченных карточек: { len (products)} ' )
145- print (f ' Уникальных товаров: { len (set (products))} ' )
146- print (f ' Среднее количество повторений карточки: { round (len (products) / len (set (products)), 2 )} ' )
147- ```
148- ``` bash
149- > Обработано карточек: 41620: 100%| █████████████████████████| 29/29 [03:56< 00:00, 8.15s/it]
150- > Общее количество встреченных карточек: 41620
151- > Уникальных товаров: 17630
152- > Среднее количество повторений карточки: 2.36
153- ```
154-
155- ---
156-
157- ### Загрузка изображений
158- ``` py
159- async with PerekrestokAPI() as Api:
160- img = await Api.General.download_image(" https://cdn-img.perekrestok.ru/i/400x400-fit/xdelivery/files/ae/2a/4f39b2a249768b268ed9f325c155.png" )
161-
162- with open (img.name, " wb" ) as f:
163- f.write(img.read())
164- ```
165-
166- ### Или параллельная загрузка
167- ``` py
168- async with PerekrestokAPI() as Api:
169- tasks = [
170- Api.General.download_image(" https://cdn-img.perekrestok.ru/i/400x400-fit/xdelivery/files/ae/2a/4f39b2a249768b268ed9f325c155.png" ),
171- Api.General.download_image(" https://cdn-img.perekrestok.ru/i/400x400-fit/xdelivery/files/ae/2a/4f39b2a249768b268ed9f325c155.png" )
172- ]
173-
174- results = await asyncio.gather(* tasks)
175- for result in results:
176- with open (result.name, " wb" ) as f:
177- f.write(result.read())
53+ > Список категорий: 31
54+ > Категория: Летний сезон (1585)
55+ > Первый товар: Пиво Василеостровское Тройной пшеничный эль нефильтрованное 6.9%, 750мл (66750)
17856```
17957
18058---
0 commit comments