Skip to main content
Glama

chineur

Оценка стоимости всего проекта по лучшей цене с учётом доставки, новые и б/у раздельно, с планом группового заказа, минимизирующим реально уплаченную сумму.

Самый дешёвый товар по каждой позиции — неверное решение: 10 позиций у 10 продавцов — это 10 доставок. Движок корзины группирует покупки у 2–3 продавцов, с учётом порогов бесплатной доставки, и показывает разницу с этим наивным итогом.

Установка

python -m venv .venv && ./.venv/bin/pip install -e .
./.venv/bin/pytest          # 74 tests hors ligne, aucun réseau

Нужен Python 3.11 или выше. Проект работает без каких-либо ключей: LeDénicheur, AliExpress и Leboncoin ничего не требуют. Источники с ключами (eBay, Mouser) остаются просто выключенными, и list_sources() сообщает об этом.

Related MCP server: aws-calculator-assistant

Ключи

Никакой секрет не читается из файла под версионным контролем. bin/chineur-web-mcp-server.sh — нет, точнее bin/chineur-mcp.sh — загружает локальный .env, если он существует (игнорируется git), иначе берёт окружение как есть. Это позволяет подставлять их из менеджера секретов простой заменой — значение при этом попадает в процесс только через окружение:

export EBAY_CERT_ID=$(votre-cli-de-coffre get password 'eBay - API Browse')

Variable

Роль

Без неё

EBAY_APP_ID / EBAY_CERT_ID

набор ключей eBay Browse

источник eBay выключен

MOUSER_API_KEY

ключ Mouser Search API

источник Mouser выключен

FLARESOLVERR_URL

браузерный обход при антибот-стене

обход выключен, остальное работает

CHINEUR_VAR

каталог состояния (кэш, квоты, cookie, журнал)

<dépôt>/var

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

Доступно через MCP stdio (bin/chineur-mcp.sh), три инструмента:

Инструмент

Роль

price_project(articles, zipcode?, used_threshold?, detail?)

оценивает полный список одним вызовом

best_price(article, …)

случай одного товара, с detail="full"

list_sources()

состояние, оставшийся почасовой бюджет и текущее отключение каждого источника

Каждый товар принимает количество или лимит: "LD2410C x3", "ESP32-S3 <=12ё".

В командной строке:

python -c "
import asyncio; from chineur.models import Project
from chineur.search import Orchestrator; from chineur.report import render
async def m():
    o = Orchestrator(); print(render(await o.run(Project.build(['LD2410C x2','BME280'])), failures=o.failures))
asyncio.run(m())"

Источники и что они стоят

Источник

Категория

Доставка

Примечание

LeDénicheur

новое + б/у

точная

агрегатор: даёт Amazon, Cdiscount, Fnac, Rue du Commerce, Back Market, Rakuten в одном запросе

AliExpress

новое

оценка

единственный реалистичный источник специфических китайских модулей

Leboncoin

б/у

оценка

максимум 10 поисков в час, это не обсуждается

eBay

новое + б/у

точно

официальная API Browse, активна с 2026-08-06

Mouser

новое

оценка

профессиональный дистрибьютор, официальное API. Покрывает то, что у AliExpress отсутствует (олово, плетёнка, пункты, резисторы, транзисторы, коннекторы). Бесполезен на китайских модулях — их нет или они в 3–5 раз дороже

Известные ограничения, измеренные 2026-08-05 и обход которых невозможен без Playwright (V2):

  • AliExpress не даёт ни продавца, ни доставку на странице поиска, а карточка товара в простом HTTP пуста. Группировка поэтому происходит на уровне платформ, с её порогом бесплатной доставки. После нескольких запросов подряд AliExpress отвечает 200 со страницей на 2 КБ: это распознаётся как блокировка, а не как отсутствие предложений.

  • Бюджет AliExpress — примерно 6 запросов с свежего IP, измерено 2026-08-10 после 46 часов без обращений: 6 позиций отданы (133 маршрутов обмена), блокировка на 7-ю, FlareSolverr тоже отправлялся к стене. Поэтому список из 17 позиций не может быть оценён за один подход скрапером, сколько бы ты ни ждал. Это структурный предел, у которого есть официальное партнёрское API (portals.aliexpress.com), а не настройка терпения.

  • На б/у цена индикативная. Объявления Leboncoin — это свободный текст: результат может быть лотом, сломанной деталью или аксессуаром. Новое и б/у никогда не объединяются в одну цену.

  • Доставка помечается ~, когда она оценочная (таблица shipping.py) и ?, когда неизвестна. Итог, содержащий оценку, помечается как таковой.

Релевантность: настоящий ограничивающий фактор

Измерено 2026-08-08 на реальном стандартном списке (17 позиций, компоненты): «не найденное» было не от недостатка источников, а из-за названия. Две отдельные причины — их разделяли, считая сырые заголовки, выданные eBay до фильтрации.

Слишком длинный запрос. «ńberries…» — точнее «brassart…» — «лося»: «живой припой 60/40 с флюсом 0.8мм» выдаёт 0 результат от eBay; «живой припой» даёт 11. Каждое добавленное описательное слово возвращает результат, пока не станет пусто. Отсюда reduced_query и второй шанс в guarded_search: когда источник не даёт ничего, делается ещё одна попытка с заголовком, урезанным до артикулов и первых двух основных слов, а все остальные определения выбрасываются. Дополнительный запрос — только при неудаче и никогда на последнем кредите бюджета.

Фильтр выбрасывал хорошее. «кабели dupont ассортимент» против «Câble Dupont… Ассортимент 5–100 pnc» сказать упало до 0,67 при пороге 0,70: сравнение только по подстроке убивал плюраль. Теперь _apparie ищет по общему префиксу (60 % слова), и только для слов не короче четырёх букв — никогда для чисел или коротких артикулов, так что «2410» и «2420» остаются разными датчиками.

Результат по тому же списку: eBay вырос с 10 до 14 покрытий из 17, позиций вообще без предложений стало с 5 до 3. Остались три настоящих «недосягаемых» на всех источниках: плата-«пастилка», Die and the 2201M и Sugon 8620DX.

За это придётся платить, и плата реальна. Расширенный поиск отвечает на более широкий вопрос, чем заданный: «ESP32-WROOM-32 DevKit 38 контактов» при варианте «esp32 wroom 32» находит модель с 30 контактами. Поэтому любое предложение из расширения снабжается оговоркой «поиск расширен до „…“», которая должна оставаться видимой до отображения.

Браузерный аварийный выход (FlareSolverr)

Слабый диспетчер проекта: AliExpress — единственный источник китайских модулей, и его блокируют после 5–9 поисковых. В README эта дыра объявлялась «не закрывается без Playwright (V2)». Она закрывается, без дополнительной зависимости со стороны проекта: экземпляр FlareSolverr использует настоящий Chrome, выполняет JavaScript и имеет полный браузерный цифровой отпечаток. Он задаётся через FLARESOLVERR_URL; если не задан — аварийный выход просто выключается`.

Измерено 2026-08-08, в момент, когда прямой коннектор был заблокирован, а его брейкер открыт: fr.aliexpress.com/w/wholesale-LD2410C.html отдал HTTP 200, 832 КБ, без принятых анти-бот-маркеров, и существующий HTML-парсер нашёл там 60 позиций с ценами в EUR. Никакой замены в парлинге не понадобилось.

Подключение в AliExpress._items: при анти-бот-стене или усечённой странице сначала пробуем обход, и только потом выбрасываем Blocked. Конструктивные моменты:

  • Авария, а не постоянный режим. Каждый вызов запускает Chrome: это медленно и тяжело. Идём туда только в подтверждённый блок.

  • None — не [], когда обход не дал результата. Пустой список был бы воспринят как «нет результатов», брейкер не разомкнулся бы, и коннектор на следующей позиции снова стучался бы в заблокированный источник, усиливая ограничение.

  • Никогда не блокирует. flaresolverr.fetch не бросает исключение: падение решителя маскировало бы настоящую причину под инцидентом инфраструктуры. FLARESOLVERR_URL= отключает обход.

  • Останавливаемся после двух неудачных . Смотри лимит ниже: без этого каждый следующий элемент ещё оплачивал бы десятки секунд ожидания впустую.

Его лимит, измеренный 2026-08-08. Обход — это не обходка наружу, это второй бюджет. На восемь запросов AliExpress подряд: шесть вернули по 60 позиций за 4–6 секунд, седьмой — ошибку 500 после ожидания 101 с, восьмой — анти-бот-стену (208 КБ, маркер RGV587). Исходящий IP не меняется, поэтому рано илинаблю ту же стену. Два следствия в коде: maxTimeout уменьшено с 90 до 45 секунд, и стена, отданная с HTTP 200, считается провалом; иначе счётчик остановок никогда не сработал бы.

На практике бюджет AliExpress увеличивается примерно с 9 до 15 запросов, по 60 позиций на странице вместо 20. Чистый выигрыш — где-то не бесконечность.

Анти-банные предохранители

Исходящий IP единственный, и он резидентный: бан ресонанс отрубает его весь. Модуль написан так, чтобы никогда этого не допускало.

  • Часовые лимиты сохраняются в SQLite (var/chineur.db): Leboncoin 10/ч, LeDénicheur 30/ч, AliExpress 20/ч, eBay 200/ч, Mouser 60/ч (квоты API, риска для IP нет).

  • Последовательный интервал по источнику, а не просто sleep: поскольку оркестратор запускает все товары параллельно, одновременно задержки завершились бы одновременно, и запросы всё равно уходили бы залпом. Каждый выход ждёт предыдущий.

  • Автоматический предохранитель при 403 / капче / усечённой странице: 1 ч, 2 ч для AliExpress, причём штраф сохраняется и после всплеска запросов, который его вызвал.

  • Блокировка AliExpress — это не квота и не вопрос частоты запросов. Три испытания от 2026-08-06, метки которых никогда не кэшировались:

    интервал

    транспорт

    отдано до блокировки

    6–12 с

    голые запросы

    5 (блокировка на 46 с)

    6–12 с

    cookie-сессия

    6 (блокировка на 56 с)

    45–60 с

    cookie-сессия

    2 (блокировка на 108 с)

    2,5 с

    cookie-сессия, JSON-эндпоинт

    9 (блокировка на 30 с)

    Замедление ухудшает результат, значит, дело не в ритме: лучшая результат достигается при быстрых запросах. Останавливает блокировка на ~40 минут — измерено дважды — и о ней сигнализируют FAIL_SYS_CONNECT / RGV587_ERROR::SM, антибот Alibaba, требующий подтверждения.

  • Товары читаются с внутренней endpoint POST www.aliexpress.com/fn/search-pc/index (того, который вызывает сама страница поиска), полезной нагрузкой вида mods, из уже открытой на главной сессисии. Он возвращает ровно такие же объекты товаров, как HTML-страница, в .data.result.mods.itemList.content, и всего 390 КБ вместо 600. Ловушка: несколько блоков ответа содержат ключ content; тот, что относится к фильтрам поиска, находится до includes. HTML-страница остаётся автоматическим запасным вариантом, но только если ответ больше не соответствует ожидаемой форме: при антибот-стене повторная попытка через HTML с того же IP просто потратила бы запрос.

  • Постоянная сессия (transport.Session) сохраняется для AliExpress: страница главной посещается один раз, файлы cookie впоследствии имеют ходить в cookies/, чтобы пережить перезапуск, и сбрасываются сразу, как только страница возвращается с усечением. Никакого выигрыша в блокировке не измерено; она оставлена, потому что приближает трафик к браузерному.

  • Незавершённая идея: если внутренний эндпоинт когда-нибудь закроется, можно отдать источник стороннему хостингу (omkar.cloud, 5 000 бесплатных запросов/мес), ценой того, что третья сторона будет видеть наши запросы.

  • Кэш проверяется до ограничителя скорости: повторная обработка проекта ничего не загружает. TTL по умолчанию 1 ч, но никогда не короче, чем срабатывает режим разрыва (Connector.effective_ttl, 6 ч для AliExpress). Без этого минимума проект, превышаем бюджет источника, не может завершиться: запуск после паузы находит пустой кэш, снова выполняет те же первые запросы, снова тратит бюджет и снова получает блокировку — бесконечно.

  • Проект, превышающий лимит Leboncoin, обрабатывается в порядке убывающей важности, и необработанные товары называются в отчёте.

Экономия токенов

Расчёт остаётся на Python, вверх поднимается только результат: вывод в плотном табличном тексте, на каждый товар — по одному лучшему новому предложению и одному подморнадному, обрезанные заголовки, очищенные URL, сгруппированные пометки, диагностика в var/chineur.log. Измерено: 10 товаров ≈ 650 токенов.

Тесты

pytest              # 74 tests hors ligne, aucun réseau
pytest -m network   # 5 tests d'intégration réels (consomment du quota)

Движок корзины полностью тестируется офлайн, включая сложные случаи (порог бесплатной доставки, срабатывает из-за размещения заказа, единственный продавец, товар без предложений, равные цены). Свойство «оптимизальный итог ≤ наивный итог» проверяется на 50 случайных наборах предложений.

Mouser

Всего одна переменная: MOUSER_API_KEY. Бесплатный ключ в самообслуживании на mouser.com/api-hub (вкладка Search API).

Ключ должен быть создан из mouser.fr. Поиск по ключевым словам не принимает никаких параметров валюты (проверено в swagger api.mouser.com/api/docs/V1): валюта зависит от сайта, на котором создана ключ. Ключ, созданный на mouser.com, возвращает доллары, и коннектор отбрасывает их, а не конвертируют по выдуманному курсу — источникл бы просто выглядел пустым.

Заявленные лимиты Mouser: 50 позиций за раз, 300 запросов в минуту, 1 000 запросов в день. Отсюда limit_per_hour = 60 и интервал 2 с: это не защита от бана, а соблюдение лимита.

Три принципиальных выбора:

  • mouserPaysCustomsAndDuties: true — Mouser отправляет из Техаса. Без этого флага таможенные пошлины приходят позже, и товар «дешевле» на бумаге становится дороже при доставке.

  • searchOptions: InStock — позиция с срокым 12 недель не нужна в сравнении цен для текущего проекта.

  • Цены уровни отслеживаются по запрашиваемому количеству. Выбор самого первого уровня делает переоценку всей групповой закупки пассивных компонентов.

Две ловушки, которые исказили бы сравнение, и они обель оставляют в примечании к предложению: минимальный заказ (0,10 € за штуку в пак способнаком по 100 штук, т.е. реальные 10 € на кассе) и формат цены («0,096 €» — это цена с трём знакам после запятой, а «$1,250» — это тысяча двести пятьдесят; наивный парсер ошибётся в тысячу раз в обеи направлениях).

Доставка: не проверена. Франко в 50 € без НДС и около 20 € при сумме ниже этой суммы сверены по вебу (2026-08-07), а не по счёту. Поэтому они описаны в shipping.py и возвращаются как ESTIMATED, но не как реальный факт. Это нужно исправить при первом настоящем заказе: если заказ ниже порога, доставка съедает выгоду, и именно этот порог решает, нужна ли данная источник.

eBay

EBAY_APP_ID (App ID) и EBAY_CERT_ID (Cert ID), для набора ключей Production — единственный работающий. Набор Sandbox подключается через EBAY_ENV=sandbox, которая переключает на api.sandbox.ebay.com. В sandbox коннектор остаётся выключенным: инвентарь фиктивный, цены попадали бы в корзину без всякого предупреждения. EBAY_SANDBOX_OK=1 включает его только для проверкой механики.

Проверено 2026-08-06 на наборе Production: получен маркер client_credentials, выполнены реальные искания (29 предложений по запросу «cable hdmi 2.1 2m», стоимость доставки точно прочитана в shippingOptions).

Состояние товара читается из conditionId, никогда не из condition: последний локализован eBay («Neuf», «Occasion», «Ouvert (jamais utilisé)» для EBAY_FR), а исходная англоязычная таблица не совпадали ни с чем, поэтому всё выходило как подержанное. Товар с кодом 7000 («на запчасти») отбрасывается: при цене 3 € повреждённое изделие выиграло бы сравнение, и на это ничто бы не указало.

Соответствие (« Your Must be»). eBay переводит набор ключей Production только после подписки на не уведомления об удалении аккаунта счёта или исключенияnement. Проект выбирает ограничение "не сохраняю данные eBay", и код делает его буквально истинным: EBay.cacheable = False, значит, ни один ответ eBay не записывается в var/chineur.db (в них есть псевдонимы продавцов). Тест это закрепляет. Если однажды его снова включить в кэш, исключение станет ложноëм: тогда придётся разместить у себя endpoint для уведомлений.

Лицензия

MIT, см. LICENSE.

Install Server
A
license - permissive license
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    B
    quality
    B
    maintenance
    MCP server for finding, comparing, and ranking the cheapest real offers across eBay, Amazon, Craigslist, OfferUp, and Google Shopping, with tax estimation and exact-model filtering.
    6
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Build shareable AWS Pricing Calculator estimates programmatically via MCP tools, designed for creating MAP funding estimates from customer infrastructure descriptions.
    8
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A hosted MCP server that routes natural-language shopping queries to independent merchant storefronts, returning normalized product and merchant results for AI agents and shopping assistants.
    MIT

View all related MCP servers

Related MCP Connectors

  • Hosted no-auth MCP for exact-spec packaging search, live price, stock, cart handoff, and no-match.

  • Real, buyable product and service offers — live pricing and trackable links for any MCP agent.

  • Routes natural-language shopping queries to merchant storefronts, returns normalized results.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/GRSMael/chineur'

If you have feedback or need assistance with the MCP directory API, please join our Discord server