反向海淘系统最脏的输入:把用户粘贴的分享文案、淘口令、短链统一解析成商品 ID

admin2个月前淘宝API224
反向海淘系统里,用户不会规规矩矩给你一条干净的详情页链接。他粘过来的可能是一整段带 emoji 的分享文案、一个 ¥xxxx¥ 淘口令、一段 m.tb.cn 短链,或者一条被跟踪参数污染到 200 字符的 URL。这篇讲我怎么把这件事做成一个稳定服务——解析链路、正则、短链展开、口令接口、缓存,以及把失败率从 12% 压到 1.5% 的全过程。

一、先盘点你实际要处理的输入长什么样

我在生产环境里捞了 500 条真实用户输入,粗分类如下:

形态
占比
示例特征
手机端分享文案
~38%
一大段中文 + 商品标题 + ¥abcd1234¥
标准详情页链接
~27%
detail.1688.com/offer/1234567890.html
短链
~18%
m.tb.cn/h.xxxxxx / 3.cn/xxxx
带跟踪参数的脏链接
~12%
尾部挂 ?spm=a1z10.5-c&scm=...&utm_...
图文混排(截图OCR、表格粘贴)
~5%
需要先抽文本

这五类输入的解析成本完全不同。所以第一件事不是写正则,而是先做形态判定,再分派给对应的解析器。

二、解析链路的五段设计

我把它拆成五段,每段只负责一件事,任何一段失败都能定位:
原始文本
  → ① 文本清洗(去 emoji / 去全角 / 统一换行)
  → ② 平台与形态判定(1688 / 淘宝 / 京东 / 未知)
  → ③ ID 抽取(正则)
  → ④ 兜底:短链展开 / 口令解析
  → ⑤ 统一输出 goods_id + platform

① 文本清洗

看起来最没技术含量,实际是最容易漏的。用户从 iOS 复制过来的文案里有:
  • 全角字符::? 以及全角数字 123
  • 零宽字符(U+200B / U+FEFF):肉眼看不见,但会把你的正则切断
  • emoji 与装饰符:✨🛒 之类
  • 换行不统一:\r\n / \r / \n 混用
import re, unicodedata

INVISIBLE = re.compile(r"[\u200b-\u200f\ufeff\u2060]")

def clean(text: str) -> str:
    text = INVISIBLE.sub("", text)
    text = "".join("\r" if c == "\n" else c for c in text.split("\r")[0:1]) + text
    text = text.replace("\r\n", "\n").replace("\r", "\n")
    text = unicodedata.normalize("NFKC", text)     # 全角转半角,一步搞定
    return text.strip()
unicodedata.normalize("NFKC", ...) 这一行值一百行手写替换代码,它能同时处理全角字母数字和兼容字符,强烈建议放在清洗链最前面。

② 平台判定

不要只靠域名判断——用户可能只粘了"【淘宝】"这样的前缀词。我的判定顺序是:显式域名 > 文本前缀词 > 兜底未知。
PLATFORM_RULES = [
    ("1688",  r"(?:detail\.)?1688\.com|阿里巴巴|1688"),
    ("taobao", r"(?:item\.)?taobao\.com|m\.tb\.cn|天猫|淘宝|tmall"),
    ("jd",    r"(?:item\.)?jd\.com|3\.cn|京东|jd\.hk"),
]

def detect_platform(text):
    for name, pat in PLATFORM_RULES:
        if re.search(pat, text, re.I):
            return name
    return "unknown"

③ ID 抽取

三个平台的商品 ID 藏在完全不同的位置,这是最容易写错的一段:
ID_PATTERNS = {
    "1688":   r"offer/(\d{8,})",
    "taobao": r"[?&](?:id|itemId)=(\d{8,})",
    "jd":     r"(?:item\.jd\.com/|/product/)(\d{6,})",
}

def extract_id(platform, text):
    m = re.search(ID_PATTERNS[platform], text)
    return m.group(1) if m else None
注意 1688 有个坑:detail.1688.com/offer/1234567890.html 里的 ID 是报价 ID,而 item_get 接受的 num_iid 就是它,不用做转换;但淘宝的 num_iid 和 sku_id 是两套东西,链接里带的是 num_iid。千万别把京东的 sku_id 当成淘宝的 num_iid 传进同一个字段,我在早期版本把两者混用,导致一整个类目的详情全查不到。

④ 短链展开

短链没有 ID,只能先跟重定向。这里有两个必须做对的地方:
第一,用手机 UA。 同一个 m.tb.cn 链接,桌面 UA 请求可能被重定向到一个带登录引导的中间页,Location 里没有商品 ID;手机 UA 通常会直接落到 item.taobao.com/item.htm?id=...。
第二,限制跳转次数并检查落点。 有的短链会先跳到活动落地页,再跳详情页,一次 HEAD 拿不到最终地址。
import requests

MOBILE_UA = ("Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) "
             "AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1")

def expand_short(url, max_hop=5):
    for _ in range(max_hop):
        r = requests.head(url, allow_redirects=False,
                          headers={"User-Agent": MOBILE_UA}, timeout=8)
        loc = r.headers.get("Location")
        if not loc:
            return url
        url = requests.compat.urljoin(url, loc)
        if re.search(r"item\.(taobao|jd)\.com|detail\.1688\.com", url):
            return url
    return url
短链展开的实测成功率并不高——3.cn 这类会有一定的跳转异常,所以我把展开失败的情况统一转入口令/链接转换接口。

⑤ 淘口令与链接转换

淘口令(¥xxxxxxxx¥)必须靠专用接口,正则解析不出来。淘宝平台的 item_password 后台统计成功率 95%,用来解口令是够用的;链接清洗与长短链互转用 item_link,它的成功率是 100%,是我这套链路里最稳的一环,我把它当"URL 归一化器"用——不管用户给的是淘客链、短链还是带一堆跟踪参数的长链,都先过一遍它。
def parse_password(text):
    url = "https://api-gw.onebound.cn/taobao/item_password"
    params = {
        "key": KEY, "secret": SECRET, "api_name": "item_password",
        "content": text,            # 直接传原始文案,接口自己找口令
        "result_type": "json",
    }
    r = requests.get(url, params=params, timeout=12).json()
    if r.get("code") != "0000":
        return None, r.get("code")
    return r.get("item", {}).get("num_iid"), "0000"

def normalize_link(link):
    url = "https://api-gw.onebound.cn/taobao/item_link"
    params = {"key": KEY, "secret": SECRET, "api_name": "item_link",
              "url": link, "result_type": "json"}
    return requests.get(url, params=params, timeout=12).json()
把口令和链接都归到 num_iid 之后,后面的详情、比价、加购链路就只需要面对一种入参。

三、四个花了两天才定位的坑

坑 1:& 被二次转义。 用户从浏览器复制来的链接里 & 可能已经是 &,你直接塞进 params 字典,requests 会把它再编码一次,服务端拿到的 id 值就带上了尾巴。做法是解析前先做一次 html.unescape。
坑 2:淘口令有生命周期。 口令并不永久有效,过期后接口会返回业务失败。我给口令结果单独打了短 TTL(10 分钟)缓存,过期即失效,不做长缓存,避免用户拿到已失效的 ID。
坑 3:短链落到 landing page。 有些短链的落点是活动页,页面上有几十个商品链接。我的原则是只接受能唯一确定商品 ID 的落点,出现多个候选就判失败、转人工——选错商品的成本远高于多一次人工。
坑 4:cache 在这里要慎用。 解析类请求(item_link / item_password)我全部关掉缓存(cache=no),因为同一个短链在不同时间可能指向不同活动页;而详情接口(item_get)走缓存没问题。混用缓存策略是我早期最隐蔽的成本浪费来源。

四、落地成服务:缓存与指标

把上面的逻辑包成一个 POST /resolve 接口,入参是原始文本,出参是 {platform, goods_id, source},source 标记它是从正则、短链还是口令拿到的。
关键是在缓存层做一层 raw_text → goods_id 的映射,因为同一段分享文案会被多个客服/多个用户反复粘贴:
def resolve(raw, ttl=7 * 24 * 3600):
    key = "rsv:" + hashlib.md5(raw.encode()).hexdigest()
    if cached := redis.get(key):
        return json.loads(cached)
    result = do_resolve(raw)                     # 五段链路
    if result["goods_id"]:
        redis.setex(key, ttl, json.dumps(result))
    return result
上线前后我记录了一组数据,解析失败率从 12.3% 降到 1.5%。下降主要由三块贡献:NFKC 归一化解决了一批全角/零宽字符导致的"看起来有链接、其实抽不出 ID";item_link 接管了脏链接清洗;缓存把重复粘贴的解析请求从下游接口上摘掉了——命中率稳定在 60% 以上,也就是说超过一半的解析请求根本不到达网关层。
监控上我只看两个指标:按 source 分的解析成功率、未知平台的原始文本采样。后者尤其有用——unknown 占比突然上升,通常意味着某个平台改了分享文案模板,比等接口大面积报错要早发现半天。
解析完成后,拿到 num_iid / sku_id 就该走详情了。这里提醒一句选型:1688 的 item_get(99%)可以放心做主链路;淘宝的 item_get 后台统计只有 40%,必须配降级;京东详情用 item_get_pro(78%),并且 不要碰它的 item_search(28%)。选错入口,前面解析做得再漂亮也没用。

五、写在最后

这套链路的价值在于:把不确定性收在入口处,让下游永远只面对一种干净的入参。 解析这件事没有巧劲,就是把清洗、判定、抽取、兜底、缓存五段各自做扎实,然后盯着指标慢慢补边界。
接口参数我参考的是 open.onebound.cn/help/api,测试 key 我是在开放平台的控制台申请的,入口放这里,需要的自取:API 控制台


相关文章

淘宝拍立淘接口(图片搜索商品列表)怎么用?一文讲透

淘宝拍立淘接口(图片搜索商品列表)怎么用?一文讲透

关键词:拍立淘接口、淘宝图片搜索商品列表 API、拍立淘 API、以图搜同款接口、淘宝图片搜同款买家发来一张图,问"哪里能买到同款";卖家看到一张爆款图,想知道谁在卖、卖多少钱、卖...

电商选品分析运营场景:京东商品爆款潜力研判与货源筛选落地方案

在京东电商精细化运营时代,选品早已告别“凭经验、靠感觉”的粗放模式。多数商家普遍面临核心痛点:盲目上新导致动销率低迷、跟风选品陷入同质化价格战、无法提前捕捉品类增长趋势、货源品质不稳定引发售后差评,最...

吃透 Taobao.Item.Get 接口:字段解析、签名调试与高频应用场景

一、前言在电商 SaaS、ERP、独立站铺货、竞品数据分析赛道里,taobao.item.get 是淘宝开放平台(TOP)最核心、使用量最高的商品详情官方接口。相比逆向爬虫,官方 API 具备合规稳定...

电商数据的获取方式:API、爬虫、第三方服务及更多

电商数据的获取方式:API、爬虫、第三方服务及更多

在竞争激烈的电商领域,数据是驱动业务增长的关键。准确、及时地获取电商数据,并进行深入分析,能够帮助企业洞察市场趋势、优化运营策略、提升用户体验。本文将全面介绍电商数据的获取方式,涵盖API接口、网络爬...

获取淘宝商品详情item_get_pro参数说明

item_get_pro-获得淘宝商品详情高级版taobao.item_get_pro公共参数名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中)secretString是...

深度解析以图搜索商品API:技术原理、接口设计与实践优化

深度解析以图搜索商品API:技术原理、接口设计与实践优化

在电商数字化转型加速的当下,以图搜索商品(以下简称“图搜商品”)已从可选的增值功能升级为核心用户体验模块。无论是C端用户“拍图找同款”的即时需求,还是B端商家“批量比价、货源匹配”的运营需求,图搜商品...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。