一、接口体系概览
1688(阿里巴巴中国站)的包装信息主要通过商品详情类API获取,而非独立接口。包装数据分散在以下字段中 :
接口类型 核心接口 包装相关字段 数据覆盖度
官方开放平台 alibaba.product.get shippingInfo、saleInfo中的物流信息 基础重量、尺寸
第三方聚合API 1688.item_get weight、packing、packingSize、grossWeight等 完整包装规格
ERP工具类 product1688edit unitWeight、packageSize、volume 编辑/读取双向
关键发现:官方API对包装信息的返回较为分散,而第三方API(如AliPrice、VV-Tool等)通常已整合完整的包装字段,更适合直接获取结构化包装数据 。
二、官方开放平台:alibaba.product.get
- 接入准备
访问 1688开放平台 完成以下步骤 :
注册企业开发者账号:1688 API主要面向企业,个人开发者权限受限
创建应用:获取 App Key 和 App Secret
申请权限:申请 alibaba.product.get 接口权限
获取Access Token:通过OAuth2.0授权流程 - 核心请求参数
参数名 类型 必选 说明 示例值
app_key String 是 应用唯一标识 12345678
method String 是 接口方法名 com.alibaba.product.alibaba.product.get
timestamp String 是 时间戳(yyyy-MM-dd HH:mm:ss) 2026-04-07 16:42:00
v String 是 API版本 2.0
format String 是 响应格式 json
sign String 是 MD5签名 E4F2G3H4...
productId Long 是 1688商品ID 619899292404
fields String 否 指定返回字段 shippingInfo,saleInfo
- 包装信息相关返回字段
根据官方文档,包装信息主要分布在以下结构中 :
{
"productinfo": {
"shippingInfo": {
"freightTemplateID": 11754104, // 运费模板ID
"unitWeight": 1.5, // 单位重量(千克)
"packageSize": "10x20x50", // 包装尺寸(长x宽x高,厘米)
"volume": 10000, // 体积(立方厘米)
"sendGoodsAddress": { // 发货地址
"province": "浙江",
"city": "杭州"
}
},
"saleInfo": {
"amountOnSale": 200.0, // 可售数量
"minOrderQuantity": 3, // 最小起订量
"unit": "件", // 计量单位
"priceRanges": [ // 阶梯价格
{"startQuantity": 3, "price": 8.0}
]
}
}
}
注意:官方API的包装字段较为基础,详细的包装方式(如独立包装、彩盒、纸箱等)通常需要在attributes或description中解析 。
三、第三方聚合API(推荐方案)
由于官方API对包装信息的限制,实际开发中更推荐使用第三方聚合API,它们整合了完整的包装规格数据 。
- AliPrice API方案
AliPrice提供专门的1688商品详情接口,包含结构化包装信息 :
表格
接口 地址 包装字段
商品详情 https://www.aliprice.com/items/itemDetail weight、packing、packingSize、grossWeight
请求示例:
import requests
url = "https://www.aliprice.com/items/itemDetail"
headers = {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
data = {
"offerId": "1234567890", # 1688商品ID
"includePackaging": True # 显式请求包装信息
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
包装信息结构
packaging = result.get("packaging", {})
print(f"净重: {packaging.get('weight')}kg")
print(f"毛重: {packaging.get('grossWeight')}kg")
print(f"包装方式: {packaging.get('packing')}") # 如"独立包装"、"彩盒"
print(f"包装尺寸: {packaging.get('packingSize')}") # 如"10205cm"
print(f"装箱规格: {packaging.get('cartonQty')}件/箱")
print(f"外箱尺寸: {packaging.get('cartonSize')}") # 如"504030cm"
- 通用第三方API字段映射
不同第三方API的包装字段命名可能不同,以下是常见映射关系 :
表格
通用含义 AliPrice VV-Tool 其他常见命名
商品净重 weight unitWeight item_weight、netWeight
商品毛重 grossWeight - gross_weight、totalWeight
包装方式 packing - packagingType、packageStyle
单品包装尺寸 packingSize packageSize item_size、unitSize
体积 - volume cubicVolume、item_volume
外箱尺寸 cartonSize - outerCartonSize、boxSize
装箱数量 cartonQty - quantityPerCarton、packingQuantity
跨境包裹重量 - offerSuttleWeight crossBorderWeight
跨境包裹尺寸 - offerLength/Width/Height cbmDimensions
四、完整实战代码(Python)
以下是一个生产级的1688包装信息获取类,支持官方API和第三方API双通道 :
Python
复制
import requests
import time
import json
import hashlib
import urllib.parse
from typing import Dict, Optional, List
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(name)
class Alibaba1688API:
"""
1688商品包装信息获取客户端
支持官方API和第三方聚合API
"""
def __init__(self,
app_key: Optional[str] = None,
app_secret: Optional[str] = None,
third_party_key: Optional[str] = None,
use_official: bool = False):
"""
初始化
:param app_key: 1688开放平台App Key(官方API)
:param app_secret: 1688开放平台App Secret(官方API)
:param third_party_key: 第三方API密钥(推荐)
:param use_official: 是否使用官方API(默认False,使用第三方)
"""
self.app_key = app_key
self.app_secret = app_secret
self.third_party_key = third_party_key
self.use_official = use_official
# API端点配置
if use_official:
self.api_url = "https://gw.open.1688.com/openapi/param2/1/com.alibaba.product/alibaba.product.get"
else:
# 默认使用第三方聚合API(示例:AliPrice)
self.api_url = "https://www.aliprice.com/items/itemDetail"
# 备选:其他第三方API
self.backup_urls = {
"vv_tool": "http://api.vv-tool.com/tool/erps/product1688get",
"o0b_cn": "https://o0b.cn/ibrad/1688/item_get/"
}
def _generate_official_sign(self, params: dict) -> str:
"""生成1688官方API签名(MD5)"""
sorted_params = sorted(
[(k, v) for k, v in params.items() if v is not None],
key=lambda x: x[0]
)
sign_str = self.app_secret
for key, value in sorted_params:
encoded_value = urllib.parse.quote(str(value), safe='')
sign_str += f"{key}{encoded_value}"
sign_str += self.app_secret
return hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
def get_packaging_info_official(self, product_id: str) -> Dict:
"""
通过官方API获取包装信息(字段较分散)
"""
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
params = {
"app_key": self.app_key,
"method": "com.alibaba.product.alibaba.product.get",
"timestamp": timestamp,
"v": "2.0",
"format": "json",
"sign_method": "md5",
"productId": product_id,
"fields": "productID,subject,shippingInfo,saleInfo,attributes"
}
params["sign"] = self._generate_official_sign(params)
try:
response = requests.post(self.api_url, data=params, timeout=30)
response.raise_for_status()
data = response.json()
# 解析包装信息(官方API字段分散)
product_info = data.get("productinfo", {})
shipping = product_info.get("shippingInfo", {})
attributes = product_info.get("attributes", [])
# 从attributes中查找包装相关属性
packaging_attr = {}
for attr in attributes:
attr_name = attr.get("attributeName", "")
if any(keyword in attr_name for keyword in ["包装", "重量", "体积", "尺寸"]):
packaging_attr[attr_name] = attr.get("value")
return {
"success": True,
"source": "official",
"product_id": product_id,
"basic_weight": shipping.get("unitWeight"), # 单位重量
"package_size": shipping.get("packageSize"), # 尺寸(长x宽x高)
"volume": shipping.get("volume"), # 体积(立方厘米)
"freight_template_id": shipping.get("freightTemplateID"),
"packaging_attributes": packaging_attr, # 其他包装属性
"raw_data": data # 原始完整数据
}
except Exception as e:
logger.error(f"官方API调用失败: {e}")
return {"success": False, "error": str(e)}
def get_packaging_info_third_party(self, product_id: str, provider: str = "aliprice") -> Dict:
"""
通过第三方API获取完整包装信息(推荐)
"""
try:
if provider == "aliprice":
# AliPrice API
headers = {
"Authorization": f"Bearer {self.third_party_key}",
"Content-Type": "application/json"
}
payload = {
"offerId": product_id,
"includePackaging": True,
"includeSku": True
}
response = requests.post(self.api_url, headers=headers, json=payload, timeout=30)
elif provider == "vv_tool":
# VV-Tool API
headers = {"Authorization": f"Bearer {self.third_party_key}"}
params = {"productId": product_id}
response = requests.get(self.backup_urls["vv_tool"], headers=headers, params=params, timeout=30)
else:
# 通用第三方API(o0b.cn等)
url = f"{self.backup_urls['o0b_cn']}?key={self.third_party_key}&num_iid={product_id}"
response = requests.get(url, timeout=30)
response.raise_for_status()
data = response.json()
# 标准化包装信息字段(不同第三方API结构略有差异)
item = data.get("item", data) # 适配不同响应结构
packaging = {
"success": True,
"source": f"third_party_{provider}",
"product_id": product_id,
"title": item.get("title"),
# 核心包装字段(第三方API通常更完整)
"net_weight": self._extract_weight(item.get("weight") or item.get("unitWeight")),
"gross_weight": self._extract_weight(item.get("grossWeight")),
"weight_unit": "kg", # 通常为千克
"packing_type": item.get("packing") or item.get("packagingType"), # 独立包装/彩盒/纸箱
"unit_package_size": item.get("packingSize") or item.get("packageSize"), # 单品包装尺寸
"carton_dimensions": item.get("cartonSize"), # 外箱尺寸
"quantity_per_carton": item.get("cartonQty"), # 装箱数量
"volume": item.get("volume"), # 体积(立方厘米)
"shipping_weight": item.get("shippingWeight"), # 发货重量
# 扩展属性
"material": item.get("material"), # 材质
"spec_params": item.get("specParams", []), # 规格参数列表
"raw_data": data
}
# 计算物流常用指标
if packaging["carton_dimensions"] and packaging["quantity_per_carton"]:
packaging["logistics_recommendation"] = self._analyze_logistics(packaging)
return packaging
except Exception as e:
logger.error(f"第三方API调用失败: {e}")
return {"success": False, "error": str(e)}
def _extract_weight(self, weight_val) -> Optional[float]:
"""提取数值型重量"""
if not weight_val:
return None
if isinstance(weight_val, (int, float)):
return float(weight_val)
# 处理字符串如 "0.8kg"、"1.2KG"
import re
match = re.search(r'(\d+\.?\d*)', str(weight_val))
return float(match.group(1)) if match else None
def _analyze_logistics(self, packaging: Dict) -> Dict:
"""基于包装信息分析物流建议"""
try:
# 解析外箱尺寸(格式:50*40*30cm)
carton_size = packaging["carton_dimensions"]
if not carton_size:
return {}
dims = [float(x) for x in carton_size.replace('cm', '').split('*')]
if len(dims) != 3:
return {}
length, width, height = dims
volume_weight = (length * width * height) / 5000 # 体积重(快递标准)
actual_weight = packaging.get("gross_weight", 0)
# 判断计费重量
chargeable_weight = max(volume_weight, actual_weight)
return {
"volume_weight_kg": round(volume_weight, 2),
"actual_weight_kg": actual_weight,
"chargeable_weight_kg": round(chargeable_weight, 2),
"dimensional_factor": "1:5000", # 体积重系数
"suitable_for": "express" if chargeable_weight < 20 else "freight",
"stackable": height < 60 # 是否适合堆叠
}
except:
return {}
def get_packaging(self, product_id: str, prefer_third_party: bool = True) -> Dict:
"""
统一入口:获取包装信息
"""
if prefer_third_party and self.third_party_key:
# 优先使用第三方API(数据更完整)
result = self.get_packaging_info_third_party(product_id)
if result.get("success"):
return result
# 回退到官方API
if self.app_key and self.app_secret:
return self.get_packaging_info_official(product_id)
return {"success": False, "error": "无可用API配置"}
==================== 使用示例 ====================
if name == "main":
# 方式1:使用第三方API(推荐,数据完整)
api = Alibaba1688API(third_party_key="your_third_party_key")
# 方式2:使用官方API(需企业资质)
# api = Alibaba1688API(
# app_key="your_app_key",
# app_secret="your_app_secret",
# use_official=True
# )
# 获取商品包装信息
result = api.get_packaging("1234567890")
if result["success"]:
print("✅ 包装信息获取成功")
print(f"商品标题: {result.get('title')}")
print(f"净重: {result.get('net_weight')}kg")
print(f"毛重: {result.get('gross_weight')}kg")
print(f"包装方式: {result.get('packing_type')}")
print(f"单品尺寸: {result.get('unit_package_size')}")
print(f"外箱尺寸: {result.get('carton_dimensions')}")
print(f"装箱数: {result.get('quantity_per_carton')}件/箱")
# 物流分析
logistics = result.get('logistics_recommendation', {})
if logistics:
print(f"\n📦 物流建议:")
print(f" 计费重量: {logistics.get('chargeable_weight_kg')}kg")
print(f" 适合运输方式: {'快递' if logistics.get('suitable_for') == 'express' else '货运'}")
else:
print(f"❌ 获取失败: {result.get('error')}")
五、包装信息字段详解
核心包装字段说明
表格
字段名 含义 示例值 应用场景
weight / unitWeight 商品净重(单件) 0.8(kg) 计算单品运费、仓储规划
grossWeight 商品毛重(含包装) 1.2(kg) 物流计费、报关申报
packing 包装方式描述 "独立包装"、"彩盒"、"OPP袋" 上架描述、客户预期管理
packingSize 单品包装尺寸 "10205cm" 仓储货架规划、包装采购
cartonSize 外箱/ carton尺寸 "504030cm" 集装箱装载计算、货运报价
cartonQty 每箱装箱数量 50(件) 批量采购、库存管理
volume 体积(立方厘米) 10000 仓储计费、运输方式选择
offerSuttleWeight 跨境包裹重量 2.0(kg) 跨境物流、平台发货
offerLength/Width/Height 跨境包裹尺寸 20.0(cm) 国际运费计算
包装信息计算逻辑
Python
复制
物流计费重量计算(快递行业标准:体积重 = 长宽高 / 5000)
def calculate_chargeable_weight(length, width, height, actual_weight):
"""
计算计费重量(实际重量 vs 体积重,取较大者)
:param length: 长(cm)
:param width: 宽(cm)
:param height: 高(cm)
:param actual_weight: 实际重量(kg)
"""
volume_weight = (length width height) / 5000
return max(volume_weight, actual_weight)
集装箱装载估算
def estimate_container_load(carton_length, carton_width, carton_height, carton_qty):
"""
估算20GP集装箱可装载数量(标准20GP内径:589cm x 235cm x 239cm)
"""
container_dims = (589, 235, 239)
carton_dims = (carton_length, carton_width, carton_height)
# 简单估算(不考虑实际堆叠间隙)
max_qty = 1
for c_dim, box_dim in zip(container_dims, sorted(carton_dims)):
max_qty *= int(c_dim // box_dim)
return max_qty * carton_qty # 总件数
六、常见问题与解决方案
表格
问题现象 可能原因 解决方案
官方API返回包装信息为空 商家未填写或字段权限不足 使用第三方API或联系商家补充
重量单位不一致(kg/g) 不同接口标准不同 统一转换为千克(kg)存储
尺寸格式不统一(cm/mm/英寸) 商家录入习惯差异 正则解析并标准化为厘米
包装方式描述混乱 商家自定义描述 建立映射字典标准化(如"独立包装"→"individual")
跨境包裹重量与实际不符 1688字段为预估重量 实际发货前称重校准
API调用频率受限 官方API限流(默认1000次/天) 使用第三方API或申请提升额度
七、最佳实践建议
数据标准化:建立包装信息标准库,将"彩盒"、"color box"、"纸盒"等映射为统一编码
多源校验:官方API + 第三方API + 页面抓取(爬虫)三重校验,确保数据准确性
缓存策略:包装信息变更频率低,建议缓存6-24小时,减少API调用成本
异常处理:商家未填写包装信息时,设置默认值或标记为"需人工确认"
合规注意:通过官方API或授权第三方获取数据,避免未经授权的爬虫导致法律风险
八、扩展应用场景
基于包装信息API可构建以下应用:
智能运费计算:根据重量、尺寸、目的地自动选择最优物流方案
仓储优化:基于包装尺寸计算货架空间需求,优化仓库布局
采购决策:对比不同供应商的包装规格,选择物流成本最低的方案
报关自动化:自动生成报关所需的重量、尺寸、包装类型数据
碳足迹计算:基于重量和运输距离计算碳排放量