当前位置: 首页 > news >正文

唯品会口红数据采集:双请求策略与JSON数据爬取实战

目录

引言

项目目标

效果展示

网站抓包分析过程

抓包分析步骤详解

步骤1:开启开发者工具

步骤2:识别数据接口

步骤3:分析请求详情

步骤4:认证机制分析

步骤5:构建完整请求流程

关键发现

需求分析

主要需求:

技术需求:

实现步骤

步骤1:环境准备和库导入

步骤2:Excel工作表初始化

步骤3:请求头配置和会话初始化

步骤4:Cookies配置

步骤5:API接口配置

步骤6:分页数据采集策略

步骤7:第一次请求参数配置

步骤8:发送第一次请求和获取商品ID列表

步骤9:商品ID分批处理策略

步骤10:第二次请求参数配置

步骤11:发送第二次请求和解析商品详情

步骤12:商品基本信息提取

步骤13:价格信息提取

步骤14:商品属性信息提取

步骤15:详情页链接构建

步骤16:数据保存和输出

步骤17:错误处理和资源清理

完整代码

技术深度解析

抓包分析技术要点

双请求架构优势

JSONP数据处理技术

智能分批策略

健壮的数据提取

详情页链接构建

应用场景与价值

法律和道德声明

技术总结


引言

在时尚美妆电商蓬勃发展的今天,唯品会作为中国领先的品牌特卖电商平台,汇聚了众多国内外知名美妆品牌。其中,口红作为美妆行业的明星品类,具有极高的市场关注度和研究价值。与传统的单次请求数据采集不同,本项目通过分析唯品会独特的双请求API架构,实现了高效、稳定的口红商品数据采集系统。

唯品会平台采用了复杂的数据加载机制,需要先获取商品ID列表,再通过二次请求获取详细商品信息。这种架构设计既保证了数据的安全性,又提升了用户体验。本项目通过深入分析这一机制,构建了完整的数据采集解决方案。

在数据采集过程中,我们严格遵守相关法律法规和平台使用条款,仅将数据用于技术学习和市场研究,尊重平台的数据安全和商家隐私。

项目目标

本项目旨在构建一个高效的唯品会平台口红数据采集系统,能够自动获取平台上的商品详细信息,并按标准化格式保存为可分析的数据文件。

具体目标包括:

  • 分析唯品会平台的双请求API接口结构

  • 配置完整的请求头和认证参数

  • 实现商品ID列表获取与详细数据采集的分离处理

  • 处理JSONP格式的数据响应

  • 提取商品标题、品牌、价格、属性等多个维度的关键指标

  • 处理分页加载和大批量数据获取机制

  • 构建完整的商品详情页链接

  • 将处理后的数据保存为结构化Excel文件

效果展示

网站抓包分析过程

抓包分析步骤详解

步骤1:开启开发者工具

首先打开唯品会网站,按F12键打开浏览器开发者工具:

  1. 打开唯品会官网:https://www.vip.com

  2. 按F12打开开发者工具

  3. 点击"Network"(网络)选项卡

  4. 在搜索框中输入"口红"开始搜索

  5. 刷新页面开始记录网络请求

步骤2:识别数据接口

在网站中浏览商品列表,观察网络请求的变化:

  1. 筛选XHR/Fetch请求:在筛选器中输入XHR或Fetch,过滤出数据接口

  2. 观察请求模式:注意观察在翻页或滚动加载时出现的重复请求模式

  3. 识别关键接口:发现两个关键接口:

    • 商品ID列表接口:/vips-mobile/rest/shopping/pc/search/product/rank

    • 商品详情接口:/vips-mobile/rest/shopping/pc/product/module/list/v2

步骤3:分析请求详情

点击具体的请求,查看详细信息:

第一次请求(商品ID列表)分析:

请求头分析:

GET /vips-mobile/rest/shopping/pc/search/product/rank?callback=getMerchandiseIds&app_name=shop_pc&... HTTP/1.1
Host: mapi-pc.vip.com
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Referer: https://category.vip.com/

请求参数分析:

callback: getMerchandiseIds
app_name: shop_pc
app_version: 4.0
keyword: 口红
pageOffset: 0
batchSize: 120

响应数据分析:

getMerchandiseIds({"data": {"products": [{"pid": "6920871310745952780","brandId": "1710621388"}]}
})

第二次请求(商品详情)分析:

请求参数分析:

callback: getMerchandiseDroplets1
app_name: shop_pc
productIds: 6920871310745952780,6920871310745952781,...
extParams: {"stdSizeVids":"","preheatTipsVer":"3","couponVer":"v2",...}

响应数据分析:

getMerchandiseDroplets1({"data": {"products": [{"title": "迪奥烈艳蓝金唇膏","brandShowName": "Dior迪奥","price": {"salePrice": "350.00","marketPrice": "450.00"},"attrs": [{"name": "颜色", "value": "999正红色"},{"name": "质地", "value": "丝绒"}],"productId": "6920871310745952780","brandId": "1710621388"}]}
})
步骤4:认证机制分析

通过分析请求参数,发现唯品会平台采用了多种认证机制:

  1. 用户身份认证:user_id、mars_cid等用户标识参数

  2. API密钥验证:api_key字段,用于接口访问权限控制

  3. 时间戳防重放:_参数,使用当前时间戳防止请求重放

  4. 令牌验证:tfs_fp_token,前端生成的指纹令牌

  5. 区域验证:fdc_area_id、province_id等区域标识参数

步骤5:构建完整请求流程

基于抓包分析,构建完整的Python双请求流程:

# 第一次请求获取商品ID列表
response1 = requests.get(url1, headers=headers, cookies=cookies, params=params1)
product_ids = extract_product_ids(response1.text)
​
# 第二次请求获取商品详细信息
response2 = requests.get(url2, headers=headers, cookies=cookies, params=params2)
product_details = extract_product_details(response2.text)

关键发现

通过抓包分析,我们获得了以下重要信息:

  1. 双请求架构:唯品会采用先获取ID列表,再获取详情的双请求机制

  2. 数据接口

    • ID列表接口:https://mapi-pc.vip.com/vips-mobile/rest/shopping/pc/search/product/rank

    • 详情接口:https://mapi-pc.vip.com/vips-mobile/rest/shopping/pc/product/module/list/v2

  3. 请求方法:GET

  4. 数据格式:JSONP格式的响应,需要正则提取

  5. 分页机制:通过pageOffset和batchSize控制分页,每页120个商品

  6. 数据分批:详情请求需要将商品ID分批,每批最多50个

需求分析

唯品会网站采用了复杂的双请求API架构,需要正确的请求参数和认证信息才能获取数据。

主要需求:

  • 配置完整的请求头和认证参数

  • 实现双请求策略:先获取商品ID列表,再获取详细信息

  • 处理JSONP格式响应,使用正则表达式提取JSON数据

  • 解析复杂的嵌套JSON结构提取商品信息

  • 处理分页加载和大批量数据获取机制

  • 构建商品详情页链接

  • 提取多个维度的商品信息

技术需求:

  • 使用requests库发送HTTP请求

  • 使用re库处理JSONP响应格式

  • 使用json库处理数据格式

  • 处理复杂的分页和分批逻辑

  • 完善的错误处理和数据处理机制

实现步骤

步骤1:环境准备和库导入

首先导入必要的Python库,为项目提供基础技术支持。

import requests
import re
import json
import time
from openpyxl import Workbook

详细说明:

  • requests 提供HTTP请求功能,能够发送GET请求获取数据

  • re 提供正则表达式功能,用于处理JSONP格式响应

  • json 提供JSON数据处理功能

  • time 提供时间戳生成功能

  • openpyxl 用于Excel文件操作和数据存储,支持大规模数据导出

步骤2:Excel工作表初始化

创建Excel工作表并设置专业的表头结构,覆盖商品分析的各个维度。

# 创建excel工作表
wb = Workbook()
# 获取活动工作表
ws = wb.active
# 设置表头
ws.append(['商品标题', '品牌展会名称', '销售价格', '市场价', '其他信息', "详情页链接"])

详细说明:

  • 使用Workbook()创建新的Excel工作簿

  • ws.active获取默认的工作表

  • ws.append()设置详细的表头字段,涵盖商品基本信息、价格、品牌等关键指标

  • 表头设计考虑了美妆商品的特有属性,如品牌信息和详情页链接

步骤3:请求头配置和会话初始化

基于抓包分析结果,精心配置请求头参数,包含完整的认证信息。

headers = {"Accept": "*/*","Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6","Connection": "keep-alive","Referer": "https://category.vip.com/","Sec-Fetch-Dest": "script","Sec-Fetch-Mode": "no-cors","Sec-Fetch-Site": "same-site","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0","sec-ch-ua": "\"Chromium\";v=\"142\", \"Microsoft Edge\";v=\"142\", \"Not_A Brand\";v=\"99\"","sec-ch-ua-mobile": "?0","sec-ch-ua-platform": "\"Windows\""
}

详细说明:

  • 配置完整的请求头信息,模拟真实浏览器行为

  • Sec-Fetch-*系列头信息表明请求的上下文和目的

  • Referer设置为搜索页面的URL,确保请求的合法性

  • User-Agent标识浏览器类型和版本,避免被识别为爬虫

步骤4:Cookies配置

配置必要的cookies信息,维持会话状态和用户身份。

cookies1 = {......}

详细说明:

  • 配置完整的cookies信息,包含用户身份认证令牌

  • PASSPORT_ACCESS_TOKEN是用户登录凭证,对于访问受限资源至关重要

  • tfs_fp_token是前端生成的指纹令牌,用于反爬虫验证

  • 这些cookies对于维持会话状态和通过身份验证至关重要

步骤5:API接口配置

配置数据接口的URL地址。

url = "https://mapi-pc.vip.com/vips-mobile/rest/shopping/pc/search/product/rank"

详细说明:

  • 通过浏览器开发者工具分析找到数据API接口

  • URL为唯品会搜索数据接口地址

  • 这种直接调用API的方式比页面解析更高效

步骤6:分页数据采集策略

实现智能的分页数据采集,通过外层循环控制页码。

for page in range(0, 6):pageOffset = page * 120print(f"正在爬取第{page + 1}页的数据内容")

详细说明:

  • 循环控制页码(0-5页),对应1-6页的实际显示

  • pageOffset计算偏移量,唯品会使用偏移量而非页码进行分页

  • 每页获取120个商品,适合大规模数据采集

  • 实时打印采集进度,提供操作反馈

步骤7:第一次请求参数配置

基于抓包分析,配置获取商品ID列表的请求参数。

params = {"callback": "getMerchandiseIds","app_name": "shop_pc","app_version": "4.0","warehouse": "VIP_NH","fdc_area_id": "104104101","client": "pc","mobile_platform": "1","province_id": "104104","api_key": "70f71280d5d547b2a7bb370a529aeea1","user_id": "645762488","mars_cid": "1762691744964_5f9e9bc0bae26551c563c283cb2a12bb","wap_consumer": "b","is_default_area": "1","standby_id": "nature","keyword": "口红","lv3CatIds": "","lv2CatIds": "","lv1CatIds": "","brandStoreSns": "","props": "","priceMin": "","priceMax": "","vipService": "ch11","sort": "0","pageOffset": pageOffset,"channelId": "1","gPlatform": "PC","batchSize": "120","tfs_fp_token": "BhIPr/K3uf5k4idKwcFfrUJFayPSF6qauzCjnIy+/5sBJdqdG4knl1kOMMs5UECqq3E7QzU/8nqoF16haA5KDXg==","_": str(int(time.time() * 1000))
}

详细说明:

  • callback指定JSONP回调函数名

  • keyword指定搜索关键词为"口红"

  • pageOffsetbatchSize控制分页,每页120个商品

  • api_key是API访问密钥,通过抓包获取

  • tfs_fp_token是重要的反爬虫令牌

  • _参数使用当前时间戳,防止请求缓存

步骤8:发送第一次请求和获取商品ID列表

发送GET请求获取JSONP格式的商品ID数据,并进行解析。

# 响应商品ID
respond_to_the_product_id = requests.get(url, headers=headers, cookies=cookies1, params=params)
# 初始化结果列表
res_products_id_list = []
# 定义时间戳
time_str = str(int(time.time() * 1000))
​
if respond_to_the_product_id.status_code == 200:respond_to_the_product_id_text = respond_to_the_product_id.textres = re.search(r'getMerchandiseIds\((.*?)\)', respond_to_the_product_id_text)if res:respond_to_the_product_id_json_data = json.loads(res.group(1))# 提取商品id列表products_id_list = respond_to_the_product_id_json_data["data"]["products"]# 遍历商品idfor num, products_id_item in enumerate(products_id_list):products_id = products_id_item["pid"]res_products_id_list.append(products_id)

详细说明:

  • 使用requests.get()发送GET请求获取数据

  • 检查响应状态码,确保请求成功

  • 使用正则表达式提取JSONP响应中的JSON数据

  • json.loads()解析JSON格式的数据

  • 从响应结构中提取商品ID列表

  • 遍历商品ID列表,收集所有商品ID

步骤9:商品ID分批处理策略

将获取的商品ID列表进行分批,为第二次请求做准备。

for node in range(1, 4):print(f'正在请求第{page+1}页的第{node}个数据包......')if node == 1:callback = "getMerchandiseDroplets1"products_id_str = ",".join(res_products_id_list[0:50]) + ","print(f"数据包数量:{len(res_products_id_list[0:50])}")elif node == 2:callback = "getMerchandiseDroplets2"products_id_str = ",".join(res_products_id_list[50:100]) + ","print(f"数据包数量:{len(res_products_id_list[50:100])}")else:callback = "getMerchandiseDroplets3"products_id_str = ",".join(res_products_id_list[100:120]) + ","print(f"数据包数量:{len(res_products_id_list[100:120])}")

详细说明:

  • 将每页120个商品ID分成3个批次进行请求

  • 第一批:前50个商品ID

  • 第二批:中间50个商品ID

  • 第三批:最后20个商品ID

  • 使用不同的callback函数名区分不同批次的响应

  • 将商品ID列表转换为逗号分隔的字符串格式

  • 实时打印每个批次的数据量,提供进度反馈

步骤10:第二次请求参数配置

配置获取商品详细信息的请求参数。

params2 = {"callback": callback,"app_name": "shop_pc","app_version": "4.0","warehouse": "VIP_NH","fdc_area_id": "104104101","client": "pc","mobile_platform": "1","province_id": "104104","api_key": "70f71280d5d547b2a7bb370a529aeea1","user_id": "645762488","mars_cid": "1762691744964_5f9e9bc0bae26551c563c283cb2a12bb","wap_consumer": "b","is_default_area": "1","productIds": products_id_str,"scene": "search","standby_id": "nature","extParams": "{\"stdSizeVids\":\"\",\"preheatTipsVer\":\"3\",\"couponVer\":\"v2\",\"exclusivePrice\":\"1\",\"iconSpec\":\"2x\",\"ic2label\":1,\"superHot\":1,\"bigBrand\":\"1\"}","context": "","tfs_fp_token": "BicZo59YoUtMcHQ2N7Oc1sob/0fqL22e7a4+g9t3NjweEyw2j8YasJyUJqQYo6G4H6qMfwaurjfuX1MjG3CygDA==","_": time_str
}

详细说明:

  • productIds参数包含批次的商品ID字符串

  • extParams包含扩展参数,以JSON字符串格式传递

  • scene参数指定请求场景为搜索

  • 使用与第一次请求相同的认证参数,确保会话一致性

  • callback参数根据批次动态设置

步骤11:发送第二次请求和解析商品详情

发送GET请求获取商品详细信息,并进行数据提取。

response2 = requests.get(url2, headers=headers, cookies=cookies2, params=params2)
if response2.status_code == 200:response_json_data = ""
​response_text = response2.text# 使用一个正则表达式匹配所有三种情况pattern = r'getMerchandiseDroplets\d+\(\s*(\{.*\})\s*\)'res = re.search(pattern, response_text)
​if res:response_json_data = json.loads(res.group(1))else:print('正则匹配失败')continue

详细说明:

  • 发送第二次请求获取商品详细信息

  • 使用动态正则表达式匹配不同批次的JSONP响应

  • json.loads()解析JSON格式的商品数据

  • 处理正则匹配失败的情况,确保程序健壮性

步骤12:商品基本信息提取

从JSON响应中提取商品的基本标识信息。

if response_json_data:# 商品列表products_list = response_json_data["data"]["products"]if products_list:print(f"获取到商品数目为:{len(products_list)}")# 遍历商品列表for products_item in products_list:products_item_dict = {}# 商品标题title = products_item["title"]products_item_dict["商品标题"] = title if title else "无"# 品牌展会名称brandShowName = products_item["brandShowName"]products_item_dict["品牌展会名称"] = brandShowName if brandShowName else "无"

详细说明:

  • 从JSON结构中提取商品信息列表

  • 验证数据列表是否为空,避免处理无效数据

  • 为每个商品创建字典对象存储信息

  • 提取商品标题和品牌名称,这是美妆商品的核心标识

  • 设置安全检查,为可能缺失的字段提供默认值

步骤13:价格信息提取

提取商品的销售价格和市场价信息。

            # 销售价格salePrice = products_item["price"]["salePrice"]products_item_dict["销售价格"] = salePrice if salePrice else "无"# 市场价marketPrice = products_item["price"]["marketPrice"]products_item_dict["市场价"] = marketPrice if marketPrice else "无"

详细说明:

  • 从嵌套的价格结构中提取销售价格和市场价

  • 销售价格是唯品会的特卖价格

  • 市场价是商品的参考原价

  • 价格信息对于价格分析和优惠力度计算很重要

步骤14:商品属性信息提取

提取商品的详细属性信息。

            # 其他信息attrs = products_item.get("attrs", "")# 初始化其他信息列表attrs_list = []if attrs:for attr in attrs:name = attr["name"]value = attr["value"]if name and value:attrs_list.append(name + ":" + value)else:attrs_list.append("无")# 其他信息字符串attrs_str = "---".join(attrs_list)products_item_dict["其他信息"] = attrs_str if attrs_str else "无"

详细说明:

  • 提取商品的属性列表,包含颜色、质地等美妆商品特有属性

  • 遍历属性列表,格式化每个属性信息

  • 使用分隔符连接多个属性,便于存储和分析

  • 处理属性为空的情况,提供默认值

  • 这种处理方式能够有效提取复杂的商品属性信息

步骤15:详情页链接构建

构建商品的详情页链接。

            # 获取商品idproductId = products_item["productId"]# 获取品牌idbrandId = products_item["brandId"]# 构建详情页链接https://www.vipglobal.hk/detail-1710621388-6920871310745952780.htmlinfo_link = f"https://www.vipglobal.hk/detail-{brandId}-{productId}.html"products_item_dict["详情页链接"] = info_link if info_link else "无"

详细说明:

  • 从商品数据中提取商品ID和品牌ID

  • 根据唯品会的URL规则构建详情页链接

  • 详情页链接提供了查看商品完整信息的入口

  • 这种动态构建链接的方式适用于所有商品

步骤16:数据保存和输出

将处理完成的商品数据保存到Excel文件。

            print(products_item_dict)ws.append([products_item_dict['商品标题'],products_item_dict['品牌展会名称'],products_item_dict['销售价格'],products_item_dict['市场价'],products_item_dict['其他信息'],products_item_dict["详情页链接"]])

详细说明:

  • 实时打印采集到的数据,提供进度反馈

  • 使用ws.append()将数据写入Excel行

  • 按表头顺序组织字段数据,确保数据结构一致性

  • 完整的字段映射确保数据准确存储

步骤17:错误处理和资源清理

处理请求失败的情况,完成数据采集后保存文件。

    else:print("请求失败,程序退出......")quit()
else:print("请求失败,程序退出")quit()
wb.save("唯品会口红数据.xlsx")
print("数据保存完毕......")

详细说明:

  • 处理请求失败的情况,提供错误提示并安全退出

  • 使用wb.save()保存完整的Excel文件

  • 文件命名为"唯品会口红数据.xlsx",清晰标识数据来源

  • 提供完成提示,确认数据保存成功

完整代码

# 爬取唯品会口红数据
import requests
import re
import json
import time
from openpyxl import Workbook
​
# 创建excel工作表
wb = Workbook()
# 获取活动工作表
ws = wb.active
# 设置表头
ws.append(['商品标题', '品牌展会名称', '销售价格', '市场价', '其他信息', "详情页链接"])
​
headers = {"Accept": "*/*","Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6","Connection": "keep-alive","Referer": "https://category.vip.com/","Sec-Fetch-Dest": "script","Sec-Fetch-Mode": "no-cors","Sec-Fetch-Site": "same-site","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0","sec-ch-ua": "\"Chromium\";v=\"142\", \"Microsoft Edge\";v=\"142\", \"Not_A Brand\";v=\"99\"","sec-ch-ua-mobile": "?0","sec-ch-ua-platform": "\"Windows\""
}
cookies1 = {......}
url = "https://mapi-pc.vip.com/vips-mobile/rest/shopping/pc/search/product/rank"
for page in range(0, 6):pageOffset = page * 120print(f"正在爬取第{page + 1}页的数据内容")params = {"callback": "getMerchandiseIds","app_name": "shop_pc","app_version": "4.0","warehouse": "VIP_NH","fdc_area_id": "104104101","client": "pc","mobile_platform": "1","province_id": "104104","api_key": "70f71280d5d547b2a7bb370a529aeea1","user_id": "645762488","mars_cid": "1762691744964_5f9e9bc0bae26551c563c283cb2a12bb","wap_consumer": "b","is_default_area": "1","standby_id": "nature","keyword": "口红","lv3CatIds": "","lv2CatIds": "","lv1CatIds": "","brandStoreSns": "","props": "","priceMin": "","priceMax": "","vipService": "ch11","sort": "0","pageOffset": pageOffset,"channelId": "1","gPlatform": "PC","batchSize": "120","tfs_fp_token": "BhIPr/K3uf5k4idKwcFfrUJFayPSF6qauzCjnIy+/5sBJdqdG4knl1kOMMs5UECqq3E7QzU/8nqoF16haA5KDXg==","_": str(int(time.time() * 1000))}"""第一次请求:获取商品id列表一次获取120个商品id,由于第二次的参数里面携带了这些"""# 响应商品IDrespond_to_the_product_id = requests.get(url, headers=headers, cookies=cookies1, params=params)# 初始化结果列表res_products_id_list = []# 定义时间戳time_str = str(int(time.time() * 1000))
​if respond_to_the_product_id.status_code == 200:respond_to_the_product_id_text = respond_to_the_product_id.textres = re.search(r'getMerchandiseIds\((.*?)\)', respond_to_the_product_id_text)if res:respond_to_the_product_id_json_data = json.loads(res.group(1))# 提取商品id列表products_id_list = respond_to_the_product_id_json_data["data"]["products"]# 遍历商品idfor num, products_id_item in enumerate(products_id_list):products_id = products_id_item["pid"]res_products_id_list.append(products_id)# print(res_products_id_list)for node in range(1, 4):print(f'正在请求第{page+1}页的第{node}个数据包......')if node == 1:callback = "getMerchandiseDroplets1"products_id_str = ",".join(res_products_id_list[0:50]) + ","print(f"数据包数量:{len(res_products_id_list[0:50])}")elif node == 2:callback = "getMerchandiseDroplets2"products_id_str = ",".join(res_products_id_list[50:100]) + ","print(f"数据包数量:{len(res_products_id_list[50:100])}")else:callback = "getMerchandiseDroplets3"products_id_str = ",".join(res_products_id_list[100:120]) + ","print(f"数据包数量:{len(res_products_id_list[100:120])}")# print(products_id_str)"""发送第二次请求:获取商品信息内容一页数据分为3个数据包,第一个50,第二个50,第三个20"""cookies2 = {......}url2 = "https://mapi-pc.vip.com/vips-mobile/rest/shopping/pc/product/module/list/v2"params2 = {"callback": callback,"app_name": "shop_pc","app_version": "4.0","warehouse": "VIP_NH","fdc_area_id": "104104101","client": "pc","mobile_platform": "1","province_id": "104104","api_key": "70f71280d5d547b2a7bb370a529aeea1","user_id": "645762488","mars_cid": "1762691744964_5f9e9bc0bae26551c563c283cb2a12bb","wap_consumer": "b","is_default_area": "1","productIds": products_id_str,"scene": "search","standby_id": "nature","extParams": "{\"stdSizeVids\":\"\",\"preheatTipsVer\":\"3\",\"couponVer\":\"v2\",\"exclusivePrice\":\"1\",\"iconSpec\":\"2x\",\"ic2label\":1,\"superHot\":1,\"bigBrand\":\"1\"}","context": "","tfs_fp_token": "BicZo59YoUtMcHQ2N7Oc1sob/0fqL22e7a4+g9t3NjweEyw2j8YasJyUJqQYo6G4H6qMfwaurjfuX1MjG3CygDA==","_": time_str}response2 = requests.get(url2, headers=headers, cookies=cookies2, params=params2)if response2.status_code == 200:response_json_data = ""
​response_text = response2.text# 使用一个正则表达式匹配所有三种情况pattern = r'getMerchandiseDroplets\d+\(\s*(\{.*\})\s*\)'res = re.search(pattern, response_text)
​if res:# print('正则匹配结果',res.group(1))response_json_data = json.loads(res.group(1))# print('json字符串转python的字典结果',response_json_data)else:print('正则匹配失败')continueif response_json_data:
​# 商品列表products_list = response_json_data["data"]["products"]if products_list:print(f"获取到商品数目为:{len(products_list)}")# 遍历商品列表for products_item in products_list:products_item_dict = {}# 商品标题title = products_item["title"]products_item_dict["商品标题"] = title if title else "无"# 品牌展会名称brandShowName = products_item["brandShowName"]products_item_dict["品牌展会名称"] = brandShowName if brandShowName else "无"# 销售价格salePrice = products_item["price"]["salePrice"]products_item_dict["销售价格"] = salePrice if salePrice else "无"# 市场价marketPrice = products_item["price"]["marketPrice"]products_item_dict["市场价"] = marketPrice if marketPrice else "无"# 其他信息attrs = products_item.get("attrs", "")# 初始化其他信息列表attrs_list = []if attrs:for attr in attrs:name = attr["name"]value = attr["value"]if name and value:attrs_list.append(name + ":" + value)else:attrs_list.append("无")# 其他信息字符串attrs_str = "---".join(attrs_list)products_item_dict["其他信息"] = attrs_str if attrs_str else "无"# 获取商品idproductId = products_item["productId"]# 获取品牌idbrandId = products_item["brandId"]# 构建详情页链接https://www.vipglobal.hk/detail-1710621388-6920871310745952780.htmlinfo_link = f"https://www.vipglobal.hk/detail-{brandId}-{productId}.html"products_item_dict["详情页链接"] = info_link if info_link else "无"print(products_item_dict)ws.append([products_item_dict['商品标题'],products_item_dict['品牌展会名称'],products_item_dict['销售价格'],products_item_dict['市场价'],products_item_dict['其他信息'],products_item_dict["详情页链接"]])
​else:print("请求失败,程序退出......")quit()else:print("正则无法匹配")else:print("请求失败,程序退出")quit()
wb.save("唯品会口红数据.xlsx")
print("数据保存完毕......")

技术深度解析

抓包分析技术要点

通过抓包分析,我们掌握了以下关键技术点:

  1. 双请求架构识别:通过观察网络请求顺序,识别出唯品会独特的先ID后详情的双请求机制

  2. JSONP响应处理:分析JSONP格式的响应,使用正则表达式提取有效JSON数据

  3. 认证机制分析:分析复杂的认证参数,包括API密钥、用户标识、指纹令牌等

  4. 分页机制理解:识别基于偏移量的分页机制,而非传统的页码分页

  5. 数据分批策略:理解商品ID分批请求的设计原理和实现方式

双请求架构优势

与传统的单次请求相比,唯品会的双请求架构具有显著优势:

# 第一次请求:获取商品ID列表
response1 = requests.get(url1, params=params1)
product_ids = extract_ids(response1.text)
​
# 第二次请求:获取商品详细信息  
response2 = requests.get(url2, params=params2)
product_details = extract_details(response2.text)
  • 数据分离:ID列表和详细信息分离,降低单次请求的数据量

  • 灵活性:可以根据需要选择获取哪些商品的详细信息

  • 性能优化:减少不必要的数据传输,提升响应速度

  • 错误恢复:单个商品详情获取失败不影响其他商品

JSONP数据处理技术

唯品会采用JSONP格式返回数据,需要特殊处理:

pattern = r'getMerchandiseDroplets\d+\(\s*(\{.*\})\s*\)'
res = re.search(pattern, response_text)
if res:response_json_data = json.loads(res.group(1))
  • 正则表达式匹配:使用动态正则匹配不同回调函数的JSONP响应

  • JSON提取:从JSONP包装中提取纯JSON数据

  • 错误处理:处理正则匹配失败的情况,确保程序稳定性

智能分批策略

针对唯品会的限制,实现了智能的商品ID分批:

for node in range(1, 4):if node == 1:products_id_str = ",".join(res_products_id_list[0:50]) + ","elif node == 2:products_id_str = ",".join(res_products_id_list[50:100]) + ","else:products_id_str = ",".join(res_products_id_list[100:120]) + ","
  • 批量限制:每批次最多50个商品ID

  • 灵活分割:根据实际商品数量动态分割

  • 进度跟踪:实时显示每个批次的处理进度

  • 容错处理:处理商品数量不足的情况

健壮的数据提取

安全的数据提取策略确保程序稳定性:

title = products_item["title"]
products_item_dict["商品标题"] = title if title else "无"
  • 直接访问JSON字段,效率高

  • 使用条件判断处理可能为空的字段

  • 为所有字段提供合理的默认值

  • 确保程序在数据不完整时仍能正常运行

详情页链接构建

动态构建商品详情页链接:

info_link = f"https://www.vipglobal.hk/detail-{brandId}-{productId}.html"
  • 基于品牌ID和商品ID构建标准URL

  • 适用于所有商品的通用链接格式

  • 提供查看商品完整信息的入口

应用场景与价值

这个唯品会口红数据采集系统可以应用于多个重要场景:

  1. 美妆市场分析:分析口红市场的品牌分布、价格区间和产品趋势

  2. 竞品监控:跟踪竞争对手的产品策略和价格变动

  3. 价格策略研究:研究唯品会的特卖价格策略和折扣力度

  4. 品牌影响力分析:分析各品牌在唯品会平台的展示和销售情况

  5. 产品选品参考:为美妆零售商提供产品选品的数据支持

  6. 消费者偏好研究:通过商品属性分析消费者对口红色号、质地的偏好

  7. 学术研究:为美妆电商和消费者行为研究提供真实的数据支持

法律和道德声明

在使用本数据采集程序时,请务必严格遵守以下原则:

  1. 遵守法律法规:严格遵循《网络安全法》、《电子商务法》及相关互联网监管规定

  2. 尊重平台规则:严格遵守唯品会平台的使用条款和robots.txt协议

  3. 控制访问频率:合理设置请求间隔,不对平台服务器造成压力

  4. 合法使用数据:仅将数据用于技术学习和市场研究,不用于商业竞争

  5. 尊重知识产权:承认数据来源,不将爬取数据用于商业用途

  6. 隐私保护:不采集、使用或传播涉及用户隐私的信息

  7. 商业道德:不利用获取的数据进行不正当竞争或损害平台利益的行为

技术总结

本文详细介绍了通过双请求API接口爬取唯品会平台口红数据的完整技术方案,特别强调了抓包分析和JSONP数据处理的重要性。通过这个项目,我们掌握了以下核心技术:

  1. 复杂架构分析:分析并理解唯品会的双请求API架构

  2. JSONP处理技术:使用正则表达式处理JSONP格式的响应数据

  3. 分批请求策略:实现智能的商品ID分批和详情获取

  4. 认证机制处理:配置复杂的用户认证和API访问参数

  5. 分页采集机制:实现基于偏移量的分页数据采集

  6. 数据标准化:将复杂的商品数据保存为可分析的标准格式

与传统的单次请求采集相比,这种基于双请求调用的方案具有独特优势:

  • 适应现代电商平台的复杂数据加载机制

  • 更高的数据获取效率和稳定性

  • 更好的错误恢复能力

  • 适用于采用先进前端技术的电商平台

关于认证参数的重要说明:

虽然在当前实现中我们直接使用了抓包获取的认证参数,但在实际生产环境中,需要理解这些参数的生成机制:

# 认证参数生成伪代码(示例)
def generate_auth_params(user_id, api_key):timestamp = int(time.time() * 1000)fingerprint = generate_fingerprint()return {"user_id": user_id,"api_key": api_key,"tfs_fp_token": fingerprint,"_": timestamp}

在实际应用中,应该分析认证参数的生成逻辑,实现自动化的参数生成,而不是硬编码固定的参数值。

抓包分析是现代网络数据采集的关键技能,通过深入分析网络请求,我们可以:

  • 理解网站的数据传输架构

  • 识别必要的认证和反爬虫机制

  • 找到最高效的数据获取方式

  • 优化数据采集的性能和稳定性

掌握这种基于抓包分析和API调用的数据采集技术,在电子商务和美妆市场分析领域具有重要价值。无论是美妆品牌商、市场研究人员还是电商分析师,都能够通过这种技术获取宝贵的市场洞察。

在网络数据采集技术的学习道路上,我们既要追求技术精进,更要坚守法律和道德底线。特别是在商业数据采集领域,必须确保技术的合法合规使用,尊重数据知识产权和市场秩序。


注意:本文仅供技术学习交流,实际应用中请严格遵守相关法律法规和平台使用条款。所有数据采集行为应仅限于个人学习研究,不得用于任何商业用途或竞争行为。商业决策请以官方渠道信息为准。

http://www.dtcms.com/a/594898.html

相关文章:

  • 修改文件权限--- chmod ,vi/vim,yum-软件包管理器,systemctl管理系统服务
  • 网站动效是代码做的吗全国信息企业公示系统
  • 个人网站制作体会长沙seo推广营销
  • thinkphp网站开发房产官方网站
  • 网站建设的预算费用番禺人才网最新招聘市场在哪里?
  • 谷歌收录网站wordpress 代码编写
  • 建立什么样的网站好梅州网站优化公司
  • 中国网站优化哪家好北京响应式网站建设费用
  • 东莞厚街网站建设百度网站怎么做的赚钱吗
  • wordpress网站白屏手表网站功能设计
  • 内蒙古网站设计360安全浏览器
  • 如何进入公司网站后台门户网站建设意见
  • 小学数学(二)资源合集
  • 小木桥建设网站电子商务网站设计与实现
  • 哪个网站可以做h5页面优秀交互设计app欣赏
  • Linux下程序设计综合实验报告——图书管理系统(黑龙江大学)
  • 网站公司的利润在哪里wordpress获取分类导航
  • 怎么看网站到期时间怎样建设VR网站
  • 公司做网站需要哪些专业网站设计公司行业
  • 两条n次B样条曲线(次数相同),已知分别的控制点和节点矢量,两条曲线G0连续,将合并成一条B样条曲线的方法
  • linux中使用docker安装MySQL
  • 我们来详细讲解一下 Linux 中 `crontab` 定时器的使用
  • 三合一网站系统建设银行内部网站
  • 做信息发布网站要多少钱百度搜索引擎优化详解
  • 网站内页没有排名网络软文是什么意思
  • 2025年上半年网络工程师基础知识真题及答案解析
  • 网站制作 网站开发fixed wordpress主题
  • 新公司建网站合肥网络推广策划方案
  • 建筑培训网站有哪些网站制作公司十强
  • 一步步实现 AI 模型调用:DeepSeek 深度对接实战全解析