还在手动复制1688商品信息?一个Python脚本帮你自动搞定
先说个真实场景。
运营收到 30 个 1688 链接,要建一张选品表:标题、起批价、起批量、库存、主图、店铺、SKU 数量。做法是——开 30 个标签页,一个个复制标题粘进 Excel,回到页面看价格,右击主图另存为,规格那一栏靠手打。
两个小时后表格建完了,但问题才刚开始:
- 标题里全是「【爆款】」「【一件代发】」前缀,排序、筛选、去重全废;
- 页面上写着
¥26.50,其实是 500 件起的价,你按 2 件算利润,报价直接亏; - 主图存下来是 750×750 的缩略图,原图链接过了两天就失效;
- 十几个 SKU 手工抄,漏一个没人发现,等客户下单才发现没这个颜色。
这些信息本来就不该用手复制。 接口一次就能取全,而且取的是结构化字段,不用再猜哪段文字是价格。
下面这个脚本,输入一批链接,输出一张能直接给运营用的表格 + 一文件夹主图。
一、它到底做什么
links.txt(一行一个链接)
│
├─ 链接 → 商品ID(自动去重)
├─ 并发调接口,单条失败不影响其它
├─ 本地缓存,第二次跑直接命中
├─ 解析:标题 / 起批价 / 批发价 / 价格区间 / 起批量 / 库存 / 销量 / 店铺 / 主图
└─ 输出
├─ 商品表.xlsx ← 18 列,冻结首行 + 自动筛选 + 超链接
├─ 商品表.csv ← 没装 openpyxl 时的降级方案
├─ 商品表_失败.csv ← 失败的链接 + 错误码 + request_id
└─ images/ ← 主图,按「ID_标题.jpg」命名
一句话:链接进,Excel 出,图片落地。
二、三步跑起来
第 1 步:环境
python --version # 3.8 以上都行,脚本只用标准库
python -m pip install openpyxl # 可选,装了才能出 .xlsx
不装 openpyxl 也能用,脚本会自动降级成 CSV,Excel 双击照样打开。
第 2 步:拿密钥
去万邦开放平台(open.onebound.cn)注册,添加 1688.item_get 接口,拿到 key 和 secret,塞进环境变量:
# Windows PowerShell
$env:ONEBOUND_KEY="你的key"
$env:ONEBOUND_SECRET="你的secret"
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
# macOS / Linux
export ONEBOUND_KEY=你的key
export ONEBOUND_SECRET=你的secret
还没跑通过接口本身?先看《1688商品详情API接口实战》那篇,把单条请求跑通,再回来批量。
第 3 步:准备清单,开跑
links.txt 长这样,# 开头是注释,链接和纯 ID 混着写都行:
# 9 月秋季选品
https://detail.1688.com/offer/610947572360.html
https://m.1688.com/offer/610947572361.html?offerId=610947572361
610947572362
python 1688_batch_export.py links.txt --out 秋季选品 --images --workers 4
跑起来是这样(数字为示意):
共 30 个商品,并发 4,优先读缓存
[1/30] ✓ 610947572360 ¥29.90 便携式榨汁机家用充电款 (新抓)
[2/30] ✓ 610947572361 ¥18.80 304不锈钢保温杯 便携 (新抓)
[3/30] ✗ 610947572363 错误码 2000
...
完成:成功 28 条,失败 2 条,耗时 11.6s
已导出 秋季选品.csv
已导出 秋季选品.xlsx
失败清单:秋季选品_失败.csv(2 条)
30 个商品,十几秒。手动做大约 25 分钟。
三、它替你做的五件事
1. 三种链接形态,都能认出商品 ID
1688 的链接不止一种写法,PC 端、分享链接、纯数字 ID 都得吃:
def extract_id(text: str) -> str | None:
text = text.strip()
if not text or text.startswith("#"):
return None
for p in (r"/offer/(\d{6,})\.html", r"offerId=(\d{6,})", r"^(\d{6,})$"):
m = re.search(p, text)
if m:
return m.group(1)
return None
顺带做了输入去重:同一个商品贴了两次,只抓一次。
2. 并发抓,但一条失败不会拖垮整批
30 个链接串行请求要 20 多秒,4 并发压到 6 秒左右。关键是失败隔离——某条商品下架、某个请求超时,只进失败清单,不影响其它:
with ThreadPoolExecutor(max_workers=workers) as pool:
futures = {
pool.submit(work, nid): nid for nid in ids}
for fut in as_completed(futures):
row, meta, payload = fut.result() # 单条异常在这里被捕获
if row is None:
failed.append({
...}) # 记错误码和 request_id
else:
rows.append(row)
并发别贪,--workers 4 已经很够;再往上容易撞上 4008 并发达上限。
3. 缓存:第二次跑,一个请求都不发
批量任务最怕“跑到第 27 个断了,重跑又从第 1 个开始”。脚本把每次抓到的原始数据存进 SQLite:
CREATE TABLE item_cache (
num_iid TEXT PRIMARY KEY,
payload TEXT, -- 原始 item JSON
fetched_at INTEGER
)
重跑时先查缓存,命中就跳过请求。我实测第二轮 4 个商品 0 次接口调用,全部走缓存。要强制刷新(比如对账)加 --refresh。
4. 价格算清楚,而不是“抄一个数”
1688 的价格是好几个概念,脚本一次给全:
| 列 | 来源 | 用途 |
|---|---|---|
| 起批价 | price |
页面展示价,通常是最低档 |
| 批发价 | batch_price |
授权后才有,做利润测算用它 |
| 价格区间 | SKU 价格 min~max | 一眼看出规格差价大不大 |
| 起批量 | min_num |
报价必看,2 件起和 500 件起是两个生意 |
prices = [fnum(s.get("price")) for s in sku_list if fnum(s.get("price")) > 0]
price_range = f"{min(prices):.2f}~{max(prices):.2f}" if len(prices) > 1 else ""
库存还有个坑:num 有时是 0,但 SKU 里明明有货。脚本做了回落——总库存取不到就按 SKU 求和。
5. 标题清洗只动开头,不动正文
这是最容易写错的一行。粗暴地删掉所有括号内容,会把「304不锈钢」「500ml」这类关键信息也干掉:
PROMO_TAG = re.compile(r"^[\s]*[【\[((][^】\]))]{0,20}[】\]))]")
def clean_title(t: str) -> str:
t = PROMO_TAG.sub("", t or "").strip() # 只剥离开头 ≤20 字的营销标签
return re.sub(r"\s+", " ", t)[:80]
效果:【爆款】便携式榨汁机家用充电款 → 便携式榨汁机家用充电款,而 304不锈钢保温杯 原样保留。
四、几个不显眼但很要命的细节
① 图片小于 1KB 就算失败。 1688 图床有防盗链,被拦时返回的不是 403,而是一张占位小图。下载后判断大小,比判断状态码靠谱:
if len(data) < 1024:
return False # 基本是占位图 / 错误页
② 商品 ID 在 Excel 里会变成科学计数法。 610947572360 一进单元格就成了 6.10948E+11,回头查都查不回来。写表时强制文本格式:
row[0].number_format = "@"
③ 表格要能直接用。 冻结首行、开启筛选、主图列和详情链接列转成可点超链接、列宽按内容给足——这些不加,运营第一件事就是自己调格式。
④ 失败清单必须留 request_id。 出问题时把 request_id 发给服务商,能直接定位是哪次调用,比截图有效得多。
五、常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
4016 余额/套餐问题 |
key 停用或套餐过期 | 登录后台看套餐,或换 key |
4013 调用次数超限 |
当日额度用完 | 次日再跑,或升级套餐 |
4008 并发达上限 |
--workers 太大 |
降到 2~3,加 --delay |
部分商品 2000 |
商品已下架 / ID 不存在 | 正常现象,看失败清单 |
| 图片下载全失败 | 图床防盗链 | 加 Referer(脚本已带),或只保留 URL |
| Excel 中文乱码 | 用了 CSV 且编码不对 | 用 .xlsx,CSV 是 UTF-8 BOM,WPS/Excel 都正常 |
商品 ID 变成 6.1E+11 |
单元格被识别成数字 | 已处理;自己二次加工时记得转字符串 |
六、边界说清楚
- 能取:商品公开信息(标题、价格、库存、SKU、店铺、图片)。这就是选品、比价、铺货素材要用的全部。
- 不能取:买家信息、订单数据、需要登录才可见的内容。这些要走商家授权,不在这个脚本范围内。
- 别做的事:把频率拉到极限、拿数据做整站搬运。控制并发、加缓存、只取自己业务需要的字段,是能被长期容忍的前提。
七、文件与下一步
配套脚本 1688_batch_export.py,纯标准库实现(openpyxl 可选),已包含:
| 能力 | 参数 |
|---|---|
| 批量读入 | 文件 / 多个链接 / 纯 ID 混写,自动去重 |
| 并发控制 | --workers 3(默认 3) |
| 断点续跑 | 默认开,--cache xxx.db 指定缓存文件 |
| 强制重抓 | --refresh |
| 主图下载 | --images |
| 输出 | --out 文件名 → .xlsx + .csv + _失败.csv |
后续想扩展,两个方向最实用:
- 加 SKU 明细 sheet:把每个规格的价格、库存铺平成行,做阶梯报价时直接算;
- 接定时任务:每天早八点跑一次,价格变动超过 5% 的标红——那就从“导表工具”变成“价格监控”了。
结语
手动复制的问题从来不是“慢”,而是慢还不准:价格看错档、规格抄漏行、图片存成缩略图,错一处就要返工。
把这些重复动作交给脚本,把判断留给自己——哪个款值得跟、哪个价能压、哪个供应商靠谱,这些才是人该干的事。