|
Professor Seleznov
|
Kufar.by - это примерно как avito.ru, только в Беларуси. После очередного “улучшения” там стало невозможно выбирать авто и недвижимость: цены показываются только в белорусских рублях, хотя рынок всегда будет в долларах (боже, храни Америку). Поэтому я сделал небольшой Chrome Extension, который добавляет рядом ориентировочную цену в долларах. Пока только для авто и недвиги. И да, по ощущениям, ЛПРы, которые это выкатывали, никогда не покупали ни то ни другое на своём сайте. Пролог Попытка #1
Цена в долларах. Верните обратно! Невозможно ориентироваться.
Первоначальное сообщение с претензией (которое отправлял в форме на сайте) не цитируется в почте, только ответ. Что уже странно, но “это база”. Получил вот такие волшебные ответы: Ответ #1 По белорусскому законодательству расчёты и ценообразование внутри страны должны производиться в национальной валюте, то есть в белорусских рублях. Раньше продавцы часто указывали цены в долларах, так как рынок недвижимости исторически был привязан к иностранной валюте. Чтобы не вводить покупателей в заблуждение и избежать путаницы (например, когда цена написана в долларах, а подразумевается в белорусских рублях), мы приняли решение изменить отображение цен на объекты недвижимости, приведя все объявления к единому стандарту. Данное решение также основано на новых требованиях законодательства, касающихся оформления договоров с агентствами недвижимости, где цены фиксируются исключительно в белорусских рублях. При этом мы стремимся максимально сохранить удобство для наших пользователей: возможность подачи объявления и фильтрацию предложений по валюте мы оставляем. Это позволяет вам по-прежнему работать с привычными ориентирами и находить наиболее подходящие варианты. Если остались вопросы, то, пожалуйста, спрашивайте. Буду рада помочь. Попытка #2
Вы не думаете о своих пользователях. Сижу с калькулятором и пересчитываю цену каждого объявления. Кто это придумал… С другой стороны, у конкурентов есть возможность извлечь свою пользу. Может это и к лучшему.
Ответ #2 Андрей, мы понимаем, что эти нововведения могли доставить неудобства, при этом следует учитывать, что данное решение также основано на требованиях законодательства. Мы стремимся максимально сохранить удобство для наших пользователей: возможность подачи объявления и фильтрацию предложений по валюте мы оставляем. Также технические специалисты занимаются вопросом добавления валютного калькулятора. Благодарим вас за обратную связь и что решили с нами поделиться мнением ☺️ Попытка #3
realt.by & onliner.by указывают “ориентировочную цену” в долларах, а вам можно пожелать удачи.
Ответ #3 А нет ответа. Хватит это терпеть Но зачем спорить, когда можно сделать себе требуемый интерфейс поверх текущего - #тыжеинженер. Нужен небольшой Chrome Extension, который открывает страницы Куфара, находит цены в белорусских рублях и рядом показывает приблизительную цену в долларах. Без аккаунтов, без серверной части, без прокси. Просто контент-скрипт и курс НБРБ. Исходники лежат тут: comerc/try-kufar. Что получилось Расширение работает на двух доменах (авто и недвига):
{ "content_scripts": [ { "matches": [ "https://auto.kufar.by/*", "https://re.kufar.by/*" ], "js": ["src/content.js"], "css": ["src/content.css"], "run_at": "document_idle" } ] }
Идея простая: на странице есть цены вида 68 683 р. или 256 873 р.. Скрипт превращает их в:
68 683 р. <span class="kufar-usd-price">≈ 25 165 $</span>
Выглядит как маленький зелёный бейдж. Не замена цены, а подсказка рядом. Курс доллара Курс берётся из официального API Нацбанка:
const RATE_URL = "https://api.nbrb.by/exrates/rates/USD?parammode=2";
Запрос делает не content script, а background service worker. Так меньше сюрпризов с CORS и проще хранить кеш.
chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => { if (!message || message.type !== "kufar:getUsdRate") { return false; } getUsdRate() .then((rateInfo) => sendResponse({ ok: true, rateInfo })) .catch((error) => sendResponse({ ok: false, error: error.message })); return true; });
Кеш на 6 часов:
const CACHE_TTL_MS = 6 * 60 * 60 * 1000;
Если API временно не отвечает, берётся последнее сохранённое значение. Для такой задачи этого более чем достаточно: это не трейдинг, это “понять порядок цены”. Как ищем цены на странице У Куфара много разных блоков. Листинг, страница объявления, попап на карте, “Похожие объявления”, “Ранее вы смотрели”, автостраницы. Классы тоже не подарок: CSS modules, хеши, разные компоненты. (Бардак в танковых войсках). Поэтому привязываться к одному классу нельзя. Основной поиск идёт по текстовым узлам:
const PRICE_RE = /(^|[^\d])(\d[\d\s\u00a0.,]*?)\s*(р\.|руб\.?|BYN)(?=$|[^\wа-яё])/i;
Дальше TreeWalker проходит по тексту страницы:
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, { acceptNode(node) { return isPriceTextNode(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; } });
Но этого мало. Иногда цена разбита по вложенным span, иногда лежит в блоке с class*="price". Поэтому есть второй проход:
const candidates = root.querySelectorAll([ "[class*='price' i]", "[data-testid*='price' i]", "[aria-label*='цен' i]", "[aria-label*='price' i]" ].join(","));
Это не идеально академически, зато устойчиво к реальной вёрстке. Динамический DOM Куфар дорисовывает части страницы после загрузки. Например, попап на карте появляется не сразу. Поэтому обычного запуска один раз недостаточно. Решение стандартное:
const observer = new MutationObserver(() => { clearTimeout(scanTimer); scanTimer = window.setTimeout(() => scanPrices(), 250); }); observer.observe(document.body, { childList: true, subtree: true, characterData: true });
Каждое изменение DOM не сканируется мгновенно. Есть debounce на 250 мс, чтобы не устроить странице маленький стресс-тест. Конвертация Сама математика смешная:
badge.textContent = `≈ ${formatUsd.format(byn / rateInfo.rate)}`;
Форматирование через Intl.NumberFormat:
const formatUsd = new Intl.NumberFormat("ru-RU", { style: "currency", currency: "USD", maximumFractionDigits: 0 });
То есть 87 914 р. превращается примерно в ≈ 32 212 $. Несколько неприятных мелочей Самое интересное было не в курсе и не в регулярке. Самое интересное было в вёрстке. Например, похожие объявления внизу страницы имеют overflow: hidden и text-overflow: ellipsis. Бейдж добавлялся, но для длинных цен просто обрезался. Пришлось помечать строку цены своим классом и разрешать перенос:
p.kufar-usd-price-row { display: flex !important; flex-wrap: wrap; gap: 2px 0 !important; overflow: visible !important; text-overflow: clip !important; white-space: normal !important; }
Для аренды есть отдельная история: 604.41 р. / мес.. После добавления доллара суффикс / мес. переставал влезать. Его пришлось вынести в отдельный span и принудительно отправить на новую строку:
.kufar-usd-rent-suffix { display: inline-flex; flex-basis: 100% !important; }
А ещё на автостранице есть кнопка “Оформить в лизинг от … р. /м.”. Это не цена объявления, поэтому такие блоки пропускаются:
const SKIP_CONTEXT_RE = /лизинг|\/\s*м\./i;
В итоге расширение конвертирует основную цену авто, но не лезет в платежи по лизингу. Установка из исходников Пока расширение не в Chrome Web Store, ставится как unpacked extension.
git clone https://github.com/comerc/try-kufar.git cd try-kufar
Дальше в Chrome:
- открыть chrome://extensions;
- включить Developer mode;
- нажать Load unpacked;
- выбрать папку try-kufar;
- открыть страницу Куфара.
Если меняли код локально, надо нажать reload у расширения на странице chrome://extensions, а потом перезагрузить вкладку с Куфаром. Это важно: content scripts и CSS не всегда обновляются просто по F5. Итог Получился маленький пользовательский слой поверх сайта. Куфар показывает цены в белорусских рублях, как ему хочется или как ему надо. Расширение рядом показывает привычный ориентир в долларах. Никакой магии. Просто немного DOM, MutationObserver, API Нацбанка и терпение к чужой вёрстке. Codex решил проблему за пару часов!-Источник
|