惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

爱范儿
爱范儿
T
The Blog of Author Tim Ferriss
G
Google Developers Blog
博客园_首页
博客园 - 【当耐特】
量子位
S
SegmentFault 最新的问题
B
Blog RSS Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
V
Visual Studio Blog
T
Tailwind CSS Blog
阮一峰的网络日志
阮一峰的网络日志
V
V2EX
Y
Y Combinator Blog
博客园 - 聂微东
The Cloudflare Blog
小众软件
小众软件
J
Java Code Geeks
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
月光博客
月光博客
H
Help Net Security
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
宝玉的分享
宝玉的分享

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Cross-matching products when Rakuten's API hides the JAN
Aulvem · 2026-06-27 · via DEV Community

Aulvem

Trying to compute "where is this product cheapest" across Rakuten's and Yahoo!'s APIs, you hit a wall before any price math: how do you decide two listings are the same product? The JAN (the product's barcode number) would make it easy — except the two marketplaces are asymmetric about it.

  • Yahoo! Shopping: a jan_code parameter looks the JAN up directly, and the response carries janCode back.
  • Rakuten item search: no JAN parameter. You throw the JAN string into keyword, and the JAN itself usually sits inside the item caption rather than a structured field.

So Yahoo! you can trust into a confirmed JAN match; Rakuten you can't use without proving that a keyword=JAN hit is really that product. Here's how I split matching into three certainty tiers around that.

Split identity into three certainty tiers

Don't force everything through a JAN match. Keep only what you can tie down with confidence at the top; the lower the tier, the weaker the evidence, so the right to enter comparison and to notify narrows with it.

Tier Method Comparison Notify
① JAN match Yahoo! direct lookup + Rakuten keyword=JAN scored for confidence confirmed only yes
② Name fuzzy Score on model no. / size / brand → candidates → user confirms after confirm confirmed only
③ No match single-store (e.g. pasted URL) no own drops only

Minimal implementation: scoring a Rakuten hit

Each Rakuten hit accumulates a score; thresholds split it three ways. ≥0.8 is confirmed, ≥0.5 is needs-review (no notify), below that is discarded.

type Grade = "high" | "mid" | "low";

function janMatchScore(
  hit: { itemName: string; itemCaption: string; itemPrice: number },
  jan: string,
  range: { min: number; max: number } | null,
): { grade: Grade; score: number } {
  let s = 0;
  // (1) JAN string appears in the name or caption (most direct evidence)
  if (hit.itemCaption.includes(jan) || hit.itemName.includes(jan)) s += 0.5;
  // (2) price sits inside the product-search API's range
  if (range) {
    const lo = range.min * 0.7; // allow 30% below (old models, parallel imports)
    const hi = range.max * 1.5; // allow 50% above (shipping-included, bundles)
    s += hit.itemPrice >= lo && hit.itemPrice <= hi ? 0.3 : -0.4;
  }
  // (3) a model number or size can be read off the hit
  if (/[a-z]+-?\d+/i.test(hit.itemName) || /\d+\s*(ml|g)/i.test(hit.itemName)) s += 0.2;

  const score = Math.max(0, Math.min(1, s));
  const grade: Grade = score >= 0.8 ? "high" : score >= 0.5 ? "mid" : "low";
  return { grade, score };
}

Refusing to treat a weak hit as confirmed — discarding low, and not letting mid notify — was the single most effective guard against merging different products into one.

Gotchas

  • The product-search API (productCode=JAN) returns 404 a lot. The price range is missing for many hits, so you can't lean on term (2). I added a fallback anchored on the cross-marketplace counterpart: if a model-number token pulled from the same-JAN Yahoo! hit (alphanumeric, 5+ chars, effectively unique) appears in the Rakuten hit's name, and the price is within ±40% of the counterpart's, promote to confirmed. The token alone can collide; the price band screens that out.

  • The fuzzy tier doesn't auto-confirm. A matching model number, size, and brand still only give you a probability, so stop at surfacing candidates and master only the ones a person confirms. A wrong pairing is rejected in one tap (dropped from the candidate pool for good). Notifications fire on JAN-confirmed and user-confirmed only.

Wrapping up

Even when JANs don't line up, collapsing identity into three certainty tiers makes cross-marketplace comparison hold: confirmed JAN matches go in the table, weak evidence becomes candidates, and unmatchable items fall back to single-store alerts. Not forcing a JAN match on everything is what prevents wrong merges.

The point-inclusive price math, the accumulating mis-match reports, and the notification-trigger rules are written up on the Aulvem site → How Rakuten's API hides the JAN, and the 3-tier cross-marketplace match