Тесты kit-парсеров на сохранённых страницах: дом Авито, выдачи Циана и Яндекса (#2422, #2408)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 32s
CI / changes (pull_request) Successful in 33s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 8m7s
All checks were successful
CI Trade-In / changes (pull_request) Successful in 32s
CI / changes (pull_request) Successful in 33s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 8m7s
После удаления golden-parity (#2419) разбор avito.houses, cian.serp и yandex.serp не проверял ни один тест: правка извлечения поля в kit проходила бы зелёной. - avito.houses: обе осиротевшие карточки дома (572538, 115188) — характеристики, рейтинг из reviews.filterEntries (#1789), отзывы, история размещений, мини-выдача с продавцом, рекомендации; карточка ЖК 12879380 — ветка developmentPage. - avito.serp: цена, комнаты, площадь, этаж/этажность и дата из sortTimeStamp на avito_serp_sample.html. - cian.serp: живая выдача 2026-09-17, урезанная до 4 offers и читаемых ключей (без телефонов и данных пользователя): вторичка, новостройка с домом, отделка и балкон, новостройка без улицы — номер дома не выдумывается (#1773). - yandex.serp: живой gate-API 2026-09-17: канонизация партнёрского url (#2235), собственник/агентство, студия без roomsTotal, новостройка без оценки. - guard: ни один модуль scraper_kit не импортирует app.* (AST, включая ленивые импорты) — замена удалённого test_kit_avito_has_no_app_imports. Тесты лежат в tradein-mvp/backend/tests/scrapers, а не в packages/scraper-kit/tests: CI гоняет pytest только из backend, каталог в пакете не собирался бы никем. Мутационный прогон: 9 порч kit (рейтинг #1789, developmentPage, цена истории, этаж Авито, год сдачи и адрес Циана, url и студия Яндекса, import app) — каждая роняет хотя бы один тест. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
85d455e387
commit
6003ddedad
5 changed files with 1832 additions and 0 deletions
911
tradein-mvp/backend/tests/fixtures/cian_serp_ekb_2room_trimmed.html
vendored
Normal file
911
tradein-mvp/backend/tests/fixtures/cian_serp_ekb_2room_trimmed.html
vendored
Normal file
|
|
@ -0,0 +1,911 @@
|
||||||
|
<!doctype html>
|
||||||
|
<!--
|
||||||
|
#2422: живая выдача Циана, снята 2026-09-17 (curl_cffi impersonate=chrome, HTTP 200, ~3 МБ):
|
||||||
|
GET https://ekb.cian.ru/cat.php?deal_type=sale&engine_version=2&offer_type=flat®ion=4743&room2=1
|
||||||
|
Урезано до того, что читает CianScraper._parse_serp_html / _offer_to_lot:
|
||||||
|
- из 154 записей _cianConfig['frontend-serp'] оставлены projectName и initialState;
|
||||||
|
- в initialState только results.totalOffers и 4 из 28 offers, по одному на ветку:
|
||||||
|
331661795 вторичка, 333599038 новостройка с домом в geo.address,
|
||||||
|
333279363 новостройка с decoration=fine, 321628098 новостройка без улицы и дома;
|
||||||
|
- у offer только ключи, которые читает парсер; phones/user/userId убраны (PII),
|
||||||
|
photos урезаны до 3 fullUrl, у geo.address/undergrounds только читаемые поля.
|
||||||
|
Форма записи (.concat([...]) с JSON-массивом) и значения полей не менялись.
|
||||||
|
-->
|
||||||
|
<html><head><meta charset="utf-8"></head><body>
|
||||||
|
<script type="text/javascript">
|
||||||
|
window._cianConfig = window._cianConfig || {};
|
||||||
|
window._cianConfig['frontend-serp'] = (window._cianConfig['frontend-serp'] || []).concat([
|
||||||
|
{
|
||||||
|
"key": "projectName",
|
||||||
|
"value": "frontend-serp",
|
||||||
|
"priority": 1000,
|
||||||
|
"filter": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "initialState",
|
||||||
|
"value": {
|
||||||
|
"results": {
|
||||||
|
"totalOffers": 13895,
|
||||||
|
"offers": [
|
||||||
|
{
|
||||||
|
"cianId": 331661795,
|
||||||
|
"id": 331661795,
|
||||||
|
"fullUrl": "https://ekb.cian.ru/sale/flat/331661795/?context=4.JppPDee85nA.3hAoeZtPv9-CCGqBSDAI8EqioM8KBdEBjsgdLaVHspglG86Z8YBFyLQQuLYOzUIJ9UfTORZd8UX_kw&mlSearchSessionGuid=924c429bf7495771ff77b66074cdf292",
|
||||||
|
"bargainTerms": {
|
||||||
|
"bargainAllowed": null,
|
||||||
|
"vatType": null,
|
||||||
|
"agentFee": null,
|
||||||
|
"clientFee": null,
|
||||||
|
"paymentPeriod": null,
|
||||||
|
"leaseType": null,
|
||||||
|
"deposit": null,
|
||||||
|
"mortgageAllowed": true,
|
||||||
|
"vatPrice": null,
|
||||||
|
"utilitiesTerms": null,
|
||||||
|
"price": 7990000,
|
||||||
|
"leaseTermType": null,
|
||||||
|
"priceRur": 7990000,
|
||||||
|
"tags": [],
|
||||||
|
"priceType": "all",
|
||||||
|
"priceForWorkplace": null,
|
||||||
|
"saleType": "alternative",
|
||||||
|
"currency": "rur",
|
||||||
|
"agentBonus": null
|
||||||
|
},
|
||||||
|
"roomsCount": 2,
|
||||||
|
"flatType": "rooms",
|
||||||
|
"totalArea": "47.2",
|
||||||
|
"livingArea": "28.0",
|
||||||
|
"kitchenArea": "7.5",
|
||||||
|
"floorNumber": 2,
|
||||||
|
"building": {
|
||||||
|
"floorsCount": 17,
|
||||||
|
"parking": {
|
||||||
|
"locationType": null,
|
||||||
|
"type": "ground",
|
||||||
|
"priceEntry": null,
|
||||||
|
"purposeType": null,
|
||||||
|
"isFree": null,
|
||||||
|
"isAvailable": null,
|
||||||
|
"currency": null,
|
||||||
|
"priceMonthly": null,
|
||||||
|
"placesCount": null
|
||||||
|
},
|
||||||
|
"deadline": null,
|
||||||
|
"type": null,
|
||||||
|
"materialType": "panel",
|
||||||
|
"heatingType": null,
|
||||||
|
"accessType": null,
|
||||||
|
"classType": null,
|
||||||
|
"buildYear": 1980,
|
||||||
|
"cargoLiftsCount": 1,
|
||||||
|
"passengerLiftsCount": 1
|
||||||
|
},
|
||||||
|
"cadastralNumber": null,
|
||||||
|
"buildingCadastralNumber": null,
|
||||||
|
"geo": {
|
||||||
|
"coordinates": {
|
||||||
|
"lat": 56.820035,
|
||||||
|
"lng": 60.634287
|
||||||
|
},
|
||||||
|
"address": [
|
||||||
|
{
|
||||||
|
"type": "location",
|
||||||
|
"geoType": "location",
|
||||||
|
"name": "Свердловская",
|
||||||
|
"fullName": "Свердловская область",
|
||||||
|
"id": 4612
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "location",
|
||||||
|
"geoType": "location",
|
||||||
|
"name": "Екатеринбург",
|
||||||
|
"fullName": "Екатеринбург",
|
||||||
|
"id": 4743
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "raion",
|
||||||
|
"geoType": "district",
|
||||||
|
"name": "Октябрьский",
|
||||||
|
"fullName": "р-н Октябрьский",
|
||||||
|
"id": 290
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "mikroraion",
|
||||||
|
"geoType": "district",
|
||||||
|
"name": "Парковый",
|
||||||
|
"fullName": "мкр. Парковый",
|
||||||
|
"id": 1489
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "metro",
|
||||||
|
"geoType": "underground",
|
||||||
|
"name": "Геологическая",
|
||||||
|
"fullName": "м. Геологическая",
|
||||||
|
"id": 346
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "street",
|
||||||
|
"geoType": "street",
|
||||||
|
"name": "Большакова",
|
||||||
|
"fullName": "улица Большакова",
|
||||||
|
"id": 1486289
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "house",
|
||||||
|
"geoType": "house",
|
||||||
|
"name": "13",
|
||||||
|
"fullName": "13",
|
||||||
|
"id": 10385250
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"undergrounds": [
|
||||||
|
{
|
||||||
|
"name": "Геологическая",
|
||||||
|
"time": 5,
|
||||||
|
"transportType": "transport",
|
||||||
|
"lineColor": "00701A",
|
||||||
|
"lineId": 26,
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Чкаловская",
|
||||||
|
"time": 5,
|
||||||
|
"transportType": "transport",
|
||||||
|
"lineColor": "00701A",
|
||||||
|
"lineId": 26,
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Площадь 1905 года",
|
||||||
|
"time": 6,
|
||||||
|
"transportType": "transport",
|
||||||
|
"lineColor": "00701A",
|
||||||
|
"lineId": 26,
|
||||||
|
"isDefault": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"newbuilding": null,
|
||||||
|
"balconiesCount": 0,
|
||||||
|
"loggiasCount": 1,
|
||||||
|
"bedroomsCount": null,
|
||||||
|
"hasFurniture": true,
|
||||||
|
"isSoldFurnished": true,
|
||||||
|
"decoration": null,
|
||||||
|
"isByHomeowner": false,
|
||||||
|
"isPro": true,
|
||||||
|
"isApartments": false,
|
||||||
|
"isRosreestrChecked": false,
|
||||||
|
"description": "В продаже двухкомнатная квартира с качественным ремонтом. \n\nРайон расположения квартиры с развитой инфраструктурой. Рядом множество детских садов и школ, городской парк развлечений \"Маяковского\" Различные бесплатные спортивные школы и секции. \n\nВо дворе дома есть бесплатные парковочные места. Места общего пользования в доме после капитального ремонта, на стенах первого этажа керамогранит, оба лифта новые. Установлена качественная сейф-дверь. В прихожей на полу керамогранитная плитка. Имеется теплый пол в прихожей. Удобно содержать пол в прихожей в чистоте. \nОстается шкаф купе в прихожей. На кухне установлен кухонный гарнитур, оставляем бытовую технику - варочную панель, духовой шкаф, вытяжку, посудомоечную машину. Окна во всей квартире и на лоджии заменены на новые пластиковые. Сан узел раздельный, в кафеле. Стояки ГВС И ХВС заменены в 2017 году.\n\nВ квартире заменена вся электропроводка. Утеплена лоджия, на полу кафельная плитка, на лоджии имеется теплый пол. Так же в стоимость квартиры входят все светильники и шторы. Рассмотрим трейд ин: у Вас не продана своя недвижимость - у нас есть кому ее предложить.\n Найдем покупателя на Вашу квартиру с фиксацией цены на наш объект. Звоните и записывайтесь на просмотр! \nДобавляйте объявление в избранное, что бы не потерять его. Просто звоните или пишите и мы найдем способ как Вам приобрести квартиру в Вашем бюджете! 2-комнатная квартира в Екатеринбурге.",
|
||||||
|
"descriptionMinhash": [
|
||||||
|
16147461,
|
||||||
|
5781654,
|
||||||
|
4548911,
|
||||||
|
115530169,
|
||||||
|
2088518,
|
||||||
|
13989882,
|
||||||
|
5236906,
|
||||||
|
29626041,
|
||||||
|
89222106,
|
||||||
|
31854558,
|
||||||
|
1755821,
|
||||||
|
30053968,
|
||||||
|
4178831,
|
||||||
|
69970867,
|
||||||
|
23526500,
|
||||||
|
79279,
|
||||||
|
22630780,
|
||||||
|
105139689,
|
||||||
|
7157020,
|
||||||
|
7498881,
|
||||||
|
439139,
|
||||||
|
40231865,
|
||||||
|
5793994,
|
||||||
|
2284150,
|
||||||
|
9460550,
|
||||||
|
20249216,
|
||||||
|
16249532,
|
||||||
|
8291340,
|
||||||
|
9226251,
|
||||||
|
55362858,
|
||||||
|
4609260,
|
||||||
|
18591719
|
||||||
|
],
|
||||||
|
"photos": [
|
||||||
|
{
|
||||||
|
"fullUrl": "https://images.cdn-cian.ru/images/kvartira-ekaterinburg-bolshakova-ulica-2915101466-1.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fullUrl": "https://images.cdn-cian.ru/images/kvartira-ekaterinburg-bolshakova-ulica-2914203429-1.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fullUrl": "https://images.cdn-cian.ru/images/kvartira-ekaterinburg-bolshakova-ulica-2915101469-1.jpg"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"addedTimestamp": 1789387127,
|
||||||
|
"offerType": "flat",
|
||||||
|
"category": "flatSale",
|
||||||
|
"fromDeveloper": false,
|
||||||
|
"buildersIds": [],
|
||||||
|
"isLayoutApproved": null,
|
||||||
|
"isByCommercialOwner": null,
|
||||||
|
"isCianPartner": false,
|
||||||
|
"descriptionWordsHighlighted": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cianId": 333599038,
|
||||||
|
"id": 333599038,
|
||||||
|
"fullUrl": "https://ekb.cian.ru/sale/flat/333599038/?context=4.RIlzprvdmBE.EoIb2G8IrpAJRWmWSKXZB54SBE-BI5E9ffyir3i1BCpfutwDcbFaqH8RXGcSSW2eGb_oYww9PzpC-g&mlSearchSessionGuid=924c429bf7495771ff77b66074cdf292",
|
||||||
|
"bargainTerms": {
|
||||||
|
"price": 4834000,
|
||||||
|
"vatPrice": null,
|
||||||
|
"deposit": null,
|
||||||
|
"saleType": "fz214",
|
||||||
|
"bargainAllowed": null,
|
||||||
|
"vatType": null,
|
||||||
|
"agentBonus": null,
|
||||||
|
"priceForWorkplace": null,
|
||||||
|
"agentFee": null,
|
||||||
|
"priceRur": 4834000,
|
||||||
|
"leaseType": null,
|
||||||
|
"mortgageAllowed": null,
|
||||||
|
"clientFee": null,
|
||||||
|
"paymentPeriod": null,
|
||||||
|
"tags": [],
|
||||||
|
"priceType": "all",
|
||||||
|
"utilitiesTerms": null,
|
||||||
|
"leaseTermType": null,
|
||||||
|
"currency": "rur"
|
||||||
|
},
|
||||||
|
"roomsCount": 2,
|
||||||
|
"flatType": "rooms",
|
||||||
|
"totalArea": "36.04",
|
||||||
|
"livingArea": "19.8",
|
||||||
|
"kitchenArea": null,
|
||||||
|
"floorNumber": 22,
|
||||||
|
"building": {
|
||||||
|
"accessType": null,
|
||||||
|
"materialType": "monolith",
|
||||||
|
"cargoLiftsCount": null,
|
||||||
|
"deadline": {
|
||||||
|
"quarterEnd": "2028-12-31",
|
||||||
|
"year": 2028,
|
||||||
|
"quarter": "fourth",
|
||||||
|
"isComplete": false
|
||||||
|
},
|
||||||
|
"type": null,
|
||||||
|
"buildYear": null,
|
||||||
|
"heatingType": null,
|
||||||
|
"passengerLiftsCount": 7,
|
||||||
|
"classType": null,
|
||||||
|
"floorsCount": 32,
|
||||||
|
"parking": null
|
||||||
|
},
|
||||||
|
"cadastralNumber": null,
|
||||||
|
"buildingCadastralNumber": null,
|
||||||
|
"geo": {
|
||||||
|
"coordinates": {
|
||||||
|
"lng": 60.538293335967175,
|
||||||
|
"lat": 56.875540746307834
|
||||||
|
},
|
||||||
|
"address": [
|
||||||
|
{
|
||||||
|
"type": "location",
|
||||||
|
"geoType": "location",
|
||||||
|
"name": "Свердловская",
|
||||||
|
"fullName": "Свердловская область",
|
||||||
|
"id": 4612
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "location",
|
||||||
|
"geoType": "location",
|
||||||
|
"name": "Екатеринбург",
|
||||||
|
"fullName": "Екатеринбург",
|
||||||
|
"id": 4743
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "raion",
|
||||||
|
"geoType": "district",
|
||||||
|
"name": "Железнодорожный",
|
||||||
|
"fullName": "р-н Железнодорожный",
|
||||||
|
"id": 287
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "mikroraion",
|
||||||
|
"geoType": "district",
|
||||||
|
"name": "Старая Сортировка",
|
||||||
|
"fullName": "мкр. Старая Сортировка",
|
||||||
|
"id": 1494
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "metro",
|
||||||
|
"geoType": "underground",
|
||||||
|
"name": "Уральская",
|
||||||
|
"fullName": "м. Уральская",
|
||||||
|
"id": 343
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "street",
|
||||||
|
"geoType": "street",
|
||||||
|
"name": "Проходной",
|
||||||
|
"fullName": "переулок Проходной",
|
||||||
|
"id": 1486939
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "house",
|
||||||
|
"geoType": "house",
|
||||||
|
"name": "1Б",
|
||||||
|
"fullName": "1Б",
|
||||||
|
"id": 13406495
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"undergrounds": [
|
||||||
|
{
|
||||||
|
"name": "Уральская",
|
||||||
|
"time": 9,
|
||||||
|
"transportType": "transport",
|
||||||
|
"lineColor": "00701A",
|
||||||
|
"lineId": 26,
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Уралмаш",
|
||||||
|
"time": 9,
|
||||||
|
"transportType": "transport",
|
||||||
|
"lineColor": "00701A",
|
||||||
|
"lineId": 26,
|
||||||
|
"isDefault": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Машиностроителей",
|
||||||
|
"time": 9,
|
||||||
|
"transportType": "transport",
|
||||||
|
"lineColor": "00701A",
|
||||||
|
"lineId": 26,
|
||||||
|
"isDefault": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"newbuilding": {
|
||||||
|
"showJkReliableFlag": false,
|
||||||
|
"isFromDeveloper": true,
|
||||||
|
"name": "Астон. Движение Вверх",
|
||||||
|
"isFromLeadFactory": false,
|
||||||
|
"isFichering": true,
|
||||||
|
"isFromBuilder": true,
|
||||||
|
"isPremium": false,
|
||||||
|
"house": {
|
||||||
|
"finishDate": {
|
||||||
|
"year": 2028,
|
||||||
|
"quarter": 4
|
||||||
|
},
|
||||||
|
"section": null,
|
||||||
|
"name": "Дом 5",
|
||||||
|
"isFinished": false,
|
||||||
|
"id": 10930182
|
||||||
|
},
|
||||||
|
"hasFlatTourBooking": false,
|
||||||
|
"comparisonStatus": null,
|
||||||
|
"id": 5779142,
|
||||||
|
"isSalesLeader": null,
|
||||||
|
"isFromSeller": false,
|
||||||
|
"countPromos": 2,
|
||||||
|
"snippetType": "advanced"
|
||||||
|
},
|
||||||
|
"balconiesCount": null,
|
||||||
|
"loggiasCount": null,
|
||||||
|
"bedroomsCount": null,
|
||||||
|
"hasFurniture": null,
|
||||||
|
"decoration": null,
|
||||||
|
"isByHomeowner": null,
|
||||||
|
"isPro": true,
|
||||||
|
"isApartments": false,
|
||||||
|
"isRosreestrChecked": false,
|
||||||
|
"description": "2-комнатная квартира с предчистовой отделкой в ЖК \"Астон. Движение вверх\" на 22 этаже. Общая площадь 36.04 м², жилая 19.83 м². \n\n\"Астон. Движение вверх\" два монолитно-блочных дома на Новой Сортировке в Екатеринбурге: один высотой 16 этажей, другой 32 этажа. Проект продолжает историю соседнего квартала \"Астон. Движение\", который уже полюбился жителям района. Строительство ведётся на месте бывшего Виншампанкомбината у этого места есть своя душа и почти вековая история.\n\nАрхитектура обыгрывает наследие территории: палитра фасадов, плавные линии и изгибы переосмысляют фактуры продукции комбината. В проекте много внимания уделено свету увеличенное остекление, продуманные планировки без глухих коридоров и тёмных углов. Из окон верхних этажей открывается панорама города это самый высокий комфорт-класс в микрорайоне.\n\nВ квартирах просторные кухни-гостиные, мастер-спальни с гардеробными, балконы и тёплые лоджии. В некоторых планировках окна в ванной комнате, что наполняет утро солнечным светом. В 32-этажной секции пять грузопассажирских лифтов, в 16-этажной по два лифта на этаж.\n\nДвор закрыт от машин, с зонами для детей разного возраста: для малышей песочницы и качели, для подростков пространство для встреч с друзьями. В просторных входных группах на первых этажах есть место для колясок. Первая очередь квартала уже сдана по утрам здесь пахнет кофе из кафе на первых этажах, вечерами гуляют с колясками и собаками.\n\nРасположение пересечение улицы Пехотинцев и Проходного переулка, в 5 минутах от Бебеля. Рядом детские сады, школы, поликлиники, торговые и фитнес-центры, остановки общественного транспорта. До центра Екатеринбурга 2530 минут на машине. Срок сдачи IV квартал 2028 года.\n\nЗастройщик: федеральный девелопер Астон, реализующий проекты в пяти городах России. Уже передано более 400 000 м² жилья. Продам 2-комнатную квартиру в Екатеринбурге.",
|
||||||
|
"descriptionMinhash": [
|
||||||
|
18308017,
|
||||||
|
8359824,
|
||||||
|
15811915,
|
||||||
|
9618444,
|
||||||
|
2088518,
|
||||||
|
6143519,
|
||||||
|
1770676,
|
||||||
|
52418947,
|
||||||
|
12009655,
|
||||||
|
11955293,
|
||||||
|
15731187,
|
||||||
|
1006418,
|
||||||
|
4178831,
|
||||||
|
5064683,
|
||||||
|
5165062,
|
||||||
|
28709808,
|
||||||
|
27942,
|
||||||
|
105139689,
|
||||||
|
37372265,
|
||||||
|
6351486,
|
||||||
|
31972117,
|
||||||
|
53400966,
|
||||||
|
5793994,
|
||||||
|
30731728,
|
||||||
|
9460550,
|
||||||
|
5740363,
|
||||||
|
24836331,
|
||||||
|
794253,
|
||||||
|
37707718,
|
||||||
|
2676229,
|
||||||
|
24769842,
|
||||||
|
1768206
|
||||||
|
],
|
||||||
|
"photos": [
|
||||||
|
{
|
||||||
|
"fullUrl": "https://images.cdn-cian.ru/images/2957954042-1.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fullUrl": "https://images.cdn-cian.ru/images/2957954049-1.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fullUrl": "https://images.cdn-cian.ru/images/2957954053-1.jpg"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"addedTimestamp": 1789377541,
|
||||||
|
"offerType": "flat",
|
||||||
|
"category": "newBuildingFlatSale",
|
||||||
|
"fromDeveloper": true,
|
||||||
|
"buildersIds": [
|
||||||
|
10137
|
||||||
|
],
|
||||||
|
"isLayoutApproved": null,
|
||||||
|
"isByCommercialOwner": null,
|
||||||
|
"isCianPartner": false,
|
||||||
|
"descriptionWordsHighlighted": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cianId": 333279363,
|
||||||
|
"id": 333279363,
|
||||||
|
"fullUrl": "https://ekb.cian.ru/sale/flat/333279363/?context=4.eJtxwNSILJE.YF5Ute3CO5a6ojZp8vw4v4wbhDX3F1ibU5rfq6T0Mt7TEHmtX3_CR5L7_Brx_JZMKAgoly3KHiIsxg&mlSearchSessionGuid=924c429bf7495771ff77b66074cdf292",
|
||||||
|
"bargainTerms": {
|
||||||
|
"tags": [],
|
||||||
|
"currency": "rur",
|
||||||
|
"priceType": "all",
|
||||||
|
"paymentPeriod": null,
|
||||||
|
"mortgageAllowed": null,
|
||||||
|
"leaseTermType": null,
|
||||||
|
"priceForWorkplace": null,
|
||||||
|
"clientFee": null,
|
||||||
|
"agentBonus": null,
|
||||||
|
"saleType": "pdkp",
|
||||||
|
"price": 8523568,
|
||||||
|
"priceRur": 8523568,
|
||||||
|
"deposit": null,
|
||||||
|
"vatPrice": null,
|
||||||
|
"vatType": null,
|
||||||
|
"leaseType": null,
|
||||||
|
"agentFee": null,
|
||||||
|
"utilitiesTerms": null,
|
||||||
|
"bargainAllowed": null
|
||||||
|
},
|
||||||
|
"roomsCount": 2,
|
||||||
|
"flatType": "rooms",
|
||||||
|
"totalArea": "56.03",
|
||||||
|
"livingArea": "21.8",
|
||||||
|
"kitchenArea": null,
|
||||||
|
"floorNumber": 4,
|
||||||
|
"building": {
|
||||||
|
"floorsCount": 8,
|
||||||
|
"deadline": {
|
||||||
|
"year": 2026,
|
||||||
|
"isComplete": true,
|
||||||
|
"quarterEnd": "2026-09-30",
|
||||||
|
"quarter": "third"
|
||||||
|
},
|
||||||
|
"cargoLiftsCount": null,
|
||||||
|
"type": null,
|
||||||
|
"accessType": null,
|
||||||
|
"passengerLiftsCount": null,
|
||||||
|
"classType": null,
|
||||||
|
"parking": null,
|
||||||
|
"materialType": null,
|
||||||
|
"heatingType": null,
|
||||||
|
"buildYear": null
|
||||||
|
},
|
||||||
|
"cadastralNumber": null,
|
||||||
|
"buildingCadastralNumber": null,
|
||||||
|
"geo": {
|
||||||
|
"coordinates": {
|
||||||
|
"lat": 56.833388,
|
||||||
|
"lng": 60.520165
|
||||||
|
},
|
||||||
|
"address": [
|
||||||
|
{
|
||||||
|
"type": "location",
|
||||||
|
"geoType": "location",
|
||||||
|
"name": "Свердловская",
|
||||||
|
"fullName": "Свердловская область",
|
||||||
|
"id": 4612
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "location",
|
||||||
|
"geoType": "location",
|
||||||
|
"name": "Екатеринбург",
|
||||||
|
"fullName": "Екатеринбург",
|
||||||
|
"id": 4743
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "raion",
|
||||||
|
"geoType": "district",
|
||||||
|
"name": "Верх-Исетский",
|
||||||
|
"fullName": "р-н Верх-Исетский",
|
||||||
|
"id": 286
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "mikroraion",
|
||||||
|
"geoType": "district",
|
||||||
|
"name": "ВИЗ",
|
||||||
|
"fullName": "мкр. ВИЗ",
|
||||||
|
"id": 1468
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "metro",
|
||||||
|
"geoType": "underground",
|
||||||
|
"name": "Геологическая",
|
||||||
|
"fullName": "м. Геологическая",
|
||||||
|
"id": 346
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "street",
|
||||||
|
"geoType": "street",
|
||||||
|
"name": "Крауля",
|
||||||
|
"fullName": "улица Крауля",
|
||||||
|
"id": 1486179
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "house",
|
||||||
|
"geoType": "house",
|
||||||
|
"name": "170Б",
|
||||||
|
"fullName": "170Б",
|
||||||
|
"id": 16773087
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"undergrounds": [
|
||||||
|
{
|
||||||
|
"name": "Геологическая",
|
||||||
|
"time": 9,
|
||||||
|
"transportType": "transport",
|
||||||
|
"lineColor": "00701A",
|
||||||
|
"lineId": 26,
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Площадь 1905 года",
|
||||||
|
"time": 10,
|
||||||
|
"transportType": "transport",
|
||||||
|
"lineColor": "00701A",
|
||||||
|
"lineId": 26,
|
||||||
|
"isDefault": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Уральская",
|
||||||
|
"time": 13,
|
||||||
|
"transportType": "transport",
|
||||||
|
"lineColor": "00701A",
|
||||||
|
"lineId": 26,
|
||||||
|
"isDefault": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"newbuilding": {
|
||||||
|
"id": 49143,
|
||||||
|
"showJkReliableFlag": false,
|
||||||
|
"isFromSeller": false,
|
||||||
|
"isFichering": true,
|
||||||
|
"name": "Янтарная Долина",
|
||||||
|
"isPremium": true,
|
||||||
|
"house": {
|
||||||
|
"id": 10931059,
|
||||||
|
"name": "6 очередь",
|
||||||
|
"section": "Секция 2",
|
||||||
|
"finishDate": {
|
||||||
|
"quarter": 3,
|
||||||
|
"year": 2026
|
||||||
|
},
|
||||||
|
"isFinished": true
|
||||||
|
},
|
||||||
|
"hasFlatTourBooking": false,
|
||||||
|
"comparisonStatus": null,
|
||||||
|
"isSalesLeader": null,
|
||||||
|
"isFromDeveloper": true,
|
||||||
|
"isFromBuilder": true,
|
||||||
|
"isFromLeadFactory": false,
|
||||||
|
"countPromos": 3,
|
||||||
|
"snippetType": "maximum"
|
||||||
|
},
|
||||||
|
"balconiesCount": 1,
|
||||||
|
"loggiasCount": 1,
|
||||||
|
"bedroomsCount": null,
|
||||||
|
"hasFurniture": null,
|
||||||
|
"decoration": "fine",
|
||||||
|
"isByHomeowner": null,
|
||||||
|
"isPro": true,
|
||||||
|
"isApartments": false,
|
||||||
|
"isRosreestrChecked": false,
|
||||||
|
"description": "Жилой квартал 'Янтарная долина' расположен в районе Новый ВИЗ, вблизи Верх-Исетского пруда. Предлагаем вам квартиры в шестой очереди строительства — секциях 6.2-6.4 по адресу улица Крауля, 170Б. Все секции 8-этажные, в доме 147 квартир. Дом сдан. Продажа по ДКП.\nРайон\nРайон Новый ВИЗ сочетает городской комфорт и близость природных зон. Это одно из самых перспективных направлений в Екатеринбурге, идеальное для семейного проживания.\n\n5 минут пешком до остановки транспорта\n5 школ и 4 детсада поблизости\n10 минут пешком до набережной Верх-Исетского пруда\n15 минут на машине до центра города\n16 минут на машине до ТЦ 'МЕГА'\n\nДвор\nВ центре жилого квартала — зелёный двор для насыщенной жизни, игр и отдыха. Озеленение включает лиственные и хвойные деревья, декоративные кустарники и цветники.\n\nКонцепция 'двор без машин'\nЗакрытая территория с пропускной системой и без посторонних\nКруглосуточное видеонаблюдение и освещение территории в тёмное время суток\nДетские площадки для разного возраста, футбол и уличный баскетбол\n \n\nПодъезды\nПодъезд в 'Янтарной долине' — уютное и светлое пространство, в котором комфортно.\n\nДоступ в подъезды на уровне земли — без барьеров\nДомофоны в тёплых остеклённых тамбурах\nВместительный грузопассажирский лифт во всех секциях\nПомещения для колясок и велосипедов на 1 этаже\nУдобная навигация с номерами этажей и квартир\n\nПланировки\nНаш подход 'разумные метры' при проектировании квартир учитывает состав семьи, число жильцов, их потребности, а также эргономику пространства.\n\n58 уникальных планировок\nнесколько вариантов для каждого типа квартир: от студий до 3-комнатных\nобъединённые кухни-гостиные для простора и общения\nрациональное использование каждого метра\nквартиры с гардеробными и тёплыми лоджиями\n\nОтделка\nВ каждой квартире 'Янтарной долины' мы позаботились о чистовой отделке, чтобы ваш переезд прошёл быстро и без лишних хлопот.\n\nПрочный ламинат на полу в комнатах, прихожих и кухнях, плитка в санузлах, виниловые обои на флизелиновой основе на стенах, белые натяжные потолки\nМежкомнатные двери светлых тонов и сейф-дверь на входе в квартиру\nРадиаторы с терморегуляторами и горизонтальной разводкой, двухкамерные стеклопакеты с приточными клапанами вентиляции, розетки и выключатели\nВ санузлах установлены раковины и унитазы Продается 2-комнатная квартира в Екатеринбурге.",
|
||||||
|
"descriptionMinhash": [
|
||||||
|
1799783,
|
||||||
|
5781654,
|
||||||
|
15811915,
|
||||||
|
4788959,
|
||||||
|
35289122,
|
||||||
|
6143519,
|
||||||
|
18432622,
|
||||||
|
45820160,
|
||||||
|
2258400,
|
||||||
|
11955293,
|
||||||
|
25662122,
|
||||||
|
7185657,
|
||||||
|
23168773,
|
||||||
|
14391071,
|
||||||
|
12464540,
|
||||||
|
13379849,
|
||||||
|
41127868,
|
||||||
|
40846940,
|
||||||
|
36828281,
|
||||||
|
6351486,
|
||||||
|
53971654,
|
||||||
|
349072,
|
||||||
|
10292969,
|
||||||
|
2066855,
|
||||||
|
30469210,
|
||||||
|
5740363,
|
||||||
|
14611990,
|
||||||
|
794253,
|
||||||
|
929833,
|
||||||
|
501391,
|
||||||
|
122143391,
|
||||||
|
5031640
|
||||||
|
],
|
||||||
|
"photos": [
|
||||||
|
{
|
||||||
|
"fullUrl": "https://images.cdn-cian.ru/images/2950950202-1.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fullUrl": "https://images.cdn-cian.ru/images/2950950220-1.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fullUrl": "https://images.cdn-cian.ru/images/2950950228-1.jpg"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"addedTimestamp": 1789408293,
|
||||||
|
"offerType": "flat",
|
||||||
|
"category": "newBuildingFlatSale",
|
||||||
|
"fromDeveloper": true,
|
||||||
|
"buildersIds": [
|
||||||
|
10188
|
||||||
|
],
|
||||||
|
"isLayoutApproved": null,
|
||||||
|
"isByCommercialOwner": null,
|
||||||
|
"isCianPartner": false,
|
||||||
|
"descriptionWordsHighlighted": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cianId": 321628098,
|
||||||
|
"id": 321628098,
|
||||||
|
"fullUrl": "https://ekb.cian.ru/sale/flat/321628098/?context=4.ZmmZlV8JbZQ.lF2e-AgOjLa29ue-yfljyTo7TzR6qFjcVKH6jOXZzubqAE_l5Ll_VyYwlGbvrZUPDs24HvZ1DfBOXg&mlSearchSessionGuid=924c429bf7495771ff77b66074cdf292",
|
||||||
|
"bargainTerms": {
|
||||||
|
"bargainAllowed": null,
|
||||||
|
"vatType": null,
|
||||||
|
"agentFee": null,
|
||||||
|
"clientFee": null,
|
||||||
|
"paymentPeriod": null,
|
||||||
|
"leaseType": null,
|
||||||
|
"deposit": null,
|
||||||
|
"mortgageAllowed": null,
|
||||||
|
"vatPrice": null,
|
||||||
|
"utilitiesTerms": null,
|
||||||
|
"price": 7815000,
|
||||||
|
"leaseTermType": null,
|
||||||
|
"priceRur": 7815000,
|
||||||
|
"tags": [],
|
||||||
|
"priceType": "all",
|
||||||
|
"priceForWorkplace": null,
|
||||||
|
"saleType": "free",
|
||||||
|
"currency": "rur",
|
||||||
|
"agentBonus": null
|
||||||
|
},
|
||||||
|
"roomsCount": 2,
|
||||||
|
"flatType": "rooms",
|
||||||
|
"totalArea": "54.3",
|
||||||
|
"livingArea": "25.2",
|
||||||
|
"kitchenArea": "16.6",
|
||||||
|
"floorNumber": 6,
|
||||||
|
"building": {
|
||||||
|
"floorsCount": 31,
|
||||||
|
"parking": null,
|
||||||
|
"deadline": {
|
||||||
|
"quarter": "fourth",
|
||||||
|
"year": 2028,
|
||||||
|
"isComplete": false,
|
||||||
|
"quarterEnd": "2028-12-31"
|
||||||
|
},
|
||||||
|
"type": null,
|
||||||
|
"materialType": null,
|
||||||
|
"heatingType": null,
|
||||||
|
"accessType": null,
|
||||||
|
"classType": null,
|
||||||
|
"buildYear": null,
|
||||||
|
"cargoLiftsCount": null,
|
||||||
|
"passengerLiftsCount": 8
|
||||||
|
},
|
||||||
|
"cadastralNumber": null,
|
||||||
|
"buildingCadastralNumber": null,
|
||||||
|
"geo": {
|
||||||
|
"coordinates": {
|
||||||
|
"lat": 56.789383109239054,
|
||||||
|
"lng": 60.60020415337982
|
||||||
|
},
|
||||||
|
"address": [
|
||||||
|
{
|
||||||
|
"type": "location",
|
||||||
|
"geoType": "location",
|
||||||
|
"name": "Свердловская",
|
||||||
|
"fullName": "Свердловская область",
|
||||||
|
"id": 4612
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "location",
|
||||||
|
"geoType": "location",
|
||||||
|
"name": "Екатеринбург",
|
||||||
|
"fullName": "Екатеринбург",
|
||||||
|
"id": 4743
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "raion",
|
||||||
|
"geoType": "district",
|
||||||
|
"name": "Чкаловский",
|
||||||
|
"fullName": "р-н Чкаловский",
|
||||||
|
"id": 291
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "mikroraion",
|
||||||
|
"geoType": "district",
|
||||||
|
"name": "Вторчермет",
|
||||||
|
"fullName": "мкр. Вторчермет",
|
||||||
|
"id": 1509
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "metro",
|
||||||
|
"geoType": "underground",
|
||||||
|
"name": "Ботаническая",
|
||||||
|
"fullName": "м. Ботаническая",
|
||||||
|
"id": 348
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"undergrounds": [
|
||||||
|
{
|
||||||
|
"name": "Ботаническая",
|
||||||
|
"time": 6,
|
||||||
|
"transportType": "transport",
|
||||||
|
"lineColor": "00701A",
|
||||||
|
"lineId": 26,
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Чкаловская",
|
||||||
|
"time": 6,
|
||||||
|
"transportType": "transport",
|
||||||
|
"lineColor": "00701A",
|
||||||
|
"lineId": 26,
|
||||||
|
"isDefault": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Геологическая",
|
||||||
|
"time": 9,
|
||||||
|
"transportType": "transport",
|
||||||
|
"lineColor": "00701A",
|
||||||
|
"lineId": 26,
|
||||||
|
"isDefault": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"newbuilding": {
|
||||||
|
"isFromBuilder": true,
|
||||||
|
"isFichering": true,
|
||||||
|
"name": "Стадиум",
|
||||||
|
"id": 5705732,
|
||||||
|
"house": {
|
||||||
|
"section": "Секция 4",
|
||||||
|
"name": "Корпус 1",
|
||||||
|
"id": 10906188,
|
||||||
|
"isFinished": false,
|
||||||
|
"finishDate": {
|
||||||
|
"quarter": 4,
|
||||||
|
"year": 2028
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hasFlatTourBooking": false,
|
||||||
|
"isSalesLeader": null,
|
||||||
|
"comparisonStatus": null,
|
||||||
|
"isPremium": true,
|
||||||
|
"showJkReliableFlag": false,
|
||||||
|
"isFromSeller": false,
|
||||||
|
"isFromLeadFactory": false,
|
||||||
|
"isFromDeveloper": true,
|
||||||
|
"countPromos": 10,
|
||||||
|
"snippetType": "maximum"
|
||||||
|
},
|
||||||
|
"balconiesCount": null,
|
||||||
|
"loggiasCount": null,
|
||||||
|
"bedroomsCount": null,
|
||||||
|
"hasFurniture": null,
|
||||||
|
"decoration": null,
|
||||||
|
"isByHomeowner": null,
|
||||||
|
"isPro": true,
|
||||||
|
"isApartments": false,
|
||||||
|
"isRosreestrChecked": false,
|
||||||
|
"description": "ЖК \"Стадиум\" — это ваш шанс жить в одном из самых зеленых уголков Екатеринбурга, но при этом в шаговой доступности от всего важного. Комплекс строится между улицами 8 Марта, Рижским переулком, Московской и Объездной дорогой — в сердце развивающегося Чкаловского района на пересечении границ микрорайонов Ботаники, Автовокзала и Вторчермета. \n\nПредставьте: утром вы выходите в свой закрытый двор-парк с зонами для игр и спорта, а через 10 минут уже в ТЦ \"Ботаника Молл\" или деловом центре \"Астор\". Рядом — детсады, школы, поликлиники, и главное: буквально рукой подать до Парка завода РТИ, Юго-Западного лесопарка и легендарного Ботанического сада. Четыре корпуса разной этажности (от 9 до 31) спроектированы так, чтобы из квартир открывались виды на лесные массивы. \n\nЗдесь воздух по-настоящему свежий, а квартиры — это и евроформаты, и мастер-спальни с ванной комнатой, варианты с террасами и эксклюзивные планировочные решения с зенитными фонарями и панорамными окнами. Современные холлы с 4-метровыми потолками и зоной ресепшна, подземный паркинг и продуманное озеленение создают ощущение, что вы живете за городом, но со всеми плюсами мегаполиса. \n\n\"Стадиум\" — для тех, кто хочет просыпаться под пение птиц, но не готов отказываться от ритма большого города. Это баланс, который так ценят екатеринбуржцы.\" \n\nПреимущества: \n\nВидовые квартиры с террасами \n\nПодземный двухуровневый паркинг \n\nЭксклюзивные варианты с зенитными фонарями \n\nПанорамное остекление \n\nКрышная газовая котельная \n\nПодготовка под установку бризеров \n\nВытяжная вентиляция с механическим побуждением \n\nЧистая питьевая вода в каждой квартире \n\nЛобби с зоной ресепшн и хранением посылок \n\nРаздельные велосипедные и колясочные \n\nСобственная сервисная компания \n\nДизайнерская архитектура фасадов \n\nКонцепция спорта и здорового образа жизни \n\nМесто покоя и природы среди шума города\nЕкатеринбург, 8 Марта , 01 кв.324",
|
||||||
|
"descriptionMinhash": [
|
||||||
|
41920473,
|
||||||
|
15036167,
|
||||||
|
44672376,
|
||||||
|
14416152,
|
||||||
|
2088757,
|
||||||
|
6143519,
|
||||||
|
11414134,
|
||||||
|
2885405,
|
||||||
|
2746117,
|
||||||
|
42658346,
|
||||||
|
10643968,
|
||||||
|
39685766,
|
||||||
|
19735224,
|
||||||
|
5057571,
|
||||||
|
13742308,
|
||||||
|
95802641,
|
||||||
|
4256809,
|
||||||
|
38329502,
|
||||||
|
105651759,
|
||||||
|
59650532,
|
||||||
|
8686384,
|
||||||
|
35024833,
|
||||||
|
4368848,
|
||||||
|
38907129,
|
||||||
|
9460550,
|
||||||
|
6586538,
|
||||||
|
9615691,
|
||||||
|
3940137,
|
||||||
|
1195648,
|
||||||
|
10860617,
|
||||||
|
8412860,
|
||||||
|
37661809
|
||||||
|
],
|
||||||
|
"photos": [
|
||||||
|
{
|
||||||
|
"fullUrl": "https://images.cdn-cian.ru/images/2622692186-1.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fullUrl": "https://images.cdn-cian.ru/images/2626766693-1.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fullUrl": "https://images.cdn-cian.ru/images/2626766766-1.jpg"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"addedTimestamp": 1789634608,
|
||||||
|
"offerType": "flat",
|
||||||
|
"category": "newBuildingFlatSale",
|
||||||
|
"fromDeveloper": true,
|
||||||
|
"buildersIds": [
|
||||||
|
8624
|
||||||
|
],
|
||||||
|
"isLayoutApproved": null,
|
||||||
|
"isByCommercialOwner": null,
|
||||||
|
"isCianPartner": false,
|
||||||
|
"descriptionWordsHighlighted": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"priority": 10,
|
||||||
|
"filter": {}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
||||||
120
tradein-mvp/backend/tests/fixtures/yandex_gate_ekb_novostroyki_trimmed.json
vendored
Normal file
120
tradein-mvp/backend/tests/fixtures/yandex_gate_ekb_novostroyki_trimmed.json
vendored
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
{
|
||||||
|
"_comment": "#2422: живой ответ gate-API Яндекс Недвижимости, снят 2026-09-17 (curl_cffi impersonate=chrome, HTTP 200): rgid=559132 type=SELL category=APARTMENT newFlat=YES page=1. Урезано: 1 из 23 entities, у entity только читаемые _entity_to_lot ключи, author без agentName (PII), mainImages до 6. Значения полей не менялись.",
|
||||||
|
"response": {
|
||||||
|
"search": {
|
||||||
|
"offers": {
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"offerId": "6216493807134609867",
|
||||||
|
"url": "//realty.yandex.ru/offer/6216493807134609867",
|
||||||
|
"price": {
|
||||||
|
"currency": "RUR",
|
||||||
|
"value": 27620850,
|
||||||
|
"period": "WHOLE_LIFE",
|
||||||
|
"unit": "WHOLE_OFFER",
|
||||||
|
"trend": "UNCHANGED",
|
||||||
|
"hasPriceHistory": false,
|
||||||
|
"valuePerPart": 366859,
|
||||||
|
"unitPerPart": "SQUARE_METER",
|
||||||
|
"valueForWhole": 27620850,
|
||||||
|
"unitForWhole": "WHOLE_OFFER",
|
||||||
|
"price": {
|
||||||
|
"value": 27620850,
|
||||||
|
"currency": "RUB",
|
||||||
|
"priceType": "PER_OFFER",
|
||||||
|
"pricingPeriod": "WHOLE_LIFE"
|
||||||
|
},
|
||||||
|
"pricePerPart": {
|
||||||
|
"value": 366859,
|
||||||
|
"currency": "RUB",
|
||||||
|
"priceType": "PER_METER",
|
||||||
|
"pricingPeriod": "WHOLE_LIFE"
|
||||||
|
},
|
||||||
|
"priceForWhole": {
|
||||||
|
"value": 27620850,
|
||||||
|
"currency": "RUB",
|
||||||
|
"priceType": "PER_OFFER",
|
||||||
|
"pricingPeriod": "WHOLE_LIFE"
|
||||||
|
},
|
||||||
|
"minMonthlyMortgagePayment": 282584,
|
||||||
|
"mortgageInfo": {
|
||||||
|
"bestMortgage": {
|
||||||
|
"id": "2974521",
|
||||||
|
"payment": "282584"
|
||||||
|
},
|
||||||
|
"minPreferentialMortgageRate": 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"area": {
|
||||||
|
"value": 75.29,
|
||||||
|
"unit": "SQUARE_METER"
|
||||||
|
},
|
||||||
|
"livingSpace": {
|
||||||
|
"value": 29.03,
|
||||||
|
"unit": "SQUARE_METER"
|
||||||
|
},
|
||||||
|
"roomsTotal": 2,
|
||||||
|
"floorsOffered": [
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"floorsTotal": 16,
|
||||||
|
"building": {
|
||||||
|
"builtYear": 2026,
|
||||||
|
"siteId": 2006795,
|
||||||
|
"siteName": "Александровский сад"
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"point": {
|
||||||
|
"latitude": 56.821068,
|
||||||
|
"longitude": 60.609924,
|
||||||
|
"precision": "EXACT"
|
||||||
|
},
|
||||||
|
"geocoderAddress": "Россия, Свердловская область, Екатеринбург, жилой район Центральный, ЖК Александровский Сад",
|
||||||
|
"streetAddress": "Свердловская область, Екатеринбург, Декабристов",
|
||||||
|
"metro": {
|
||||||
|
"metroGeoId": 101986,
|
||||||
|
"metroCityRgid": 559132,
|
||||||
|
"name": "Геологическая",
|
||||||
|
"metroTransport": "ON_FOOT",
|
||||||
|
"timeToMetro": 9,
|
||||||
|
"latitude": 56.827534,
|
||||||
|
"longitude": 60.602486,
|
||||||
|
"minTimeToMetro": 8,
|
||||||
|
"lineColors": [
|
||||||
|
"f03d2f"
|
||||||
|
],
|
||||||
|
"rgbColor": "f03d2f"
|
||||||
|
},
|
||||||
|
"metroList": [
|
||||||
|
{
|
||||||
|
"name": "Геологическая",
|
||||||
|
"timeToMetro": 9
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"creationDate": "2026-03-17T11:04:44Z",
|
||||||
|
"description": "Александровский сад настоящий бизнес-класс в центре Екатеринбурга от девелопера Forum. Забудьте о суете города. Ваш двор это пейзажный сад, где царят умиротворение и гармония. Прогулочные дорожки с мягкой вечерней подсветкой проведут по уединенным",
|
||||||
|
"author": {
|
||||||
|
"category": "DEVELOPER"
|
||||||
|
},
|
||||||
|
"mainImages": [
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/20177950/9476e26d-8cbc-4b69-a7bd-03fefa0a960a/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/16258130/d185b4dc-8386-4fa1-bdf9-0865da1f8e5d/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/13970442/da0f5415-d014-466b-b5e9-0fe70d5e8680/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/14824781/f882caeb-4d40-4775-9f0a-acb01177ff0e/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/20657783/1359e480-6c21-4c07-b1de-9e36149f83fd/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/14671802/38d6dc24-8366-4460-9e99-06a1605e1919/main"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pager": {
|
||||||
|
"page": 0,
|
||||||
|
"pageSize": 20,
|
||||||
|
"sitesPageSize": 20,
|
||||||
|
"totalItems": 32234,
|
||||||
|
"totalPages": 25
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
355
tradein-mvp/backend/tests/fixtures/yandex_gate_ekb_vtorichka_trimmed.json
vendored
Normal file
355
tradein-mvp/backend/tests/fixtures/yandex_gate_ekb_vtorichka_trimmed.json
vendored
Normal file
|
|
@ -0,0 +1,355 @@
|
||||||
|
{
|
||||||
|
"_comment": "#2422: живой ответ gate-API Яндекс Недвижимости, снят 2026-09-17 (curl_cffi impersonate=chrome, HTTP 200): rgid=559132 type=SELL category=APARTMENT newFlat=NO page=1. Урезано: 3 из 23 entities, у entity только читаемые _entity_to_lot ключи, author без agentName (PII), mainImages до 6. Значения полей не менялись.",
|
||||||
|
"response": {
|
||||||
|
"search": {
|
||||||
|
"offers": {
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"offerId": "5228381943217465492",
|
||||||
|
"url": "https://novostroi-ekb.ru/catalog/sale/vtorichka/object/1064",
|
||||||
|
"price": {
|
||||||
|
"currency": "RUR",
|
||||||
|
"value": 4400000,
|
||||||
|
"period": "WHOLE_LIFE",
|
||||||
|
"unit": "WHOLE_OFFER",
|
||||||
|
"trend": "DECREASED",
|
||||||
|
"previous": 4450000,
|
||||||
|
"hasPriceHistory": true,
|
||||||
|
"valuePerPart": 129412,
|
||||||
|
"unitPerPart": "SQUARE_METER",
|
||||||
|
"valueForWhole": 4400000,
|
||||||
|
"unitForWhole": "WHOLE_OFFER",
|
||||||
|
"price": {
|
||||||
|
"value": 4400000,
|
||||||
|
"currency": "RUB",
|
||||||
|
"priceType": "PER_OFFER",
|
||||||
|
"pricingPeriod": "WHOLE_LIFE"
|
||||||
|
},
|
||||||
|
"pricePerPart": {
|
||||||
|
"value": 129412,
|
||||||
|
"currency": "RUB",
|
||||||
|
"priceType": "PER_METER",
|
||||||
|
"pricingPeriod": "WHOLE_LIFE"
|
||||||
|
},
|
||||||
|
"priceForWhole": {
|
||||||
|
"value": 4400000,
|
||||||
|
"currency": "RUB",
|
||||||
|
"priceType": "PER_OFFER",
|
||||||
|
"pricingPeriod": "WHOLE_LIFE"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"area": {
|
||||||
|
"value": 34,
|
||||||
|
"unit": "SQUARE_METER"
|
||||||
|
},
|
||||||
|
"kitchenSpace": {
|
||||||
|
"value": 7,
|
||||||
|
"unit": "SQUARE_METER"
|
||||||
|
},
|
||||||
|
"roomsTotal": 1,
|
||||||
|
"floorsOffered": [
|
||||||
|
8
|
||||||
|
],
|
||||||
|
"floorsTotal": 9,
|
||||||
|
"ceilingHeight": 2.5,
|
||||||
|
"building": {
|
||||||
|
"builtYear": 1978,
|
||||||
|
"buildingType": "BRICK"
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"point": {
|
||||||
|
"latitude": 56.903275,
|
||||||
|
"longitude": 60.6229,
|
||||||
|
"precision": "EXACT"
|
||||||
|
},
|
||||||
|
"geocoderAddress": "Россия, Свердловская область, Екатеринбург, Шефская улица, 85",
|
||||||
|
"streetAddress": "Шефская улица, 85",
|
||||||
|
"metro": {
|
||||||
|
"metroGeoId": 101947,
|
||||||
|
"metroCityRgid": 559132,
|
||||||
|
"name": "Проспект Космонавтов",
|
||||||
|
"metroTransport": "ON_FOOT",
|
||||||
|
"timeToMetro": 7,
|
||||||
|
"latitude": 56.901844,
|
||||||
|
"longitude": 60.61394,
|
||||||
|
"minTimeToMetro": 5,
|
||||||
|
"lineColors": [
|
||||||
|
"f03d2f"
|
||||||
|
],
|
||||||
|
"rgbColor": "f03d2f"
|
||||||
|
},
|
||||||
|
"metroList": [
|
||||||
|
{
|
||||||
|
"name": "Проспект Космонавтов",
|
||||||
|
"timeToMetro": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Машиностроителей",
|
||||||
|
"timeToMetro": 14
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"creationDate": "2026-08-19T06:23:51Z",
|
||||||
|
"description": "1 комнатная квартира 34 кв .м с развитой инфраструктурой , станция метро «КОСМАНАВТОВ» в шаговой доступности . Фукциональная планировка правильной формы, дополнительное место хранения гардеробная , в квартире сделана качественная предчистовая отделка",
|
||||||
|
"author": {
|
||||||
|
"category": "AGENCY",
|
||||||
|
"organization": "САМОЛЕТ ПЛЮС"
|
||||||
|
},
|
||||||
|
"predictions": {
|
||||||
|
"predictedPrice": {
|
||||||
|
"min": "3795000",
|
||||||
|
"max": "4638000",
|
||||||
|
"value": "4217000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mainImages": [
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/14333116/89f721ff-ad4b-49f1-8cec-432ad11baeab/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/13853239/caf4740f-dca8-47a3-8005-56968d20a3b1/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/14244677/f1943334-731e-4539-98f6-9d38d4a725ce/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/12726755/346626db-ba69-4a49-8940-76f08d6aa924/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/20074534/021cc849-6554-4059-9423-19193e3006b9/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/13912669/b240dbf0-1adc-4dbd-9ce8-c0ca6c478fc8/main"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offerId": "6282460993454547968",
|
||||||
|
"url": "//realty.yandex.ru/offer/6282460993454547968",
|
||||||
|
"price": {
|
||||||
|
"currency": "RUR",
|
||||||
|
"value": 10290000,
|
||||||
|
"period": "WHOLE_LIFE",
|
||||||
|
"unit": "WHOLE_OFFER",
|
||||||
|
"trend": "UNCHANGED",
|
||||||
|
"hasPriceHistory": false,
|
||||||
|
"valuePerPart": 294000,
|
||||||
|
"unitPerPart": "SQUARE_METER",
|
||||||
|
"valueForWhole": 10290000,
|
||||||
|
"unitForWhole": "WHOLE_OFFER",
|
||||||
|
"price": {
|
||||||
|
"value": 10290000,
|
||||||
|
"currency": "RUB",
|
||||||
|
"priceType": "PER_OFFER",
|
||||||
|
"pricingPeriod": "WHOLE_LIFE"
|
||||||
|
},
|
||||||
|
"pricePerPart": {
|
||||||
|
"value": 294000,
|
||||||
|
"currency": "RUB",
|
||||||
|
"priceType": "PER_METER",
|
||||||
|
"pricingPeriod": "WHOLE_LIFE"
|
||||||
|
},
|
||||||
|
"priceForWhole": {
|
||||||
|
"value": 10290000,
|
||||||
|
"currency": "RUB",
|
||||||
|
"priceType": "PER_OFFER",
|
||||||
|
"pricingPeriod": "WHOLE_LIFE"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"area": {
|
||||||
|
"value": 35,
|
||||||
|
"unit": "SQUARE_METER"
|
||||||
|
},
|
||||||
|
"livingSpace": {
|
||||||
|
"value": 11,
|
||||||
|
"unit": "SQUARE_METER"
|
||||||
|
},
|
||||||
|
"kitchenSpace": {
|
||||||
|
"value": 14,
|
||||||
|
"unit": "SQUARE_METER"
|
||||||
|
},
|
||||||
|
"roomsTotal": 1,
|
||||||
|
"floorsOffered": [
|
||||||
|
27
|
||||||
|
],
|
||||||
|
"floorsTotal": 27,
|
||||||
|
"ceilingHeight": 2.75,
|
||||||
|
"building": {
|
||||||
|
"builtYear": 2023,
|
||||||
|
"buildingType": "MONOLIT",
|
||||||
|
"siteId": 1668651,
|
||||||
|
"siteName": "Парковый квартал"
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"point": {
|
||||||
|
"latitude": 56.815243,
|
||||||
|
"longitude": 60.62593,
|
||||||
|
"precision": "EXACT"
|
||||||
|
},
|
||||||
|
"geocoderAddress": "Россия, Свердловская область, Екатеринбург, Машинная улица, 4",
|
||||||
|
"streetAddress": "Машинная улица, 4",
|
||||||
|
"metro": {
|
||||||
|
"metroGeoId": 116399,
|
||||||
|
"metroCityRgid": 559132,
|
||||||
|
"name": "Чкаловская",
|
||||||
|
"metroTransport": "ON_FOOT",
|
||||||
|
"timeToMetro": 17,
|
||||||
|
"latitude": 56.807995,
|
||||||
|
"longitude": 60.610184,
|
||||||
|
"minTimeToMetro": 12,
|
||||||
|
"lineColors": [
|
||||||
|
"f03d2f"
|
||||||
|
],
|
||||||
|
"rgbColor": "f03d2f"
|
||||||
|
},
|
||||||
|
"metroList": [
|
||||||
|
{
|
||||||
|
"name": "Чкаловская",
|
||||||
|
"timeToMetro": 17
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ботаническая",
|
||||||
|
"timeToMetro": 13
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Площадь 1905 Года",
|
||||||
|
"timeToMetro": 16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Геологическая",
|
||||||
|
"timeToMetro": 20
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"creationDate": "2026-08-02T14:04:19Z",
|
||||||
|
"description": "Продам квартиру в 10 минутах от центра города. Рядом Парк Маяковского. Хорошая транспортная доступность: до метро можно дойти пешком. Великолепный вид из окна.Хороший обзор. Высокие потолки, 2,75.Нет соседей сверху. Качественный",
|
||||||
|
"author": {
|
||||||
|
"category": "OWNER"
|
||||||
|
},
|
||||||
|
"predictions": {
|
||||||
|
"predictedPrice": {
|
||||||
|
"min": "8741000",
|
||||||
|
"max": "10683000",
|
||||||
|
"value": "9712000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mainImages": [
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/10211679/add.69def35c26379a08babb742069d310dc.realty-api-vos/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/14373170/add.e2e2b76847d9b69e3abe0c64efee75c4.realty-api-vos/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/14717586/add.c65fd15bb15736448bac2a597ffd0bae.realty-api-vos/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/11512705/add.b894c4e448f696251deaed148ee9c30e.realty-api-vos/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/13847384/add.f13072669ebf54647b1682fc70fa9e99.realty-api-vos/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/14527622/add.1708ed4ada10c2d407f64b0e744d8047.realty-api-vos/main"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offerId": "8530722463088927619",
|
||||||
|
"url": "//realty.yandex.ru/offer/8530722463088927619",
|
||||||
|
"price": {
|
||||||
|
"currency": "RUR",
|
||||||
|
"value": 5600000,
|
||||||
|
"period": "WHOLE_LIFE",
|
||||||
|
"unit": "WHOLE_OFFER",
|
||||||
|
"trend": "UNCHANGED",
|
||||||
|
"hasPriceHistory": false,
|
||||||
|
"valuePerPart": 269231,
|
||||||
|
"unitPerPart": "SQUARE_METER",
|
||||||
|
"valueForWhole": 5600000,
|
||||||
|
"unitForWhole": "WHOLE_OFFER",
|
||||||
|
"price": {
|
||||||
|
"value": 5600000,
|
||||||
|
"currency": "RUB",
|
||||||
|
"priceType": "PER_OFFER",
|
||||||
|
"pricingPeriod": "WHOLE_LIFE"
|
||||||
|
},
|
||||||
|
"pricePerPart": {
|
||||||
|
"value": 269231,
|
||||||
|
"currency": "RUB",
|
||||||
|
"priceType": "PER_METER",
|
||||||
|
"pricingPeriod": "WHOLE_LIFE"
|
||||||
|
},
|
||||||
|
"priceForWhole": {
|
||||||
|
"value": 5600000,
|
||||||
|
"currency": "RUB",
|
||||||
|
"priceType": "PER_OFFER",
|
||||||
|
"pricingPeriod": "WHOLE_LIFE"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"area": {
|
||||||
|
"value": 20.8,
|
||||||
|
"unit": "SQUARE_METER"
|
||||||
|
},
|
||||||
|
"livingSpace": {
|
||||||
|
"value": 12,
|
||||||
|
"unit": "SQUARE_METER"
|
||||||
|
},
|
||||||
|
"floorsOffered": [
|
||||||
|
8
|
||||||
|
],
|
||||||
|
"floorsTotal": 11,
|
||||||
|
"ceilingHeight": 2.7,
|
||||||
|
"building": {
|
||||||
|
"builtYear": 2021,
|
||||||
|
"buildingType": "MONOLIT_BRICK",
|
||||||
|
"siteId": 1948687,
|
||||||
|
"siteName": "Северный квартал"
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"point": {
|
||||||
|
"latitude": 56.89804,
|
||||||
|
"longitude": 60.6199,
|
||||||
|
"precision": "EXACT"
|
||||||
|
},
|
||||||
|
"geocoderAddress": "Россия, Свердловская область, Екатеринбург, переулок Ритслянда, 15",
|
||||||
|
"streetAddress": "переулок Ритслянда, 15",
|
||||||
|
"metro": {
|
||||||
|
"metroGeoId": 101947,
|
||||||
|
"metroCityRgid": 559132,
|
||||||
|
"name": "Проспект Космонавтов",
|
||||||
|
"metroTransport": "ON_FOOT",
|
||||||
|
"timeToMetro": 5,
|
||||||
|
"latitude": 56.901844,
|
||||||
|
"longitude": 60.61394,
|
||||||
|
"minTimeToMetro": 5,
|
||||||
|
"lineColors": [
|
||||||
|
"f03d2f"
|
||||||
|
],
|
||||||
|
"rgbColor": "f03d2f"
|
||||||
|
},
|
||||||
|
"metroList": [
|
||||||
|
{
|
||||||
|
"name": "Проспект Космонавтов",
|
||||||
|
"timeToMetro": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Уралмаш",
|
||||||
|
"timeToMetro": 13
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Машиностроителей",
|
||||||
|
"timeToMetro": 12
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"creationDate": "2026-09-15T06:17:51Z",
|
||||||
|
"description": "Продается прекрасная студия в ЖК Северные кварталы, застройщик Брусника. Дом комфорт класса Площадь студии 20,8 плюс теплая лоджия 4кв.м (убрана перегородка) -благодаря этому площадь студии увеличена до 24,8кв.м - компактно и функционально для одного",
|
||||||
|
"author": {
|
||||||
|
"category": "AGENCY",
|
||||||
|
"organization": "DOMOS CLUB"
|
||||||
|
},
|
||||||
|
"predictions": {
|
||||||
|
"predictedPrice": {
|
||||||
|
"min": "4562000",
|
||||||
|
"max": "5576000",
|
||||||
|
"value": "5069000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mainImages": [
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/14727395/1635cddb-a57c-4cce-a6c1-c70b9aef13cd/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/14621926/3ae41eaf-5b30-46ec-b844-b40af2bb697a/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/12719313/6921877e-51f6-4d02-93ef-0395b99776bb/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/13297592/8a8d583b-d205-460e-aec8-c9cb827eae73/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/10246351/8eee4902-aa24-42dc-aaa2-9259c82146d8/main",
|
||||||
|
"//avatars.mds.yandex.net/get-realty-offers/14621926/116dc1df-3288-4236-acfe-2f660fb2ac8b/main"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pager": {
|
||||||
|
"page": 0,
|
||||||
|
"pageSize": 20,
|
||||||
|
"sitesPageSize": 20,
|
||||||
|
"totalItems": 4077,
|
||||||
|
"totalPages": 25
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
"""scraper_kit не импортирует app.* (#2422 п.2).
|
||||||
|
|
||||||
|
Инвариант держал test_kit_avito_has_no_app_imports, удалённый вместе с golden-parity
|
||||||
|
(#2419). Проверка обходит весь пакет, а не только providers: импорт app внутри kit —
|
||||||
|
цикл зависимостей, где бы он ни стоял. Смотрит AST, поэтому находит и ленивый импорт
|
||||||
|
внутри функции, и не срабатывает на слово «app» в комментарии.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import ast
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import scraper_kit
|
||||||
|
|
||||||
|
# conftest.py (autouse) тянет app.core.config, которому нужен DATABASE_URL; БД не нужна.
|
||||||
|
os.environ.setdefault("DATABASE_URL", "postgresql+psycopg://test:test@localhost:5432/test")
|
||||||
|
|
||||||
|
KIT_ROOT = Path(scraper_kit.__file__).parent
|
||||||
|
|
||||||
|
|
||||||
|
def _app_imports(path: Path) -> list[str]:
|
||||||
|
found: list[str] = []
|
||||||
|
for node in ast.walk(ast.parse(path.read_text(encoding="utf-8"), filename=str(path))):
|
||||||
|
if isinstance(node, ast.Import):
|
||||||
|
names = [alias.name for alias in node.names]
|
||||||
|
elif isinstance(node, ast.ImportFrom) and node.level == 0:
|
||||||
|
names = [node.module or ""]
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
found += [f"{n} (строка {node.lineno})" for n in names if n.split(".")[0] == "app"]
|
||||||
|
return found
|
||||||
|
|
||||||
|
|
||||||
|
def test_kit_has_no_app_imports() -> None:
|
||||||
|
files = sorted(KIT_ROOT.rglob("*.py"))
|
||||||
|
# Обход не пустой и дошёл до провайдеров — иначе тест зелёный по построению.
|
||||||
|
assert KIT_ROOT / "providers" / "avito" / "houses.py" in files
|
||||||
|
assert len(files) > 40
|
||||||
|
|
||||||
|
offenders = {
|
||||||
|
str(p.relative_to(KIT_ROOT)): imports for p in files if (imports := _app_imports(p))
|
||||||
|
}
|
||||||
|
assert offenders == {}
|
||||||
|
|
@ -0,0 +1,401 @@
|
||||||
|
"""Разбор kit-парсеров на сохранённых страницах площадок: фикстура → лот (#2422, #2408).
|
||||||
|
|
||||||
|
Golden-parity тесты сверяли kit с legacy-копией и ушли вместе с ней (#2419). После
|
||||||
|
этого разбор avito.houses, cian.serp и yandex.serp не проверял никто: правка
|
||||||
|
извлечения поля в kit проходила бы зелёной. Здесь ожидания записаны прямо значениями
|
||||||
|
из сохранённых страниц, без второй реализации в роли эталона.
|
||||||
|
|
||||||
|
Фикстуры:
|
||||||
|
- avito_house_572538.html, avito_houses_sample.html — карточки домов Авито
|
||||||
|
(вторичка), рейтинг только в reviews.filterEntries (#1789);
|
||||||
|
- avito_novostroyka_12879380.html — карточка ЖК (developmentPage);
|
||||||
|
- avito_serp_sample.html — выдача Авито, собранная из живой страницы (#726);
|
||||||
|
- cian_serp_ekb_2room_trimmed.html, yandex_gate_ekb_*_trimmed.json — живые выдачи
|
||||||
|
2026-09-17, урезанные до читаемых парсером полей (что и как урезано — в шапке
|
||||||
|
каждого файла; разбор урезанной и полной выдачи совпал поле в поле, кроме числа
|
||||||
|
фото).
|
||||||
|
|
||||||
|
Не покрыто здесь, потому что уже покрыто на фикстурах в своих файлах: avito.detail
|
||||||
|
(test_avito_detail_fields_3047.py), cian.detail (test_cian_views_parse.py,
|
||||||
|
test_cian_bti_house_persist.py), domclick (test_domclick_sweep.py,
|
||||||
|
scrapers/test_domclick_detail.py), base (scrapers/test_base_clamp_date.py).
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from datetime import date
|
||||||
|
from pathlib import Path
|
||||||
|
from types import SimpleNamespace
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
# conftest.py (autouse) тянет app.core.config, которому нужен DATABASE_URL; БД не нужна.
|
||||||
|
os.environ.setdefault("DATABASE_URL", "postgresql+psycopg://test:test@localhost:5432/test")
|
||||||
|
|
||||||
|
from scraper_kit.providers.avito.houses import (
|
||||||
|
HouseCatalogEnrichment,
|
||||||
|
_extract_preloaded_state,
|
||||||
|
parse_houses_state,
|
||||||
|
)
|
||||||
|
from scraper_kit.providers.avito.serp import AvitoScraper
|
||||||
|
from scraper_kit.providers.cian.serp import CianScraper
|
||||||
|
from scraper_kit.providers.yandex.serp import _extract_gate_data, _parse_gate_json
|
||||||
|
|
||||||
|
FIXTURES = Path(__file__).parent.parent / "fixtures"
|
||||||
|
|
||||||
|
|
||||||
|
def _read(name: str) -> str:
|
||||||
|
return (FIXTURES / name).read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
# ── avito.houses: карточка дома (вторичка) ─────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
def _house(name: str, url: str) -> HouseCatalogEnrichment:
|
||||||
|
state = _extract_preloaded_state(_read(name))
|
||||||
|
assert state is not None, name
|
||||||
|
return parse_houses_state(state, url)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def house_572538() -> HouseCatalogEnrichment:
|
||||||
|
return _house("avito_house_572538.html", "https://www.avito.ru/catalog/houses/572538")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def house_115188() -> HouseCatalogEnrichment:
|
||||||
|
return _house("avito_houses_sample.html", "https://www.avito.ru/catalog/houses/115188")
|
||||||
|
|
||||||
|
|
||||||
|
def test_avito_house_characteristics(house_572538: HouseCatalogEnrichment) -> None:
|
||||||
|
h = house_572538.house
|
||||||
|
assert h.ext_id == 572538
|
||||||
|
assert h.ext_id_hash == "MTE3LjQ1Nzk0Mg"
|
||||||
|
assert h.full_address == "Свердловская область, Екатеринбург, ул. Сони Морозовой, 190"
|
||||||
|
assert (h.lat, h.lon) == (56.832359, 60.625583)
|
||||||
|
assert h.year_built == 1994
|
||||||
|
assert h.total_floors == 10
|
||||||
|
assert h.house_type == "brick"
|
||||||
|
assert h.material_floors == "Железобетонные"
|
||||||
|
assert h.hot_water == "Центральное"
|
||||||
|
assert h.passenger_elevators == 1
|
||||||
|
assert h.cargo_elevators is None # параметра нет на странице — не 0
|
||||||
|
assert h.has_concierge is True
|
||||||
|
assert h.has_playground is True
|
||||||
|
assert h.closed_yard is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_avito_house_rating_from_reviews_filter_entries_1789(
|
||||||
|
house_572538: HouseCatalogEnrichment, house_115188: HouseCatalogEnrichment
|
||||||
|
) -> None:
|
||||||
|
"""В обеих карточках housePage отдаёт бейдж без оценки (scoreString «—»), оценка
|
||||||
|
есть только в reviews.filterEntries[type=score]. Без запасного пути #1789
|
||||||
|
рейтинг и число отзывов были бы None."""
|
||||||
|
h = house_572538.house
|
||||||
|
assert h.rating_score == pytest.approx(14 / 3)
|
||||||
|
assert h.rating_string == "4,7"
|
||||||
|
assert h.reviews_count == 3
|
||||||
|
assert [(r["score"], r["count"]) for r in h.rating_distribution] == [
|
||||||
|
(5, 2),
|
||||||
|
(4, 1),
|
||||||
|
(3, 0),
|
||||||
|
(2, 0),
|
||||||
|
(1, 0),
|
||||||
|
]
|
||||||
|
|
||||||
|
h2 = house_115188.house
|
||||||
|
assert (h2.rating_score, h2.rating_string, h2.reviews_count) == (4.0, "4,0", 4)
|
||||||
|
|
||||||
|
|
||||||
|
def test_avito_house_reviews(house_572538: HouseCatalogEnrichment) -> None:
|
||||||
|
reviews = {r.ext_review_id: r for r in house_572538.reviews}
|
||||||
|
assert list(reviews) == [2360701, 2018777, 1757422]
|
||||||
|
|
||||||
|
full = reviews[2018777]
|
||||||
|
assert full.author_name == "Иван"
|
||||||
|
assert full.score == 5
|
||||||
|
assert full.rated_date == date(2025, 9, 14)
|
||||||
|
assert full.text_main is not None and full.text_main.startswith("Желательно добавить")
|
||||||
|
assert full.text_pros is not None and full.text_pros.startswith("Удобное расположение")
|
||||||
|
assert full.text_cons is not None and full.text_cons.startswith("Возможно, проблемы")
|
||||||
|
|
||||||
|
# Секции без заголовка нет — основной текст пуст, плюсы/минусы на месте.
|
||||||
|
no_main = reviews[1757422]
|
||||||
|
assert no_main.rated_date == date(2025, 7, 9)
|
||||||
|
assert no_main.text_main is None
|
||||||
|
assert no_main.text_pros is not None and no_main.text_pros.startswith("Двор закрытый")
|
||||||
|
|
||||||
|
# Отзыв 2360701 датирован «16 апреля» без года — такую дату разбор сейчас не
|
||||||
|
# читает (rated_date=None). Это дефект, а не контракт, поэтому здесь не закреплён.
|
||||||
|
|
||||||
|
|
||||||
|
def test_avito_house_reviews_next_page(
|
||||||
|
house_572538: HouseCatalogEnrichment, house_115188: HouseCatalogEnrichment
|
||||||
|
) -> None:
|
||||||
|
assert house_572538.reviews_next_page_url is None # запись pages без nextPageUrl
|
||||||
|
assert house_115188.reviews_next_page_url == (
|
||||||
|
"/web/3/rating/model?categoryId=24&catalogId=283&paths[]=115188&limit=10&cursor=3"
|
||||||
|
"&sortBy[]=modelTypeId&sortBy[]=publishedAt&modelTypeId=14&developmentId=115188"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_avito_house_placement_history(house_572538: HouseCatalogEnrichment) -> None:
|
||||||
|
history = house_572538.placement_history
|
||||||
|
assert len(history) == 8
|
||||||
|
first = history[0]
|
||||||
|
assert first.ext_item_id == "2304054124"
|
||||||
|
assert first.title == "3-к. квартира, 108\xa0м², 5/10\xa0эт."
|
||||||
|
assert (first.start_price, first.last_price) == (11_000_000, 14_000_000)
|
||||||
|
assert first.start_price_date == date(2022, 1, 8)
|
||||||
|
assert first.last_price_date == date(2026, 1, 17)
|
||||||
|
assert first.exposure_days == 677
|
||||||
|
assert first.removed_date is None # виджет даты снятия не отдаёт
|
||||||
|
assert first.raw_payload is not None and "itemImage" not in first.raw_payload
|
||||||
|
|
||||||
|
|
||||||
|
def test_avito_house_mini_serp_and_seller(house_572538: HouseCatalogEnrichment) -> None:
|
||||||
|
# Цена в виджете — строка «21 700 000 ₽» с неразрывными пробелами.
|
||||||
|
assert [(m.ext_item_id, m.price_rub) for m in house_572538.mini_serp] == [
|
||||||
|
(8007602481, 21_700_000),
|
||||||
|
(8029678809, 21_600_000),
|
||||||
|
]
|
||||||
|
first = house_572538.mini_serp[0]
|
||||||
|
assert first.metro_text == "Геологическая, 1,5 км"
|
||||||
|
assert first.metro_color == "#0A6F20"
|
||||||
|
assert first.seller is not None
|
||||||
|
assert first.seller.ext_seller_id == "i251003466"
|
||||||
|
assert first.seller.name == "Самолет Плюс Центральный"
|
||||||
|
assert first.seller.seller_type == "Компания"
|
||||||
|
|
||||||
|
|
||||||
|
def test_avito_house_recommendations(house_115188: HouseCatalogEnrichment) -> None:
|
||||||
|
recs = house_115188.recommendations
|
||||||
|
assert len(recs) == 14
|
||||||
|
assert recs[0].title == "1-к. квартира, 30,3\xa0м², 3/5\xa0эт."
|
||||||
|
assert recs[0].price_text == "4\xa0000\xa0000 ₽"
|
||||||
|
assert recs[0].address == "Свердловская область, Екатеринбург, улица 40-летия Октября, 32А"
|
||||||
|
assert recs[0].image_url is not None and recs[0].image_url.startswith(
|
||||||
|
"https://50.img.avito.st/"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ── avito.houses: карточка ЖК (developmentPage) ────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
def test_avito_novostroyka_development_page() -> None:
|
||||||
|
e = _house(
|
||||||
|
"avito_novostroyka_12879380.html",
|
||||||
|
"https://www.avito.ru/catalog/novostroyki/ekaterinburg/semeynyy_kvartal_beregovoy/12879380",
|
||||||
|
)
|
||||||
|
h = e.house
|
||||||
|
assert h.ext_id == 12879380
|
||||||
|
assert h.ext_id_hash == "MGDKHN70PQ"
|
||||||
|
assert h.title == "Семейный квартал «Береговой»"
|
||||||
|
assert h.short_address == "ул. Щербакова, жилые дома"
|
||||||
|
assert h.full_address is None # на странице пустая строка
|
||||||
|
assert (h.lat, h.lon) == (56.77005, 60.67244)
|
||||||
|
assert h.house_type == "monolith"
|
||||||
|
assert h.house_class == "comfort"
|
||||||
|
assert (h.passenger_elevators, h.cargo_elevators) == (42, 60)
|
||||||
|
assert (h.developer_name, h.developer_key) == ("Талан", "6749804656-3468412387")
|
||||||
|
assert h.year_built is None # дом строится: «Срок сдачи», а не год постройки
|
||||||
|
assert h.rating_score is None
|
||||||
|
assert e.reviews == [] and e.placement_history == []
|
||||||
|
|
||||||
|
|
||||||
|
# ── avito.serp ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
def test_avito_serp_cards_to_lots() -> None:
|
||||||
|
scraper = AvitoScraper(SimpleNamespace(avito_serp_ekb_only=True)) # type: ignore[arg-type]
|
||||||
|
lots = scraper._parse_html(
|
||||||
|
_read("avito_serp_sample.html"),
|
||||||
|
source_url_base="https://www.avito.ru/ekaterinburg/kvartiry/prodam?p=1",
|
||||||
|
)
|
||||||
|
got = [
|
||||||
|
(lot.source_id, lot.price_rub, lot.rooms, lot.area_m2, lot.floor, lot.total_floors)
|
||||||
|
for lot in lots
|
||||||
|
]
|
||||||
|
assert got == [
|
||||||
|
("8043936560", 5_500_000, 2, 54.0, 5, 9),
|
||||||
|
("8163084615", 4_200_000, 1, 38.0, 3, 16),
|
||||||
|
]
|
||||||
|
assert lots[0].source_url == (
|
||||||
|
"https://www.avito.ru/ekaterinburg/kvartiry/2-k._kvartira_54m_59et._8043936560"
|
||||||
|
)
|
||||||
|
# sortTimeStamp в миллисекундах, дата по Москве (#726).
|
||||||
|
assert [lot.listing_date for lot in lots] == [date(2023, 11, 15), date(2023, 11, 16)]
|
||||||
|
assert {lot.listing_segment for lot in lots} == {"vtorichka"}
|
||||||
|
assert scraper.parse_failures == 0
|
||||||
|
|
||||||
|
|
||||||
|
# ── cian.serp ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def cian_lots() -> dict[str, Any]:
|
||||||
|
scraper = CianScraper(SimpleNamespace(glitchtip_dsn=None)) # type: ignore[arg-type]
|
||||||
|
html = _read("cian_serp_ekb_2room_trimmed.html")
|
||||||
|
lots = scraper._parse_serp_html(html)
|
||||||
|
assert scraper._extract_total_offers(html) == 13_895
|
||||||
|
assert (scraper.state_extraction_attempts, scraper.state_extraction_failures) == (2, 0)
|
||||||
|
return {lot.source_id: lot for lot in lots}
|
||||||
|
|
||||||
|
|
||||||
|
def test_cian_serp_all_offers_parsed(cian_lots: dict[str, Any]) -> None:
|
||||||
|
assert list(cian_lots) == ["331661795", "333599038", "333279363", "321628098"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_cian_serp_secondary_offer(cian_lots: dict[str, Any]) -> None:
|
||||||
|
lot = cian_lots["331661795"]
|
||||||
|
assert lot.source == "cian"
|
||||||
|
assert lot.source_url.startswith("https://ekb.cian.ru/sale/flat/331661795/")
|
||||||
|
assert lot.listing_segment == "vtorichka"
|
||||||
|
assert (lot.house_source, lot.house_ext_id) == ("cian", None)
|
||||||
|
assert lot.price_rub == 7_990_000
|
||||||
|
assert (lot.rooms, lot.area_m2, lot.living_area_m2, lot.kitchen_area_m2) == (
|
||||||
|
2,
|
||||||
|
47.2,
|
||||||
|
28.0,
|
||||||
|
7.5,
|
||||||
|
)
|
||||||
|
assert (lot.floor, lot.total_floors, lot.year_built) == (2, 17, 1980)
|
||||||
|
assert lot.house_type == "panel"
|
||||||
|
assert lot.address == "р-н Октябрьский, мкр. Парковый, улица Большакова, 13"
|
||||||
|
assert (lot.lat, lot.lon) == (56.820035, 60.634287)
|
||||||
|
assert lot.listing_date == date(2026, 9, 14)
|
||||||
|
assert (lot.mortgage_available, lot.sale_type) == (True, "alternative")
|
||||||
|
assert (lot.is_homeowner, lot.is_pro_seller) == (False, True)
|
||||||
|
assert lot.phones == [] # #2217: телефоны не сохраняем
|
||||||
|
assert lot.metro_stations[0] == {
|
||||||
|
"name": "Геологическая",
|
||||||
|
"time": 5,
|
||||||
|
"mode": "transport",
|
||||||
|
"line_color": "00701A",
|
||||||
|
"line_id": 26,
|
||||||
|
"is_default": True,
|
||||||
|
}
|
||||||
|
# descriptionMinhash приходит списком — склеен через запятую в исходном порядке.
|
||||||
|
assert lot.description_minhash.startswith("16147461,5781654,4548911,")
|
||||||
|
assert len(lot.photo_urls) == 3
|
||||||
|
|
||||||
|
|
||||||
|
def test_cian_serp_newbuilding_with_house(cian_lots: dict[str, Any]) -> None:
|
||||||
|
lot = cian_lots["333599038"]
|
||||||
|
assert lot.listing_segment == "novostroyki"
|
||||||
|
assert (lot.house_source, lot.house_ext_id) == ("cian_newbuilding", "5779142")
|
||||||
|
assert lot.address == "р-н Железнодорожный, мкр. Старая Сортировка, переулок Проходной, 1Б"
|
||||||
|
assert lot.year_built == 2028 # buildYear нет, берётся год сдачи из deadline
|
||||||
|
assert lot.house_type == "monolith"
|
||||||
|
assert (lot.price_rub, lot.area_m2, lot.floor, lot.total_floors) == (4_834_000, 36.04, 22, 32)
|
||||||
|
assert lot.sale_type == "fz214"
|
||||||
|
|
||||||
|
|
||||||
|
def test_cian_serp_newbuilding_decoration_and_balcony(cian_lots: dict[str, Any]) -> None:
|
||||||
|
lot = cian_lots["333279363"]
|
||||||
|
assert lot.repair_state == "good" # decoration=fine
|
||||||
|
assert lot.has_balcony is True # balconiesCount=1
|
||||||
|
assert lot.house_type is None # materialType на странице null
|
||||||
|
assert lot.year_built == 2026
|
||||||
|
|
||||||
|
|
||||||
|
def test_cian_serp_newbuilding_without_street_keeps_address_houseless(
|
||||||
|
cian_lots: dict[str, Any],
|
||||||
|
) -> None:
|
||||||
|
"""В geo.address нет ни улицы, ни дома; в названии ЖК номера нет, кадастра нет.
|
||||||
|
Номер дома не выдумывается (#1773)."""
|
||||||
|
lot = cian_lots["321628098"]
|
||||||
|
assert lot.address == "р-н Чкаловский, мкр. Вторчермет"
|
||||||
|
assert (lot.house_source, lot.house_ext_id) == ("cian_newbuilding", "5705732")
|
||||||
|
|
||||||
|
|
||||||
|
# ── yandex.serp ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
def _gate(name: str) -> dict[str, Any]:
|
||||||
|
return json.loads(_read(name))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def yandex_secondary() -> dict[str, Any]:
|
||||||
|
lots = _parse_gate_json(_gate("yandex_gate_ekb_vtorichka_trimmed.json"), 1, "NO")
|
||||||
|
return {lot.source_id: lot for lot in lots}
|
||||||
|
|
||||||
|
|
||||||
|
def test_yandex_gate_pager() -> None:
|
||||||
|
extracted = _extract_gate_data(_gate("yandex_gate_ekb_vtorichka_trimmed.json"))
|
||||||
|
assert extracted is not None
|
||||||
|
entities, pager = extracted
|
||||||
|
assert len(entities) == 3
|
||||||
|
assert (pager["totalItems"], pager["totalPages"]) == (4077, 25)
|
||||||
|
|
||||||
|
|
||||||
|
def test_yandex_agency_offer_with_partner_url(yandex_secondary: dict[str, Any]) -> None:
|
||||||
|
lot = yandex_secondary["5228381943217465492"]
|
||||||
|
# url в выдаче — сайт агентства; source_url строится из offerId (#2235).
|
||||||
|
assert lot.source_url == "https://realty.yandex.ru/offer/5228381943217465492/"
|
||||||
|
assert lot.yandex_offer_id == "5228381943217465492"
|
||||||
|
assert lot.listing_segment == "vtorichka"
|
||||||
|
assert (lot.price_rub, lot.price_per_m2) == (4_400_000, 129_412)
|
||||||
|
assert (lot.rooms, lot.area_m2, lot.living_area_m2, lot.kitchen_area_m2) == (1, 34.0, None, 7.0)
|
||||||
|
assert (lot.floor, lot.total_floors, lot.year_built) == (8, 9, 1978)
|
||||||
|
assert lot.house_type == "brick" # BRICK
|
||||||
|
assert lot.ceiling_height_m == 2.5
|
||||||
|
assert lot.address == "Россия, Свердловская область, Екатеринбург, Шефская улица, 85"
|
||||||
|
assert (lot.lat, lot.lon) == (56.903275, 60.6229)
|
||||||
|
assert (lot.house_source, lot.house_ext_id) == (None, None)
|
||||||
|
assert lot.listing_date == lot.publish_date == date(2026, 8, 19)
|
||||||
|
assert (lot.is_homeowner, lot.is_pro_seller, lot.agency_name) == (None, True, "САМОЛЕТ ПЛЮС")
|
||||||
|
assert (lot.predicted_price_rub, lot.predicted_price_min, lot.predicted_price_max) == (
|
||||||
|
4_217_000,
|
||||||
|
3_795_000,
|
||||||
|
4_638_000,
|
||||||
|
)
|
||||||
|
assert (lot.price_trend, lot.price_previous_rub) == ("DECREASED", 4_450_000)
|
||||||
|
assert lot.metro_stations[0] == {"name": "Проспект Космонавтов", "min": 7}
|
||||||
|
# В фикстуре 6 фото с «//»: берутся первые 5 со схемой.
|
||||||
|
assert len(lot.photo_urls) == 5
|
||||||
|
assert all(u.startswith("https://avatars.mds.yandex.net/") for u in lot.photo_urls)
|
||||||
|
|
||||||
|
|
||||||
|
def test_yandex_owner_offer_in_complex(yandex_secondary: dict[str, Any]) -> None:
|
||||||
|
lot = yandex_secondary["6282460993454547968"]
|
||||||
|
assert lot.source_url == "https://realty.yandex.ru/offer/6282460993454547968"
|
||||||
|
assert (lot.is_homeowner, lot.is_pro_seller, lot.agency_name) == (True, None, None)
|
||||||
|
assert (lot.house_source, lot.house_ext_id) == ("yandex_realty_nb", "1668651")
|
||||||
|
assert lot.house_type == "monolith" # MONOLIT
|
||||||
|
assert (lot.floor, lot.total_floors) == (27, 27)
|
||||||
|
assert (lot.living_area_m2, lot.kitchen_area_m2) == (11.0, 14.0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_yandex_studio_without_rooms_total(yandex_secondary: dict[str, Any]) -> None:
|
||||||
|
lot = yandex_secondary["8530722463088927619"]
|
||||||
|
assert lot.rooms == 0 # roomsTotal отсутствует — студия
|
||||||
|
assert lot.area_m2 == 20.8
|
||||||
|
assert lot.kitchen_area_m2 is None
|
||||||
|
assert lot.house_type == "monolith_brick" # MONOLIT_BRICK
|
||||||
|
|
||||||
|
|
||||||
|
def test_yandex_newbuilding_without_valuation() -> None:
|
||||||
|
lots = _parse_gate_json(_gate("yandex_gate_ekb_novostroyki_trimmed.json"), 1, "YES")
|
||||||
|
assert len(lots) == 1
|
||||||
|
lot = lots[0]
|
||||||
|
assert lot.source_id == "6216493807134609867"
|
||||||
|
assert lot.listing_segment == "novostroyki"
|
||||||
|
assert lot.price_rub == 27_620_850
|
||||||
|
assert (lot.predicted_price_rub, lot.predicted_price_min, lot.predicted_price_max) == (
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
assert lot.ceiling_height_m is None
|
||||||
|
assert lot.house_type is None
|
||||||
|
assert (lot.house_source, lot.house_ext_id) == ("yandex_realty_nb", "2006795")
|
||||||
|
assert (lot.is_homeowner, lot.is_pro_seller, lot.agency_name) == (None, None, None)
|
||||||
|
assert lot.address == (
|
||||||
|
"Россия, Свердловская область, Екатеринбург, жилой район Центральный, "
|
||||||
|
"ЖК Александровский Сад"
|
||||||
|
)
|
||||||
Loading…
Add table
Reference in a new issue