在电商数据分析、价格监控、竞品分析等场景中,实时获取商品详情数据具有重要价值。京东作为国内领先的电商平台,其商品数据接口的开发与实践一直是开发者关注的焦点。本文将详细讲解京东平台商品详情实时数据采集接口的开发过程,包括接口设计思路、技术选型、核心代码实现及注意事项。
一、接口开发需求分析
商品详情数据采集接口需满足以下核心需求:
- 实时性:能够快速获取最新的商品信息(价格、库存、规格等)
- 稳定性:应对高并发请求,保证接口响应可靠
- 合规性:遵守平台接口调用规范,避免触发反爬机制
- 完整性:覆盖商品基本信息、价格、库存、参数、评价等核心字段
二、技术选型
基于需求分析,选择以下技术栈:
- 开发语言:Python(高效的爬虫生态与接口开发库)
- 网络请求:Requests(处理 HTTP 请求)+ Selenium(应对动态渲染页面)
- 数据解析:BeautifulSoup(HTML 解析)+ JSONPath(JSON 数据提取)
- 缓存机制:Redis(减轻重复请求压力,提高响应速度)
- 接口框架:FastAPI(高性能 API 服务开发)
三、核心实现方案
3.1 京东商品数据获取原理
京东商品详情页 URL 格式通常为:https://item.jd.com/{商品ID}.html,其中商品 ID 为关键标识。获取数据的两种主要方式:
- 直接解析 HTML 页面(适用于静态数据)
- 调用京东内部 API 接口(适用于动态加载数据,如价格、库存)
3.2 接口设计
设计 RESTful 风格 API,核心接口定义:
- 请求地址:
/api/jd/product - 请求方法:GET
- 请求参数:
product_id(商品 ID,必填)、fields(需要返回的字段,可选) - 返回格式:JSON,包含商品各类信息及请求状态
3.3 核心代码实现
3.3.1 项目结构
jd_product_api/
├── app.py # API服务入口
├── jd_spider.py # 京东数据爬取核心逻辑
├── cache.py # 缓存处理
└── config.py # 配置文件
3.3.2 配置文件(config.py)
# 超时设置
TIMEOUT = 10
# 缓存配置
REDIS_CONFIG = {
"host": "localhost",
"port": 6379,
"db": 0,
"password": ""
}
CACHE_EXPIRE = 300 # 缓存过期时间(5分钟)
# 京东API相关配置
JD_PRICE_API = "https://p.3.cn/prices/mgets" # 价格接口
JD_STOCK_API = "https://c0.3.cn/stock" # 库存接口
3.3.3 缓存处理(cache.py)
import redis
from config import REDIS_CONFIG
class RedisCache:
def __init__(self):
self.client = redis.Redis(
host=REDIS_CONFIG["host"],
port=REDIS_CONFIG["port"],
db=REDIS_CONFIG["db"],
password=REDIS_CONFIG["password"],
decode_responses=True
)
def get(self, key):
"""获取缓存数据"""
return self.client.get(key)
def set(self, key, value, expire=None):
"""设置缓存数据"""
if expire:
self.client.setex(key, expire, value)
else:
self.client.set(key, value)
def delete(self, key):
"""删除缓存数据"""
self.client.delete(key)
3.3.4 京东数据爬取逻辑(jd_spider.py)
import requests
import json
from bs4 import BeautifulSoup
from config import TIMEOUT, JD_PRICE_API, JD_STOCK_API
from cache import RedisCache
import hashlib
cache = RedisCache()
class JDProductSpider:
def __init__(self):
# 设置请求头,模拟浏览器
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36",
"Referer": "https://www.jd.com/"
}
def get_product_detail(self, product_id, fields=None):
"""获取商品详情主方法"""
# 先检查缓存
cache_key = f"jd_product:{product_id}"
cached_data = cache.get(cache_key)
if cached_data:
return json.loads(cached_data)
# 组合各类数据
product_data = {
"product_id": product_id,
"basic_info": self.get_basic_info(product_id),
"price_info": self.get_price_info(product_id),
"stock_info": self.get_stock_info(product_id),
"spec_info": self.get_spec_info(product_id)
}
# 按字段筛选(如果指定)
if fields:
fields = fields.split(',')
filtered_data = {}
for field in fields:
if field in product_data:
filtered_data[field] = product_data[field]
product_data = filtered_data
# 存入缓存
cache.set(cache_key, json.dumps(product_data), expire=300)
return product_data
def get_basic_info(self, product_id):
"""获取商品基本信息(标题、图片等)"""
url = f"https://item.jd.com/{product_id}.html"
try:
response = requests.get(url, headers=self.headers, timeout=TIMEOUT)
soup = BeautifulSoup(response.text, "html.parser")
# 提取标题
title = soup.select_one(".sku-name")?.text.strip() or ""
# 提取主图
main_img = soup.select_one("#spec-img")?.get("data-origin") or ""
# 提取店铺信息
shop_name = soup.select_one(".shop-name a")?.text.strip() or ""
return {
"title": title,
"main_img": main_img,
"shop_name": shop_name
}
except Exception as e:
print(f"获取基本信息失败: {str(e)}")
return {}
def get_price_info(self, product_id):
"""获取商品价格信息"""
try:
params = {
"skuIds": f"J_{product_id}",
"type": "1"
}
response = requests.get(
JD_PRICE_API,
headers=self.headers,
params=params,
timeout=TIMEOUT
)
price_data = response.json()
if price_data and len(price_data) > 0:
return {
"original_price": price_data[0].get("m", ""), # 原价
"current_price": price_data[0].get("p", "") # 当前价
}
return {}
except Exception as e:
print(f"获取价格信息失败: {str(e)}")
return {}
def get_stock_info(self, product_id):
"""获取商品库存信息"""
try:
params = {
"skuId": product_id,
"area": "1_72_2799_0", # 地区编码,可根据需求调整
"venderId": "1000000000",
"cat": "1,2,3" # 分类信息,可动态获取
}
response = requests.get(
JD_STOCK_API,
headers=self.headers,
params=params,
timeout=TIMEOUT
)
# 京东库存接口返回的是JSONP格式,需要处理
stock_data = json.loads(response.text.lstrip("jQuery1124037746267620312745_1646607123606(").rstrip(");"))
return {
"stock_status": stock_data.get("stock", {}).get("stockStatusName", ""),
"remain": stock_data.get("stock", {}).get("remainCount", 0)
}
except Exception as e:
print(f"获取库存信息失败: {str(e)}")
return {}
def get_spec_info(self, product_id):
"""获取商品规格参数"""
try:
url = f"https://item.jd.com/{product_id}.html"
response = requests.get(url, headers=self.headers, timeout=TIMEOUT)
soup = BeautifulSoup(response.text, "html.parser")
# 提取规格参数
spec_list = []
for item in soup.select(".Ptable-item"):
name = item.select_one(".fl").text.strip() if item.select_one(".fl") else ""
value = item.select_one(".fr").text.strip() if item.select_one(".fr") else ""
spec_list.append({
"name": name,
"value": value
})
return {"spec_list": spec_list}
except Exception as e:
print(f"获取规格信息失败: {str(e)}")
return {}
3.3.5 API 服务入口(app.py)
from fastapi import FastAPI, HTTPException
from jd_spider import JDProductSpider
import uvicorn
app = FastAPI(title="京东商品详情API", version="1.0")
spider = JDProductSpider()
@app.get("/api/jd/product", summary="获取京东商品详情")
async def get_jd_product(product_id: str, fields: str = None):
if not product_id:
raise HTTPException(status_code=400, detail="商品ID不能为空")
try:
result = spider.get_product_detail(product_id, fields)
return {
"code": 200,
"message": "success",
"data": result
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"获取数据失败: {str(e)}")
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
四、接口测试与使用
启动服务后,可通过以下方式调用接口:
GET http://localhost:8000/api/jd/product?product_id=100012345678&fields=basic_info,price_info
返回示例:
{
"code": 200,
"message": "success",
"data": {
"basic_info": {
"title": "测试商品标题",
"main_img": "https://img10.360buyimg.com/n1/s450x450_jfs/t1/12345/6/7890/123456/abcdef/1234567890abcdef.jpg",
"shop_name": "测试官方旗舰店"
},
"price_info": {
"original_price": "999.00",
"current_price": "799.00"
}
}
}
五、注意事项
-
反爬机制应对:
- 合理设置请求间隔,避免高频请求
- 使用动态 User-Agent 池,模拟不同浏览器
- 必要时引入代理 IP,分散请求源
-
接口稳定性:
- 京东 API 接口可能会不定期调整,需定期维护解析规则
- 实现失败重试机制,提高接口容错性
- 关键字段提取增加异常处理,避免整体解析失败
-
合规性说明:
- 本接口仅用于技术学习,使用时需遵守京东平台规则
- 商业使用需获得京东官方授权,避免法律风险
- 控制请求频率,避免对平台服务器造成压力
六、总结
本文实现的京东商品详情数据采集接口,通过结合页面解析与内部 API 调用,能够高效获取商品核心信息。通过 FastAPI 构建的服务具有良好的扩展性,可根据实际需求增加更多字段提取或功能扩展(如批量查询、历史价格追踪等)。在实际应用中,需重点关注反爬策略与合规性,确保接口长期稳定运行。
京东商品数据接口开发

570

被折叠的 条评论
为什么被折叠?



