chineur
chineur
为整个项目按最低价格(含运费)报价,新品与二手分开处理,并提供分组采购方案,以最大程度减少实际支付总额。
逐件商品买最便宜并不是正确答案:向 10 个商家买 10 件商品,就要付 10 次运费。购物车引擎会把购买集中到 2 或 3 个商家(计入免邮门槛),并显示与这种盲目合计之间的成本差额。
安装
python -m venv .venv && ./.venv/bin/pip install -e .
./.venv/bin/pytest # 74 tests hors ligne, aucun réseauPython 3.11 或更高版本。项目无需任何密钥即可运行:它在使用 LeDénicheur、AliExpress 和 Leboncoin 时不需要任何密钥。需要密钥的数据源(eBay、Mouser)则干脆保持关闭,list_sources() 会说明这一点。
Related MCP server: aws-calculator-assistant
密钥
不会从版本化文件中读取任何密钥。bin/chineur-mcp.sh 会加载本地的 .env 文件(若存在,并被 git 忽略),否则直接使用当前环境;这就允许通过密钥管理器用简单替换的方式注入密钥,值仅经由进程环境传递:
export EBAY_CERT_ID=$(votre-cli-de-coffre get password 'eBay - API Browse')参数 | 作用 | 没有它时 |
| eBay Browse keyset | 此 eBay 数据源被关闭 |
| Mouser Search API key | Mouser 数据源被关闭 |
| 遇到反爬墙时启用浏览器兜底 | 兜底关闭,其余功能正常 |
| 状态目录(缓存、限额、cookies、日志) | 使用 |
用法
通过 MCP stdio 暴露(bin/chineur-mcp.sh),共有三个工具:
工具 | 作用 |
| 在一次调用中为整个清单报价 |
| 单条商品场景,使用 |
| 每个数据源的状态、剩余每小时限额以及当前发生的切断 |
每一条商品都允许指定数量或上限:字符串 "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 | 新品 + 二手 | 精确 | 官方 Browse API,目前所需组件 2026-08-06 起生效 |
Mouser | 新品 | 预计 | 专业分销商,官方 API。它覆盖了 AliExpress 缺失的内容(焊料、吸锡带、电阻、晶体管、连接器)。 对国产模块没用:要么没有,要么 3 到 5 倍价格 |
已知限制(测试于 2026-08-05,且除非使用 Playwright (V2) 之外无法绕过):
AliExpress 不在搜索页面结果中给出卖家或运费,且通过纯 HTTP 打开产品页面时显示为空。因此合并购买只能在平台层面完成,并采用其免邮门槛。几次连续请求后,AliExpress 返回 HTTP 200 以及一份 2 KB 页面:程序会将其识别并视为封锁,而不是“没有报价”。
AliExpress 的上限大约是每 IP 链接尝试的 6 次请求,在无法确认 46 小时后于 2026-08-10 附带测得:6 个商品被正常返回(共 133 条报价),第 7 次被封锁,FlareSolverr 也撞上了同一堵墙。因此,17 个商品的清单无法通过一次批量爬取完成,即使等待时间加长并保持间隔也一样。这是结构性限制,也是必须用官方驻盟 API(
portals.aliexpress.com)的原因,而不是通过调一个更长的时间间隔就能解决的问题。二手价格只是作为参考。 Leboncoin 的广告是自由文本:搜索结果可能是一整批货、损坏的零件或配件。新品和二手永远没有一起合并成一个统一价。
运费在代码中标记为
~时表示其为估算值,?时表示未知数(见脚本shipping.py)。任何包含估算运费的合计都会补表示为估算值。
匹配效率:真正的瓶颈
测试于 2026-08-08,使用真实需要的清单(17 个组件):我们当时口中的「找不到」并不是因为缺少数据源,而是因为商品名称本身的问题。通过统计 eBay 在启动结果过滤前返回的原始标题,我们可以区分出两个不同原因。
查询条件太长。 在 eBay 上搜索 « etain soudure 60/40 flux 0.8mm » 返回 0 个结果;搜索 « etain soudure » 返回 到 个结果。每多增加一个描述性单词都会让结果一步步收窄,直至没有结果。因此我引入了 reduced_query 和 guarded_search 的第二次尝试机制:当某个数据源没有返回任何结果时,会对聚焦到只有在失败时进行第二次更短的查询,并且计数不占用 该 数据源的最后一次配额。
过滤算法之前误配了一批好结果。 例如搜索“cables dupont assortiment”对比标题“Câble Dupont … Trésultat : 0.67,而适度为 0.70”——评分规则只做子串匹配,因此“复数形式”(multiple 形态) 让整个匹配失效。现在 _apparie 不加前缀的经过换进行匹配(取占其 60% 的公共前缀),且仅针对长度 ≥4 的单词,不会处理数字或短参考,因此 “2410” 和 “2420” 仍然会被视为两种不同传感器。
在同一列表上用同样清单测试,里,第二新版文字结果:eBay 覆盖数量从 10/17 提高到 14/17,完全找不到商品数从 5 减少到 3。剩下即使所有数据源也无法找到的三样东西是:带焊接盘的 PCB 板,Diese 2201M 以及 Sugon 8620DX 这类复制品,如 Sugon 8620DX。
这代价是真实存在的、且需要付出。 扩大规模搜索范围后,结果会对应多扩展较宽的问题而不是你所问的问题:“ expansion-ESP32-WROOM-32 DevKit 38 针”会扩展到 “ESP32-ESP32 32”,并返回一个 30 招的型号。为什么要这样设计 任何来自于放大搜索范围的结果,因此都必须完整体,提供“搜索范围已扩展为 “…”” 这样的提示,并且提示要一直显示到最终呈现为止。
浏览器自动化翻墙(FlareSolverr)
这是项目目前最大的软肋: AliExpress 是国产模块的唯一真实数据源,而它在 5 到 9 次搜索之后大约就会锁定。README 中 erst von 这个节写为“不用 Playwright (V2) 不可绕过”。但它实,无需在项目端添加了一个额外条件:一个 FlareSolver 实例(真实 Chrome浏览器,运行 JavaScript e,并使用完整的浏览器指纹),因此可以通过配置 FLARESOLVERR_URL 来启用。未设置时,该翻墙功能则直接关闭。
实测于 2026-08-08,当时直连已被阻断、熔断器已打开:fr.aliexpress.com/w/wholesale-LD2410C.html 返回 HTTP 200,响应大小为 832 KB,无任何防爬特征,并且我们现有的 HTML 解析器从页面中解析出 60 件商品,价格为 EUR。解析逻辑完全没有改动。
现在将它与 AliExpress._items 中给这个爬虫连接:只要出现反爬页面,或者响应内容不完整,就会先尝试翻墙,如果最终调任会才抛出 Blocked。设计要点如下:
这是一个保护机制,不会每次搜索都启用。 每次调用都会启动一个 Chrome 实例:响应效果和资源占用都较高。因此在真正发生不可失败时才进入。
返回失败时返回
None,而不是[]。一个空列表会被当成“没有任何报价”,那样断路器就不会自动打开,然后连接器就会在下一次查询时再次去批访问,已封锁的数据源,会加剧限制。永不阻塞调用流程。
flaresolverr.fetch抛不到它:否则,sign自己故障会掩盖真正的原因,并且能从外部看到页面性问题。设置FLARESOLVERR_URL=以禁用该翻墙。连续失败 2 次后放弃。 见下面所述限制过大——如果不这么考虑,后续每个商品都得白白多等待一整数十几十秒。
它的限制(实测于 2026-08-08)。 这个兜底方案并不是持久有效的翻墙替代,而是一种第二种额度。连续连续 8 次 AliExpress 搜索中,前 6 次搜索能拿到 60 个商品,每次 4 到 6 秒;第 7 次在等待 101 秒后返回 500 错误;第 8 次则直接返回反爬墙(208 KB,携带爬虫标记 RGV587)。站的 IP 出口地址不会改变,因此最终整个服务器都会被会诶一次识别。代码里有两种对应方案:把 maxTimeout 从 90 秒降到 45 秒,并且一种当反爬墙也拖着 HTTP 200 成功时会被统计为失败,否则这个暂停保护早就不会真正派礼。
因此,目前实际可用的 AliExpress 额度大约是 9 次提高到 15 次,而每页的报价结果从 20 个变成 60 个。这是净增加,但同时还不是無限。
防封提供保障
出口 IP 是唯一且住宅的——一旦被站点限制,完事彻底切断。整个模块的代码设计都是为了防止 USB接口无论如何都不要发生这种情况。
每小时配额持久化在 SQLite(
var/chineur.db)中:Leboncoin 10/小时、LeDénicheur 30/小时、AliExpress 20/小时、eBay 200/小时、Mouser 60/小时(API 配额,无 IP 风险)。按来源串行化的间隔,而不是简单的
sleep:编排器并行启动所有条目, 并发的延迟本来也会同时结束,请求仍会成突发地发出。每次启动都要等前一次完成。针对 403 / 验证码 / 页面截断的熔断器:1 小时,AliExpress 为 2 小时,其惩罚会持续到触发它的那次突发之后。
AliExpress 的阻断既不是配额问题,也不是速率问题。 2026-08-06 的三组测试记录,均从未被缓存:
间隔
传输方式
被阻断前已服务条数
6-12 s
裸请求
5(46 s 时阻断)
6-12 s
带 cookie 的会话
6(56 s 时阻断)
45-60 s
带 cookie 的会话
2(108 s 时阻断)
2,5 s
带 cookie 的会话,JSON 端点
9(30 s 时阻断)
放慢 降低 吞吐,所以节奏并不是杠杆:最快的吞吐来自快速运行。阻断持续约 40 分钟,且测量到两次;它由
FAIL_SYS_USER_VALIDATE/RGV587_ERROR::SM表明,这是阿里巴巴要求验证的反爬机制。商品从内部端点
POST www.aliexpress.com/fn/search-pc/index读取(就是搜索页自身调用的那个),请求载荷形式为mods,会话事先已在首页上打开。它返回与 HTML 页面完全相同的商品对象,位于.data.result.mods.itemList.content,只需 390 字节而不是 600。陷阱:响应中有多个块带有content键;其中搜索筛选的那一块出现在itemList之前。HTML 页面仍作为自动回退,但只有在响应不再具有预期形式时才这样:面对反爬墙时,从同一 IP 重试 HTML 只会浪费一次请求。持久会话(
transport.Session)为 AliExpress 保留:首页访问过一次,之后重放 cookie,cookie jar 放在var/cookies/以便重启后依然可用;一旦页面返回被截断就丢弃。它对阻断没有产生可测量的改善;保留它只是因为这让流量更接近浏览器的流量。尚未定论的路径:如果某天内部端点关闭,就把该来源外包给联盟托管服务(omkar.cloud,每月 5 000 次免费请求),代价是第三方会看到我们的搜索。
在速率限制器之前查询缓存:重新计算一个项目不会再请求任何数据。默认 TTL 为 1 小时,但绝不短于熔断器的断开时间(
Connector.effective_ttl,AliExpress 为 6 小时)。没有这个下限,一个比单个来源预算更大的项目永远无法完成:断开后的复起看到空缓存,重做同样的最初搜索,再次烧掉预算并再次被阻断,无限循环。 eBay 除外,它被排除在缓存之外,以便继续符合豁免(见下文)。超出 Leboncoin 配额的项目按价值影响降序的顺序处理,未处理的条目会在汇报中列出。
Token 经济
计算仍然留在 Python 中,只有最终结论返回:输出为紧凑的表格文本;每个商品给出一个最佳全新报价和一个二手报价;标题截断、URL 清理、备注合并;诊断放在 var/chineur.log。实测:10 个商品约为 650 个 token。
测试
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 个料,每分钟 30 个 /money,每天 1 000 个 /money。因此 limit_per_hour = 60,间隔 2 秒:这不是反爬,而是遵守配额。
三个底层的选择:
mouserPaysCustomsAndDuties: true— Mouser 从德克萨斯发货。如果没有这个标志,关税出现在后欠你的之后,一个在纸面上“更便宜”的价格在送达时却更贵。searchOptions: InStock— 供货周期 12 星期的料号,在一个项目正在进行的价格对比里根本没有理由存在。价格阶梯按需求数量取值。 只用第 1 档会限高任何被动元件的批量采购。
两个会弄显比较的陷阱,都会在库存项目上标注:最小起订量(0.10 € 元/个,但按 100 个一袋出售,实际结账金额是 10 €)和价格格式(“0.095 €”是一个三位小数的价格;“$1,250”是一部二百五十一的价钱—一个冒失的解析器会在两个方向上错 1000 倍)。
运费:未经核实。 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 key set 上:取到了 client_credentials token,真正的搜索 29 个对“cable hdmi 2.1 2m”的报价,运费精确从 shippingOptions 读出。
物品状态读取是在 conditionId 上,绝不在 condition 上:后者是 eBay 翻译的(在 EBAY_FR 上为“Neuf”“Occasion”“Ouvert (jamais utilisé)”);原本的英文键表完全不匹配,所以所有条目都被当成/used。编号为 7000(表示“拆机)”的物品会被排除:在 3 € 的价位,一个损坏的物品会在价格对比中胜出,而没有任何提示。
合规性(“Your Keyset is currently disabled”)。 eBay 只有在注册了账户遭删除通知服务或获豁免后,才会启用 Production keyset。本项目采用的是“我不保留 eBay 数据”豁免,代码让这句话从字面上成为真:EBay.cacheable = False 因此主要的没有 eBay 答复写入 var/chineur.db(它们包含卖家昵称)。有一个测试锁定了这一点。如果有一天我们把禁再把 eBay 放回缓存,这个豁免就变成过改为:到那时就需要反过来托管该通知端点。
许可
MIT,见 LICENSE。
Maintenance
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
- AlicenseBqualityBmaintenanceMCP 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.6MIT
- AlicenseNot gradedqualityBmaintenanceBuild shareable AWS Pricing Calculator estimates programmatically via MCP tools, designed for creating MAP funding estimates from customer infrastructure descriptions.8MIT
- AlicenseNot gradedqualityCmaintenanceEnables querying and comparing prices, availability, ratings, reviews, and seller details from major Russian and Chinese marketplaces (Wildberries, Ozon, Yandex Market, and others) without requiring API keys, via a unified MCP interface.3MIT

BizNetAI MCP Serverofficial
AlicenseNot gradedqualityBmaintenanceA 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
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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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