一、接口体系概览
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
1. 接入准备
访问 1688开放平台 完成以下步骤:
- 注册企业开发者账号:1688 API主要面向企业,个人开发者权限受限
- 创建应用:获取 App Key 和 App Secret
- 申请权限:申请
alibaba.product.get接口权限 - 获取Access Token:通过OAuth2.0授权流程
2. 核心请求参数
| 参数名 | 类型 | 必选 | 说明 | 示例值 |
|---|---|---|---|---|
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 |
3. 包装信息相关返回字段
根据官方文档,包装信息主要分布在以下结构中:
JSON
{
"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,它们整合了完整的包装规格数据。
1. AliPrice API方案
AliPrice提供专门的1688商品详情接口,包含结构化包装信息:
| 接口 | 地址 | 包装字段 |
|---|---|---|
| 商品详情 | https://www.aliprice.com/items/itemDetail | weight、packing、packingSize、grossWeight |
请求示例:
Python
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')}") # 如"10*20*5cm"print(f"装箱规格: {packaging.get('cartonQty')}件/箱")print(f"外箱尺寸: {packaging.get('cartonSize')}") # 如"50*40*30cm"2. 通用第三方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 requestsimport timeimport jsonimport hashlibimport urllib.parsefrom typing import Dict, Optional, Listimport 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 | 单品包装尺寸 | "10*20*5cm" | 仓储货架规划、包装采购 |
cartonSize | 外箱/ carton尺寸 | "50*40*30cm" | 集装箱装载计算、货运报价 |
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可构建以下应用:
- 智能运费计算:根据重量、尺寸、目的地自动选择最优物流方案
- 仓储优化:基于包装尺寸计算货架空间需求,优化仓库布局
- 采购决策:对比不同供应商的包装规格,选择物流成本最低的方案
- 报关自动化:自动生成报关所需的重量、尺寸、包装类型数据
- 碳足迹计算:基于重量和运输距离计算碳排放量