什么值得买(SMZDM)作为国内知名消费决策平台,以 “优惠爆料、商品评测、消费指南” 为核心,其商品详情信息(如历史价格曲线、用户真实评测、优惠活动、品类推荐)对电商比价、消费决策、市场分析等场景具有重要价值。由于平台无公开官方 API,开发者需通过页面解析实现商品详情()的获取。本文系统讲解接口对接逻辑、技术实现、反爬应对及消费决策特有字段解析,帮助开发者构建稳定的商品详情获取系统。
item_get
一、接口基础认知(核心功能与场景)
核心功能值得买接口(非官方命名)通过商品 ID(
item_get)获取目标商品的全量信息,核心字段聚焦消费决策特性:
item_id
基础信息:商品 ID、标题(含规格)、主图(多图)、品牌、类目(如 “数码家电”“美妆个护”)、详情页 URL、来源平台(如京东、天猫)价格信息:当前价、历史最低价(含时间)、原价、优惠信息(如 “满减”“优惠券”)、价格趋势标签(如 “近期低价”)消费决策数据:用户评分(如 “4.8 分”)、评测数量、核心评价标签(如 “性价比高”“质感好”)、爆料次数商品特性:规格参数、优缺点总结(来自评测)、适用场景、同类推荐商品交易关联:购买链接(跳转至电商平台)、销量趋势、库存状态(部分商品)内容生态:热门评测文章、用户问答、社区讨论话题
典型应用场景
比价工具:获取 “iPhone 15” 的值得买历史低价与当前电商平台价格对比,辅助决策 “是否入手”消费趋势分析:跟踪 “空气炸锅” 的用户评分变化、核心评价标签,分析市场反馈优惠监控:监控 “春节礼盒” 的优惠活动(如优惠券、满减)及历史价格波动选品辅助:通过 “同类推荐” 和 “优缺点总结” 筛选高性价比商品
接口特性
内容驱动性:数据融合商品信息与用户生成内容(UGC),评价、评测字段占比高非官方性:无公开 API,依赖页面 HTML 解析,动态加载内容多(如历史价格、评价)反爬机制:包含 IP 限制(高频请求封锁)、User-Agent 校验、Cookie 验证(部分数据需登录)、请求频率监控平台跳转性:商品购买链接多跳转至第三方电商(京东、天猫等),自身不直接售卖
二、对接前置准备(环境与 URL 结构)
开发环境
开发语言:Python(推荐,适合快速处理 HTML 解析与反爬)核心库:
网络请求:(同步请求)、
requests(异步批量获取)页面解析:
aiohttp(静态 HTML 解析)、
BeautifulSoup(XPath 提取复杂结构)反爬工具:
lxml(随机 User-Agent)、
fake_useragent(代理 IP 池)数据处理:
proxy_pool(正则提取价格、评分)、
re(解析动态接口响应)、
json(处理历史价格曲线)
pandas
商品 ID 与 URL 结构值得买商品详情页 URL 格式为:,其中
https://www.smzdm.com/p/{item_id}/为商品唯一标识(纯数字,如
item_id)。示例:某品牌耳机详情页
1234567,商品 ID 为
https://www.smzdm.com/p/1234567/。
1234567
页面结构分析通过浏览器开发者工具(F12)分析详情页结构,核心数据位置:
静态数据:标题、主图、当前价格、来源平台等嵌入主页面 HTML(如
<h1 class="title">);动态数据:历史价格曲线、用户评价、评测文章等通过 AJAX 接口加载,接口含
<div class="price">(如
item_id);UGC 内容:用户评价、问答等常放在
https://www.smzdm.com/ajax/pc_product_history_price/?item_id={item_id}
<div class="comment-list">标签内,需单独解析。
<div class="qa-list">
三、接口调用流程(基于页面解析)
以 “获取某品牌扫地机器人商品详情” 为例,核心流程为URL 构建→主页面解析→动态接口补充→UGC 内容提取→数据结构化:
URL 与请求头构建
目标 URL:(替换
https://www.smzdm.com/p/{item_id}/为实际值);请求头:模拟浏览器行为,关键字段包括
item_id、
User-Agent、
Referer(部分历史价格数据需登录态):
Cookie
python
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
"Referer": "https://www.smzdm.com/",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Cookie": "sess=xxx; user_id=xxx; device_id=xxx" # 登录后从浏览器获取
}
主页面静态数据解析从主页面 HTML 中提取基础信息,重点关注消费决策字段:
| 字段 | 解析方式(CSS 选择器 / XPath) | 示例值 |
|---|---|---|
| 商品标题 | (CSS 选择器) |
“某品牌扫地机器人 扫拖一体 自动集尘” |
| 主图列表 | 的属性 |
|
| 当前价格 | 的文本(去除 “¥”) |
“2999.00”(元) |
| 原价 | 的文本(去除 “¥”) |
“3999.00”(元) |
| 来源平台 | 的文本 |
“京东” |
| 购买链接 | 的属性 |
|
| 用户评分 | 的文本 |
“4.7”(满分 5 分) |
动态数据补充(AJAX 接口)历史价格、评测数量等通过动态接口加载,无需复杂签名,直接调用即可:
历史价格接口示例:;响应示例(历史价格):
https://www.smzdm.com/ajax/pc_product_history_price/?item_id={item_id}
json
{
"data": {
"price_list": [
{"date": "2023-10-01", "price": 2999, "tag": "促销价"},
{"date": "2023-09-15", "price": 3299, "tag": "日常价"}
],
"lowest_price": 2799,
"lowest_date": "2023-06-18" # 618大促最低价
}
}
UGC 内容提取(评价与问答)用户评价和问答是值得买的核心价值数据,需从页面中解析:
评价列表解析示例:
python
# 提取前5条评价
comment_list = []
for comment in soup.select("div.comment-item")[:5]:
user_name = comment.select_one("div.user-name")?.text.strip() or ""
rating = comment.select_one("div.star")?.get("data-score") or "0" # 星级评分
content = comment.select_one("div.comment-content")?.text.strip() or ""
comment_list.append({
"user": user_name,
"rating": rating,
"content": content
})
数据整合与结构化合并静态、动态及 UGC 数据,形成标准化字典,突出消费决策特性:
python
standardized_data = {
"item_id": item_id,
"title": title,
"price": {
"current": current_price,
"original": original_price,
"history_lowest": {
"price": lowest_price,
"date": lowest_date
},
"price_trend": price_list, # 历史价格列表
"discount": discount_info # 优惠信息
},
"product": {
"brand": brand,
"specs": specs_dict, # 规格参数
"advantages": advantages, # 优点总结
"disadvantages": disadvantages # 缺点总结
},
"user_feedback": {
"score": score, # 综合评分
"comment_count": comment_count,
"comments": comment_list, # 精选评价
"qa_list": qa_list # 用户问答
},
"platform": {
"source": source_platform, # 来源平台(如京东)
"buy_url": buy_url # 购买链接
},
"related": {
"similar_items": similar_items, # 同类推荐
"reviews": review_articles # 评测文章
},
"images": image_list,
"url": detail_url
}
四、代码实现示例(Python)
以下是接口的完整实现,包含主页面解析、动态接口调用、UGC 内容提取及反爬处理:
item_get
import requests
import time
import random
import re
import json
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
from typing import Dict, List
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
class SmzdmItemApi:
def __init__(self, proxy_pool: List[str] = None, cookie: str = ""):
self.base_url = "https://www.smzdm.com/p/{item_id}/"
self.history_price_api = "https://www.smzdm.com/ajax/pc_product_history_price/" # 历史价格接口
self.qa_api = "https://www.smzdm.com/ajax/pc_ask_list/" # 问答接口
self.ua = UserAgent()
self.proxy_pool = proxy_pool # 代理池列表
self.cookie = cookie # 登录态Cookie(用于获取完整历史价格)
def _get_headers(self) -> Dict[str, str]:
"""生成随机请求头"""
headers = {
"User-Agent": self.ua.random,
"Referer": "https://www.smzdm.com/",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
}
if self.cookie:
headers["Cookie"] = self.cookie
return headers
def _get_proxy(self) -> Dict[str, str]:
"""随机获取代理"""
if self.proxy_pool and len(self.proxy_pool) > 0:
proxy = random.choice(self.proxy_pool)
return {"http": proxy, "https": proxy}
return None
def _clean_price(self, price_str: str) -> float:
"""清洗价格字符串(去除¥、逗号等)"""
if not price_str:
return 0.0
price_str = re.sub(r"[^d.]", "", price_str)
return float(price_str) if price_str else 0.0
def _parse_specs(self, spec_html) -> Dict[str, str]:
"""解析规格参数"""
specs = {}
if not spec_html:
return specs
spec_soup = BeautifulSoup(spec_html, "lxml")
for row in spec_soup.select("tr"):
th = row.select_one("th")
td = row.select_one("td")
if th and td:
specs[th.text.strip()] = td.text.strip()
return specs
def _parse_main_page(self, html: str) -> Dict[str, str]:
"""解析主页面基础信息"""
soup = BeautifulSoup(html, "lxml")
# 提取优缺点(来自评测总结)
advantages = [li.text.strip() for li in soup.select("div.advantage-list li")]
disadvantages = [li.text.strip() for li in soup.select("div.disadvantage-list li")]
return {
"title": soup.select_one("h1.title")?.text.strip() or "",
"images": [img.get("src") for img in soup.select("div.main-img img") if img.get("src")],
"price": {
"current": self._clean_price(soup.select_one("div.price-box .price")?.text or ""),
"original": self._clean_price(soup.select_one("div.price-box .origin-price")?.text or ""),
"discount": soup.select_one("div.coupon-info")?.text.strip() or ""
},
"product": {
"brand": soup.select_one("div.brand a")?.text.strip() or "",
"specs": self._parse_specs(str(soup.select_one("div.parameter-table"))),
"advantages": advantages,
"disadvantages": disadvantages
},
"user_feedback": {
"score": float(soup.select_one("div.score-box .score")?.text or "0"),
"comment_count": int(re.search(r"d+", soup.select_one("div.comment-tab .count")?.text or "0").group()) if soup.select_one("div.comment-tab .count") else 0
},
"platform": {
"source": soup.select_one("div.buy-link a")?.text.strip() or "",
"buy_url": soup.select_one("div.buy-link a")?.get("href") or ""
},
"related": {
"similar_items": [
{
"title": a.text.strip(),
"url": f"https://www.smzdm.com{a.get('href')}"
} for a in soup.select("div.similar-goods a")[:3]
]
}
}
def _parse_comments(self, html: str) -> List[Dict]:
"""解析用户评价"""
soup = BeautifulSoup(html, "lxml")
comments = []
for item in soup.select("div.comment-item")[:5]: # 取前5条
user = item.select_one("div.user-name")?.text.strip() or "匿名用户"
rating = item.select_one("div.star")?.get("data-score") or "0"
content = item.select_one("div.comment-content")?.text.strip() or ""
comments.append({
"user": user,
"rating": rating,
"content": content
})
return comments
def _fetch_dynamic_data(self, item_id: str, headers: Dict[str, str], proxy: Dict[str, str]) -> Dict:
"""调用动态接口获取历史价格和问答"""
dynamic_data = {
"price_trend": [],
"history_lowest": {"price": 0, "date": ""},
"qa_list": []
}
try:
# 1. 获取历史价格
price_params = {"item_id": item_id}
price_resp = requests.get(
self.history_price_api,
params=price_params,
headers=headers,
proxies=proxy,
timeout=10
)
price_data = price_resp.json()
if price_data.get("error_code") == 0 and "data" in price_data:
dynamic_data["price_trend"] = price_data["data"].get("price_list", [])
dynamic_data["history_lowest"] = {
"price": price_data["data"].get("lowest_price", 0),
"date": price_data["data"].get("lowest_date", "")
}
# 2. 获取用户问答(前3条)
qa_params = {"item_id": item_id, "page": 1, "size": 3}
qa_resp = requests.get(
self.qa_api,
params=qa_params,
headers=headers,
proxies=proxy,
timeout=10
)
qa_data = qa_resp.json()
if qa_data.get("error_code") == 0 and "data" in qa_data:
dynamic_data["qa_list"] = [
{
"question": item.get("ask_content", ""),
"answer": item.get("answer_content", "")
} for item in qa_data["data"].get("list", [])
]
except Exception as e:
print(f"动态数据获取失败: {str(e)}")
return dynamic_data
def item_get(self, item_id: str, timeout: int = 10) -> Dict:
"""
获取值得买商品详情
:param item_id: 商品ID(如1234567)
:param timeout: 超时时间
:return: 标准化商品数据
"""
try:
# 1. 主页面请求
url = self.base_url.format(item_id=item_id)
headers = self._get_headers()
proxy = self._get_proxy()
# 随机延迟,避免反爬
time.sleep(random.uniform(1.5, 3))
response = requests.get(
url=url,
headers=headers,
proxies=proxy,
timeout=timeout
)
response.raise_for_status()
main_html = response.text
# 2. 解析主页面数据
main_data = self._parse_main_page(main_html)
if not main_data["title"]:
return {"success": False, "error_msg": "商品不存在或已下架"}
# 3. 解析用户评价(主页面包含部分评价)
comments = self._parse_comments(main_html)
# 4. 获取动态数据(历史价格、问答)
dynamic_data = self._fetch_dynamic_data(item_id, headers, proxy)
# 5. 整合结果
result = {
"success": True,
"data": {
"item_id": item_id,** main_data,
"price": {
**main_data["price"],
"history_lowest": dynamic_data["history_lowest"],
"price_trend": dynamic_data["price_trend"]
},
"user_feedback": {** main_data["user_feedback"],
"comments": comments,
"qa_list": dynamic_data["qa_list"]
},
"update_time": time.strftime("%Y-%m-%d %H:%M:%S")
}
}
return result
except requests.exceptions.HTTPError as e:
if "403" in str(e):
return {"success": False, "error_msg": "触发反爬,建议更换代理或Cookie", "code": 403}
return {"success": False, "error_msg": f"HTTP错误: {str(e)}", "code": response.status_code}
except Exception as e:
return {"success": False, "error_msg": f"获取失败: {str(e)}", "code": -1}
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
# 使用示例
if __name__ == "__main__":
# 代理池(替换为有效代理)
PROXIES = [
"http://123.45.67.89:8888",
"http://98.76.54.32:8080"
]
# 登录态Cookie(从浏览器获取,用于完整历史价格)
COOKIE = "sess=xxx; user_id=xxx; device_id=xxx"
# 初始化API客户端
api = SmzdmItemApi(proxy_pool=PROXIES, cookie=COOKIE)
# 获取商品详情(示例item_id)
item_id = "1234567" # 替换为实际商品ID
result = api.item_get(item_id)
if result["success"]:
data = result["data"]
print(f"商品标题: {data['title']}")
print(f"价格: 当前¥{data['price']['current']} | 原价¥{data['price']['original']} | 历史最低¥{data['price']['history_lowest']['price']}({data['price']['history_lowest']['date']})")
print(f"来源平台: {data['platform']['source']} | 购买链接: {data['platform']['buy_url'][:50]}...")
print(f"用户评分: {data['user_feedback']['score']}分 | 评价数: {data['user_feedback']['comment_count']}条")
print(f"核心优点: {', '.join(data['product']['advantages'][:3])}")
print(f"核心缺点: {', '.join(data['product']['disadvantages'][:3])}")
print(f"精选评价1: {data['user_feedback']['comments'][0]['content'][:50]}...")
print(f"热门问答: {data['user_feedback']['qa_list'][0]['question'][:30]}? {data['user_feedback']['qa_list'][0]['answer'][:50]}...")
else:
print(f"获取失败: {result['error_msg']}(错误码: {result.get('code')})")
五、关键技术难点与解决方案
历史价格曲线解析(消费决策核心)
问题:历史价格是值得买的核心数据(如 “618 最低价”),但通过动态接口返回,未登录状态下可能获取不完整。解决方案:
携带登录态 Cookie 请求历史价格接口(),确保获取完整的价格曲线;对价格数据按日期排序,提取 “历史最低价” 及对应时间,辅助用户判断 “是否当前入手”;示例代码中
pc_product_history_price函数专门处理价格曲线,结构化输出便于趋势分析。
_fetch_dynamic_data
UGC 内容提取(评价与问答)
问题:用户评价、问答等 UGC 内容分散在页面不同位置,且包含大量冗余标签,提取纯净文本难度大。解决方案:
评价内容通过标签定位,过滤广告、表情符号等冗余信息(用正则
div.comment-item去除特殊字符);问答数据优先调用官方接口(
re.sub),减少页面解析复杂度;对长文本内容(如详细评测)进行截断处理,保留核心观点(如示例中取前 50 字)。
pc_ask_list
反爬机制对抗
问题:值得买对数据爬取限制严格,高频请求会触发 IP 封锁(403 错误),甚至要求验证码验证。解决方案:
代理 IP 轮换:使用高匿代理池,每 2-3 次请求切换 IP,优先选择存活时间≥10 分钟的代理;请求频率控制:单 IP 每分钟请求≤2 次,两次请求间隔 2-4 秒(模拟用户浏览节奏);Cookie 池策略:维护多个登录态 Cookie(通过不同账号获取),随机携带以降低单一账号风险;异常处理:若返回验证码页面,自动切换代理和 Cookie 重试(最多 2 次)。
平台跳转链接处理
问题:值得买商品购买链接多跳转至第三方电商(京东、天猫等),需确保链接有效性,避免 404 错误。解决方案:
解析的
div.buy-link a属性时,检查链接格式(如
href),过滤无效链接;对跳转链接进行标记(如 “来源:京东”),便于后续关联第三方平台数据;若链接失效(如商品下架),在结果中明确标记 “购买链接已失效”。
https://item.jd.com/
六、最佳实践与合规要点
系统架构设计采用 “轻量高频采集 + UGC 内容缓存” 架构,适配消费决策数据特性:
采集层:集成代理池、Cookie 池,控制单 IP 请求频率(≤2 次 / 分钟),避免触发反爬;解析层:分离基础数据(价格、标题)与 UGC 内容(评价、问答)解析逻辑,重点处理历史价格曲线;存储层:用 Redis 缓存热门商品(1 小时过期,价格波动较快),MySQL 存储 UGC 内容(用于长期趋势分析);监控层:实时监控请求成功率、评价提取完整度,异常时通过邮件告警。
性能优化策略
异步批量获取:使用并发处理多个
aiohttp(控制并发数≤2),提升效率;按需解析:优先提取价格、评分、历史最低价等核心字段,详细评测和全部评价可选择性获取;增量更新:仅更新价格、评分有变化的商品(通过对比缓存的历史数据),减少无效请求。
item_id
合规性与风险控制
频率限制:单 IP 日请求量≤300 次,避免对服务器造成压力,符合平台 robots 协议;数据使用边界:不得将 UGC 内容用于商业售卖或恶意抹黑,需注明数据来源 “什么值得买”;法律风险规避:用户评价涉及个人信息,使用时需脱敏处理(如隐藏用户名、头像),遵守《个人信息保护法》。
七、总结
值得买接口的对接核心在于历史价格曲线的精准提取、UGC 内容的有效解析及低频率高稳定性的采集策略。开发者需重点关注:
item_get
登录态 Cookie 的使用(确保历史价格数据完整);评价、问答等 UGC 内容的清洗与结构化(突出消费决策价值);代理池与请求频率的精细化控制(应对严格反爬)。
通过本文的技术方案,可构建稳定的商品详情获取系统,为消费决策、比价分析等场景提供可靠数据支持。实际应用中,需根据平台最新页面结构动态调整解析规则,平衡数据获取效率与合规性