以下是实时获取京东指定商品当前价格的实战示例,包含接口分析、代码实现及反爬处理,适用于开发者快速落地价格监控功能:
一、京东商品价格接口分析
京东商品价格数据通过独立 API 接口返回,核心特点:
- 接口地址:
https://p.3.cn/prices/mgets
(公开可访问,登录) - 请求方式:
GET
- 关键参数:
skuIds=J_商品ID
(商品 ID 需拼接前缀J_
) - 返回格式:JSON,包含原价、当前价、促销价等信息
二、实战代码实现(Python)
1. 基础版:单商品价格获取
import requests
import json
def get_jd_price(sku_id):
"""
获取京东指定商品当前价格
:param sku_id: 商品ID(如100012345678)
:return: 价格字典(含原价、当前价等)
"""
# 构造请求参数
url = "https://p.3.cn/prices/mgets"
params = {
"skuIds": f"J_{sku_id}", # 必须拼接J_前缀
"type": 1,
"area": "1_72_2799_0", # 地区编码(可固定,不影响价格获取)
"pduid": "1234567890", # 随机用户ID,可固定
"_": "1688888888888" # 时间戳(可选,增加随机性)
}
# 请求头(模拟浏览器)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
"Referer": f"https://item.jd.com/{sku_id}.html", # Referer必须与商品页一致
"Accept": "application/json, text/plain, */*"
}
try:
# 发送请求
response = requests.get(url, params=params, headers=headers, timeout=10)
response.encoding = "utf-8"
# 解析响应
if response.status_code == 200:
price_data = json.loads(response.text)
if price_data and len(price_data) > 0:
# 提取核心价格字段
return {
"sku_id": sku_id,
"current_price": float(price_data[0]["p"]), # 当前售价
"original_price": float(price_data[0]["m"]), # 原价(市场价)
"price_time": response.headers.get("Date") # 价格更新时间
}
else:
return {"error": "未获取到价格数据"}
else:
return {"error": f"请求失败,状态码:{response.status_code}"}
except Exception as e:
return {"error": f"接口调用异常:{str(e)}"}
# 使用示例
if __name__ == "__main__":
# 京东商品ID(可从商品详情页URL获取,如https://item.jd.com/100032608854.html中的100032608854)
sku_id = "100032608854"
price_info = get_jd_price(sku_id)
if "error" in price_info:
print(f"获取失败:{price_info['error']}")
else:
print(f"商品ID:{price_info['sku_id']}")
print(f"当前价格:¥{price_info['current_price']}")
print(f"原价:¥{price_info['original_price']}")
print(f"价格时间:{price_info['price_time']}")
2. 进阶版:批量获取 + 反爬优化
import requests
import json
import time
import random
from fake_useragent import UserAgent
class JDPriceFetcher:
def __init__(self):
self.ua = UserAgent()
self.proxies = self._get_proxies() # 代理池(可选,高频请求时使用)
self.area_codes = [
"1_72_2799_0", # 北京地区
"2_281_0_0", # 上海地区
"3_340_0_0" # 广州地区
]
def _get_proxies(self):
"""获取代理IP(示例:实际需对接代理服务)"""
# 免费代理示例(不稳定,生产环境建议使用付费代理)
return {
# "http": "http://123.45.67.89:8080",
# "https": "https://123.45.67.89:8080"
}
def _get_headers(self, sku_id):
"""动态生成请求头"""
return {
"User-Agent": self.ua.random, # 随机User-Agent
"Referer": f"https://item.jd.com/{sku_id}.html",
"Accept": "application/json, text/plain, */*",
"Connection": "keep-alive",
"Cache-Control": "no-cache"
}
def fetch_price(self, sku_id):
"""获取单个商品价格(带反爬处理)"""
url = "https://p.3.cn/prices/mgets"
params = {
"skuIds": f"J_{sku_id}",
"type": 1,
"area": random.choice(self.area_codes), # 随机地区编码
"pduid": str(random.randint(1000000000, 9999999999)), # 随机用户ID
"_": int(time.time() * 1000) # 实时时间戳
}
try:
# 随机延迟(1-3秒),避免高频请求
time.sleep(random.uniform(1, 3))
response = requests.get(
url,
params=params,
headers=self._get_headers(sku_id),
proxies=self.proxies,
timeout=10,
verify=False # 忽略SSL证书验证(可选,部分代理需要)
)
if response.status_code == 200:
price_data = json.loads(response.text)
if price_data and len(price_data) > 0:
return {
"sku_id": sku_id,
"current_price": float(price_data[0]["p"]),
"original_price": float(price_data[0]["m"]),
"status": "success"
}
else:
return {"sku_id": sku_id, "error": "价格数据为空", "status": "fail"}
else:
return {
"sku_id": sku_id,
"error": f"状态码:{response.status_code}",
"status": "fail"
}
except Exception as e:
return {
"sku_id": sku_id,
"error": str(e),
"status": "fail"
}
def batch_fetch(self, sku_ids):
"""批量获取多个商品价格"""
results = []
for sku_id in sku_ids:
print(f"正在获取商品 {sku_id} 价格...")
result = self.fetch_price(sku_id)
results.append(result)
return results
# 批量获取示例
if __name__ == "__main__":
fetcher = JDPriceFetcher()
# 待查询的商品ID列表
sku_ids = [
"100032608854", # 示例商品1
"100012345678", # 示例商品2
"100008348544" # 示例商品3
]
# 批量获取价格
prices = fetcher.batch_fetch(sku_ids)
# 打印结果
print("\n===== 价格查询结果 =====")
for item in prices:
if item["status"] == "success":
print(f"商品 {item['sku_id']}:当前价 ¥{item['current_price']},原价 ¥{item['original_price']}")
else:
print(f"商品 {item['sku_id']}:获取失败,原因:{item['error']}")
三、关键技术点解析
- 参数构造:skuIds必须以J_为前缀(京东商品 ID 格式要求)area参数为地区编码(如1_72_2799_0代表北京朝阳区),不影响价格但增加请求真实性
- 反爬处理:随机 User-Agent:使用fake_useragent库生成不同设备的浏览器标识Referer 验证:必须与商品详情页 URL 一致,否则可能返回 403请求延迟:每次请求间隔 1-3 秒,避免触发频率限制代理 IP:高频请求时使用代理池,防止 IP 被封
- 数据解析:核心字段:p(当前价)、m(原价),返回值为字符串需转为浮点数异常处理:针对网络超时、JSON 解析失败等情况返回错误信息
四、注意事项
- 合规性:非商业用途合理调用(建议≤100 次 / 小时)遵守京东robots.txt规则(https://www.jd.com/robots.txt)数据不得用于商业售卖或恶意竞争
- 接口稳定性:京东可能不定期调整接口参数,需定期测试代码若返回 403/429,需增加延迟或更换 IP
- 通过以上示例,可快速实现京东商品价格的实时获取,结合定时任务和数据存储,可进一步构建价格监控系统,为用户提供降价提醒、趋势分析等增值服务。