1611 字
8 分钟
1688爬虫爬爬乐:抓包分析与Playwright实战
2026-01-11
...

前言#

上篇文章中,我尝试爬取闲鱼商品数据。本次来尝试爬取1688商品。 1688的 PC 端页面是一个典型的“混合渲染”迷宫。 起初我尝试用 Playwright 的常规方法 page.evaluate() 去读取页面上的全局变量,结果撞了墙:明明在浏览器控制台能看到的 window.context,脚本读出来却是 null。排查后发现,这是因为 1688 采用了复杂的闭包初始化和页面注水(Hydration)机制,导致 JS 执行时机难以把控。(应该吧)

耗费时间去调试 JS 执行时机并不划算,于是我转向了**“逆向抓包 + 正则”**的方案。本文将详细记录如何绕过浏览器 JS 执行,直接从网络层和源码层抓出我们需要的所有数据。

一、抓包:数据到底藏在哪?#

与闲鱼类似,1688 的数据源分为两块,我们需要分别击破: **动态数据(价格/库存)**走 API,**静态数据(属性/详情图)**埋在 HTML 源码里。

1. SKU 体系:mtop 协议监听#

SKU 数据(比如:红色-L码-100件-单价5元)不在 HTML 里,而是页面加载后通过 mtop 接口异步拉取的。 打开 F12 Network 面板,刷新页面,搜索 queryofferskuselectormodel,你会找到这个核心包:

1688抓包截图

接口特征mtop.1688.wosc.queryofferskuselectormodel

请求方式:GET (JSONP)

数据结构

  • skuPropsList:定义了规格维度(颜色、尺寸)和对应的缩略图。
  • skuMapOriginal:这是最关键的字典,Key 是规格组合(如 颜色:红色;尺码:L),Value 包含真实成交价(discountPrice)和实时库存(canBookCount)。

实战结论:不需要去逆向复杂的 Sign 签名来伪造请求,直接用 Playwright 做个”中间人”,监听并拦截浏览器发出的合法请求即可,这点和闲鱼的方式一样。

2. 属性与详情:HTML 里的捉迷藏#

商品的属性参数(如材质、品牌)和详情长图链接,藏在页面源码的一段硬编码脚本中:

源码截图

window.context = (function(b, d) { ... })(window.contextPath, {
"result": {
"data": {
"offerDetail": {
"featureAttributes": [...] // 想要的数据在这里
},
.....
"description": {
"detailUrl": "..." // 详情图 API 地址
}
}
}
});

常规爬虫会尝试等待页面加载完成后,通过 JS 读取 window.context。但在实测中,由于闭包写法和执行顺序问题或者包内容过于复杂,也许是我技术不够(悲,Playwright 经常拿不到这个对象,只能通过 html 正则获取。

详情图在本html页面有两个地方,这里只介绍一个地方,另外一个地方在上图末尾处(好像是,大伙自己找找吧)

详情图位置1

详情图位置2

详情图API调用后给出的也不是常规 json,同样使用正则获取即可。注意要转换为标准 URL。

实战结论:只要它存在于 HTML 源码中,我们就可以用正则表达式把它提取出来。

二、避坑指南:四大”雷点”#

在编写代码时,我遇到的几个问题,总结如下:

💥 雷点 1:JS 提取返回 Null#

现象data = await page.evaluate("() => window.context") 经常报错或返回空。

原因:页面 JS 执行环境复杂,变量未挂载或被混淆,或者无法准确定位位置。

解决:使用 page.content() 获取纯文本 HTML,直接上正则匹配。

💥 雷点 2:转义字符的干扰#

现象:提取出的图片链接无法访问,比如 https:\/\/cbu01...

原因:服务端返回的 JSON 数据经过了序列化转义。

解决:拿到字符串后,必须先做全局替换 .replace("\\", ""),还原成标准 URL。

💥 雷点 3:Cookie 必须固化#

现象:脚本运行几次后被重定向到登录页。

原因:1688 对未登录查看价格有严格限制,而且未登录数据包名貌似会发生变化,导致抓不到数据。

解决:首次人工扫码登录后保存 auth.json,我这里是专门做了个脚本用来登录保存。之后脚本直接加载 Session,不要每次都重新登录。

怎么四个雷点又只有三个呢(

## 三、Python 关键代码解析#

1. 正则提取(核心逻辑)#

直接绕过浏览器 JS 解析,从 HTML 源码中提取属性。

def extract_attributes_directly(html_content):
"""
直接正则匹配 featureAttributes 数组
"""
# 查找 "featureAttributes": [...] 结构,无视 JS 执行状态
pattern = r'"featureAttributes"\s*:\s*(\[\{.*?\}\])'
match = re.search(pattern, html_content, re.DOTALL)
attr_list = []
if match:
try:
# 拿到字符串直接转 JSON,干净利落
feature_attrs = json.loads(match.group(1))
for item in feature_attrs:
name = item.get("name")
val = item.get("value")
if name and val:
attr_list.append(f"{name}: {val}")
except:
pass
return attr_list

2. 流量监听器#

不主动请求 API,直接拦截 SKU 数据包。

async def on_response(response):
# 锁定 SKU 核心接口
if "queryofferskuselectormodel" in response.url and response.status == 200:
try:
text = await response.text()
# 清洗 JSONP 的括号 wrapper:callback(...)
if "(" in text and ")" in text:
text = text[text.find("(")+1 : text.rfind(")")]
json_data = json.loads(text)
# 解析 SKU 数据的逻辑...
parsed = parse_sku_packet(json_data)
if parsed:
data_container["skus"] = parsed
except:
pass
# 注册监听
page.on("response", on_response)

3. 详情图旁路下载#

拿到 detailUrl 后,由于详情图是放在阿里 CDN 中,无需鉴权,直接用 requests 下载图片即可。

# 1. 从源码正则提取 detailUrl
match = re.search(r'"detailUrl"\s*:\s*"(https?://.*?)"', page_content)
detail_url = match.group(1)
# 2. 旁路请求(不占用浏览器资源)
resp = requests.get(detail_url, headers=headers)
# 3. 正则提取所有图片链接
images = re.findall(r'(https?://[^"\'\\]+?\.(?:jpg|png|jpeg))', resp.text)
# 放入后台线程池下载

总结#

通过 “Playwright 监听动态 API” + “正则解析静态 HTML” 的混合架构,解决了 1688 PC 端数据采集的痛点。

实战效果

不用多说自己看图

实战效果1

实战效果2

IMPORTANT

出于各种因素考虑,本文及其后续爬虫文章不会放出完整代码,有需要的小伙伴自行测试编写即可。

题外话#

上个闲鱼的从项目起步到完成,只用了2个多小时(闲鱼大部分数据都是能明文找到位置),而1688环境更为复杂,从起步到完成花了快一天时间(还是有AI的情况下),属于是难度提升了不少。我也不是技术大牛,后续可能会尝试爬取淘宝,京东等,如果有其他实现方法欢迎邮箱联系交流学习。

法律声明

爬虫技术仅用于学习交流,请勿用于非法商业用途,并严格遵守平台 Robots 协议。

1688爬虫爬爬乐:抓包分析与Playwright实战
https://www.sakasa.cn/posts/pa1688/
作者
lastcyh
发布于
2026-01-11
许可协议
CC BY-NC-SA 4.0