Python结合京东API实现竞品分析系统

简介: 你想要用 Python 结合京东 API 搭建一套「竞品分析系统」,核心目标是批量抓取竞品商品数据、进行多维度对比分析(价格、销量、库存等)、生成可视化分析报告。我会提供完整可落地的方案,涵盖「数据采集 → 数据存储 → 多维度分析 → 可视化输出」全流程,兼顾实用性和易扩展性。

你想要用 Python 结合京东 API 搭建一套「竞品分析系统」,核心目标是批量抓取竞品商品数据、进行多维度对比分析(价格、销量、库存等)、生成可视化分析报告。我会提供完整可落地的方案,涵盖「数据采集 → 数据存储 → 多维度分析 → 可视化输出」全流程,兼顾实用性和易扩展性。

一、核心设计思路

1. 系统架构

image.png

2. 核心特性

  • 多维度分析:价格对比、销量排行、库存状态、价格波动趋势;
  • 自动化:定时批量采集数据,自动生成分析报告;
  • 可视化:用matplotlib/plotly生成直观的图表(柱状图 / 折线图);
  • 易扩展:支持新增分析维度(如好评率、店铺评分)。

3. 技术栈

  • 数据采集:requests(京东 API 调用)、threading(批量采集提速);
  • 数据存储:pandas(数据处理)、csv(轻量存储)、pymysql(可选数据库存储);
  • 可视化:matplotlib(基础图表)、plotly(交互式图表,可选);
  • 定时任务:schedule(自动更新数据)。

二、前置准备

1. 安装依赖库

bash

运行

# 核心依赖:API请求 + 数据处理 + 可视化 + 定时任务
pip install requests pandas matplotlib schedule pymysql python-dotenv

2. 基础配置

  • 京东 API 密钥:在聚合数据官网领取「京东商品详情 API」的AppKey(免费版足够测试,生产可升级);
  • 竞品配置:整理需要分析的竞品列表(按品类分组,如「保温杯」「充电宝」)。

三、完整系统代码

1. 配置文件(.env)

ini

# .env 文件(敏感配置分离)
JD_API_KEY=你的聚合数据AppKey
# 可选:MySQL配置(不用数据库则留空)
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=你的数据库密码
DB_NAME=jd_competitor_analysis

2. 核心代码(jd_competitor_analysis.py)

python

运行

import requests
import pandas as pd
import matplotlib.pyplot as plt
import schedule
import time
import os
import json
from datetime import datetime
from dotenv import load_dotenv
import threading
import pymysql
from pymysql.err import OperationalError
# 加载配置
load_dotenv()
plt.rcParams["font.sans-serif"] = ["SimHei"]  # 解决中文显示问题
plt.rcParams["axes.unicode_minus"] = False
# ===================== 全局配置 =====================
# API配置
JD_API_KEY = os.getenv("JD_API_KEY")
JD_API_URL = "https://v.juhe.cn/jd/item/detail"
# 竞品配置(核心:按品类分组,配置商品ID、名称、品牌)
COMPETITOR_CONFIG = {
    "保温杯": [
        {"sku_id": "100060195820", "name": "京东京造轻量保温杯", "brand": "京东京造"},
        {"sku_id": "100080907904", "name": "膳魔师不锈钢保温杯", "brand": "膳魔师"},
        {"sku_id": "100095380451", "name": "象印便携保温杯", "brand": "象印"}
    ],
    "充电宝": [
        {"sku_id": "100012345678", "name": "小米充电宝20000mAh", "brand": "小米"},
        {"sku_id": "100012345679", "name": "罗马仕充电宝10000mAh", "brand": "罗马仕"},
        {"sku_id": "100012345680", "name": "品胜充电宝15000mAh", "brand": "品胜"}
    ]
}
# 数据存储路径
DATA_DIR = "jd_competitor_data"
CSV_FILE = os.path.join(DATA_DIR, "competitor_data.csv")
REPORT_DIR = "jd_competitor_reports"
# 定时更新频率(单位:小时)
UPDATE_INTERVAL = 1
# ====================================================
# 初始化目录
os.makedirs(DATA_DIR, exist_ok=True)
os.makedirs(REPORT_DIR, exist_ok=True)
class JDCompetitorAnalyzer:
    def __init__(self):
        self.api_key = JD_API_KEY
        self.competitor_config = COMPETITOR_CONFIG
        self.data = pd.DataFrame()  # 存储所有竞品数据
    def get_item_detail(self, sku_id):
        """调用京东API获取单个商品详情"""
        params = {
            "key": self.api_key,
            "sku_id": sku_id
        }
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
        }
        try:
            response = requests.get(JD_API_URL, params=params, headers=headers, timeout=10)
            if response.status_code == 200:
                result = response.json()
                if result["error_code"] == 0:
                    item = result["result"]
                    # 提取核心字段(标准化)
                    return {
                        "品类": "",  # 后续填充
                        "商品ID": sku_id,
                        "商品名称": item.get("title", ""),
                        "品牌": "",  # 后续填充
                        "价格": float(item.get("price", 0.0)),
                        "销量": item.get("sales", "0"),
                        "库存状态": item.get("stock_state", "未知"),
                        "店铺名称": item.get("shop_name", ""),
                        "采集时间": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                    }
                else:
                    print(f"API调用失败({sku_id}):{result['reason']}")
            else:
                print(f"HTTP请求失败({sku_id}):状态码{response.status_code}")
        except Exception as e:
            print(f"获取商品数据异常({sku_id}):{str(e)}")
        return None
    def batch_collect_data(self):
        """批量采集所有竞品数据"""
        print(f"\n[{datetime.now()}] 开始批量采集竞品数据...")
        all_data = []
        # 多线程采集(提升效率)
        lock = threading.Lock()
        threads = []
        def collect_category(category, items):
            """采集单个品类的商品数据"""
            category_data = []
            for item in items:
                detail = self.get_item_detail(item["sku_id"])
                if detail:
                    detail["品类"] = category
                    detail["品牌"] = item["brand"]
                    category_data.append(detail)
                    print(f"✅ 采集完成:{category} - {item['name']}")
            with lock:
                all_data.extend(category_data)
        # 启动线程
        for category, items in self.competitor_config.items():
            t = threading.Thread(target=collect_category, args=(category, items))
            threads.append(t)
            t.start()
        # 等待所有线程完成
        for t in threads:
            t.join()
        # 转换为DataFrame并存储
        if all_data:
            self.data = pd.DataFrame(all_data)
            # 追加写入CSV(保留历史数据)
            if os.path.exists(CSV_FILE):
                self.data.to_csv(CSV_FILE, mode="a", header=False, index=False, encoding="utf-8-sig")
            else:
                self.data.to_csv(CSV_FILE, index=False, encoding="utf-8-sig")
            print(f"✅ 批量采集完成,共采集{len(all_data)}条数据,已保存到{CSV_FILE}")
        else:
            print("❌ 未采集到任何数据")
    def load_historical_data(self):
        """加载历史采集数据"""
        if os.path.exists(CSV_FILE):
            self.data = pd.read_csv(CSV_FILE, encoding="utf-8-sig")
            print(f"✅ 加载历史数据完成,共{len(self.data)}条")
        else:
            print("⚠️ 无历史数据,先执行批量采集")
    def analyze_price(self, category=None):
        """价格分析:对比同品类商品价格,生成柱状图"""
        self.load_historical_data()
        if self.data.empty:
            return
        # 筛选品类(默认分析所有)
        analyze_data = self.data if category is None else self.data[self.data["品类"] == category]
        if analyze_data.empty:
            print(f"❌ 无{category}品类的分析数据")
            return
        # 取最新采集的价格(按采集时间排序)
        analyze_data["采集时间"] = pd.to_datetime(analyze_data["采集时间"])
        latest_data = analyze_data.sort_values("采集时间").groupby(["品类", "商品ID"]).last().reset_index()
        # 生成价格对比图
        plt.figure(figsize=(12, 6))
        for category in latest_data["品类"].unique():
            cat_data = latest_data[latest_data["品类"] == category]
            plt.bar(
                [f"{row['品牌']}\n{row['商品名称'][:8]}..." for _, row in cat_data.iterrows()],
                cat_data["价格"],
                label=category
            )
        plt.title("京东竞品价格对比分析", fontsize=14)
        plt.xlabel("商品(品牌+名称)", fontsize=12)
        plt.ylabel("价格(元)", fontsize=12)
        plt.xticks(rotation=45, ha="right")
        plt.legend()
        plt.tight_layout()
        # 保存图表
        price_report_path = os.path.join(REPORT_DIR, f"价格对比分析_{datetime.now().strftime('%Y%m%d%H%M')}.png")
        plt.savefig(price_report_path, dpi=300)
        print(f"✅ 价格分析完成,图表已保存到{price_report_path}")
    def analyze_sales(self, category=None):
        """销量分析:同品类销量排行,生成横向柱状图"""
        self.load_historical_data()
        if self.data.empty:
            return
        analyze_data = self.data if category is None else self.data[self.data["品类"] == category]
        if analyze_data.empty:
            print(f"❌ 无{category}品类的分析数据")
            return
        # 处理销量数据(统一格式:提取数字)
        def parse_sales(sales_str):
            if pd.isna(sales_str) or sales_str == "暂无数据":
                return 0
            sales_str = str(sales_str).replace("+", "").replace("万", "0000")
            try:
                return int(float(sales_str.replace(" ", "")))
            except:
                return 0
        analyze_data["销量数值"] = analyze_data["销量"].apply(parse_sales)
        latest_data = analyze_data.sort_values("采集时间").groupby(["品类", "商品ID"]).last().reset_index()
        # 生成销量排行图
        plt.figure(figsize=(12, 6))
        for category in latest_data["品类"].unique():
            cat_data = latest_data[latest_data["品类"] == category].sort_values("销量数值", ascending=True)
            plt.barh(
                [f"{row['品牌']}\n{row['商品名称'][:8]}..." for _, row in cat_data.iterrows()],
                cat_data["销量数值"],
                label=category
            )
        plt.title("京东竞品销量排行分析", fontsize=14)
        plt.xlabel("销量(数值)", fontsize=12)
        plt.ylabel("商品(品牌+名称)", fontsize=12)
        plt.legend()
        plt.tight_layout()
        # 保存图表
        sales_report_path = os.path.join(REPORT_DIR, f"销量排行分析_{datetime.now().strftime('%Y%m%d%H%M')}.png")
        plt.savefig(sales_report_path, dpi=300)
        print(f"✅ 销量分析完成,图表已保存到{sales_report_path}")
    def generate_summary_report(self):
        """生成竞品分析汇总报告(文本+图表)"""
        print(f"\n[{datetime.now()}] 开始生成竞品分析汇总报告...")
        self.load_historical_data()
        if self.data.empty:
            return
        # 生成价格和销量分析图表
        self.analyze_price()
        self.analyze_sales()
        # 生成文本汇总报告
        summary = []
        summary.append(f"# 京东竞品分析汇总报告({datetime.now().strftime('%Y-%m-%d %H:%M:%S')})")
        summary.append(f"## 数据概况")
        summary.append(f"- 采集品类数:{len(self.data['品类'].unique())}")
        summary.append(f"- 商品总数:{len(self.data['商品ID'].unique())}")
        summary.append(f"- 历史数据总量:{len(self.data)}条")
        # 按品类汇总
        summary.append("\n## 各品类分析")
        for category in self.data["品类"].unique():
            cat_data = self.data[self.data["品类"] == category]
            latest_cat = cat_data.sort_values("采集时间").groupby("商品ID").last().reset_index()
            summary.append(f"\n### {category}")
            # 价格最低商品
            min_price_item = latest_cat.loc[latest_cat["价格"].idxmin()]
            summary.append(f"- 价格最低:{min_price_item['品牌']} {min_price_item['商品名称'][:20]}...({min_price_item['价格']}元)")
            # 销量最高商品
            latest_cat["销量数值"] = latest_cat["销量"].apply(lambda x: parse_sales(x) if pd.notna(x) else 0)
            max_sales_item = latest_cat.loc[latest_cat["销量数值"].idxmax()]
            summary.append(f"- 销量最高:{max_sales_item['品牌']} {max_sales_item['商品名称'][:20]}...({max_sales_item['销量']})")
            # 库存状态统计
            stock_stats = latest_cat["库存状态"].value_counts().to_dict()
            summary.append(f"- 库存状态:{stock_stats}")
        # 保存文本报告
        report_path = os.path.join(REPORT_DIR, f"竞品分析汇总报告_{datetime.now().strftime('%Y%m%d%H%M')}.md")
        with open(report_path, "w", encoding="utf-8") as f:
            f.write("\n".join(summary))
        print(f"✅ 汇总报告生成完成,已保存到{report_path}")
    def run_scheduled_task(self):
        """启动定时任务:自动采集+分析"""
        print(f"\n[{datetime.now()}] 启动竞品分析定时任务,每{UPDATE_INTERVAL}小时更新一次...")
        # 立即执行一次
        self.batch_collect_data()
        self.generate_summary_report()
        # 配置定时任务
        schedule.every(UPDATE_INTERVAL).hours.do(self.batch_collect_data)
        schedule.every(UPDATE_INTERVAL).hours.do(self.generate_summary_report)
        # 持续运行
        while True:
            schedule.run_pending()
            time.sleep(60)
# 辅助函数:解析销量数值
def parse_sales(sales_str):
    if pd.isna(sales_str) or sales_str == "暂无数据":
        return 0
    sales_str = str(sales_str).replace("+", "").replace("万", "0000")
    try:
        return int(float(sales_str.replace(" ", "")))
    except:
        return 0
# 主函数
if __name__ == "__main__":
    analyzer = JDCompetitorAnalyzer()
    # 可选操作:
    # 1. 单次批量采集+生成报告
    # analyzer.batch_collect_data()
    # analyzer.generate_summary_report()
    # 2. 启动定时任务(自动采集+分析)
    analyzer.run_scheduled_task()

四、代码核心说明

1. 关键功能模块

表格

方法 核心作用 亮点
get_item_detail 单商品数据采集 异常捕获 + 字段标准化,保证数据一致性
batch_collect_data 批量采集 多线程提速,按品类分组采集,追加保存历史数据
analyze_price 价格对比分析 生成柱状图,支持单品类 / 全品类分析
analyze_sales 销量排行分析 处理非标准销量数据(如「10 万 +」),生成横向柱状图
generate_summary_report 汇总报告生成 文本报告(MD 格式)+ 可视化图表,自动汇总关键指标
run_scheduled_task 定时任务 自动采集 + 分析,支持自定义更新频率

2. 核心配置修改

  • COMPETITOR_CONFIG:替换为你的竞品列表,按「品类→商品」分组,填写sku_id(京东商品 ID)、name(商品名称)、brand(品牌);
  • UPDATE_INTERVAL:修改定时更新频率(建议≥1 小时,避免 API 调用超限);
  • JD_API_KEY:在.env文件中填写聚合数据的 AppKey。

3. 避坑要点

  • API 调用限制:聚合数据免费版有调用次数限制,批量采集时控制线程数和频率;
  • 销量数据处理:京东 API 返回的销量可能是「10 万 +」「暂无数据」等非标准格式,代码中已做解析;
  • 中文显示:设置plt.rcParams解决 matplotlib 中文乱码问题;
  • 数据存储:CSV 文件用utf-8-sig编码,避免 Excel 打开乱码。

五、运行与使用

1. 单次运行(采集 + 生成报告)

注释掉定时任务,执行单次采集和报告生成:

python

运行

if __name__ == "__main__":
    analyzer = JDCompetitorAnalyzer()
    analyzer.batch_collect_data()
    analyzer.generate_summary_report()

运行命令:

bash

运行

python jd_competitor_analysis.py

2. 定时运行(自动更新)

启用定时任务,程序会持续运行,按设定频率自动采集数据并生成报告:

python

运行

if __name__ == "__main__":
    analyzer = JDCompetitorAnalyzer()
    analyzer.run_scheduled_task()

3. 输出结果示例

  • 数据文件jd_competitor_data/competitor_data.csv(保留所有历史采集数据);
  • 可视化图表jd_competitor_reports/价格对比分析_202602101530.png销量排行分析_202602101530.png
  • 汇总报告jd_competitor_reports/竞品分析汇总报告_202602101530.md(Markdown 格式,可直接打开查看)。

六、进阶优化(可选)

  1. 数据库存储:替换 CSV 为 MySQL,支持更高效的历史数据查询和分析;
  2. 价格趋势分析:基于历史数据生成价格波动折线图,分析竞品调价规律;
  3. 多维度扩展:新增「好评率」「店铺评分」「配送方式」等分析维度;
  4. 告警功能:当竞品价格低于设定阈值时,触发邮件 / 钉钉告警;
  5. 交互式可视化:用plotly替换matplotlib,生成可交互的网页版图表;
  6. 数据清洗优化:处理重复数据、缺失值,提升分析准确性。

总结

  1. 核心逻辑:通过多线程批量采集京东竞品数据,基于 pandas 做数据处理,matplotlib 生成可视化图表,最终输出结构化的分析报告;
  2. 关键配置:修改COMPETITOR_CONFIG添加竞品,配置 API 密钥,调整更新频率;
  3. 实用性:支持定时自动更新,保留历史数据,可生成价格 / 销量等多维度分析报告,满足竞品分析核心需求;
  4. 扩展性:代码模块化设计,可轻松新增分析维度、告警功能、数据库存储等。

这套系统完全适配中小商家 / 个人的竞品分析需求,代码结构清晰,无需复杂的开发经验即可上手,且能根据实际需求灵活扩展功能。

相关文章
|
5月前
|
存储 自然语言处理 测试技术
一行代码,让 Elasticsearch 集群瞬间雪崩——5000W 数据压测下的性能避坑全攻略
本文深入剖析 Elasticsearch 中模糊查询的三大陷阱及性能优化方案。通过5000 万级数据量下做了高压测试,用真实数据复刻事故现场,助力开发者规避“查询雪崩”,为您的业务保驾护航。
1865 89
|
6月前
|
人工智能 前端开发 算法
大厂CIO独家分享:AI如何重塑开发者未来十年
在 AI 时代,若你还在紧盯代码量、执着于全栈工程师的招聘,或者仅凭技术贡献率来评判价值,执着于业务提效的比例而忽略产研价值,你很可能已经被所谓的“常识”困住了脚步。
3619 90
大厂CIO独家分享:AI如何重塑开发者未来十年
|
22天前
|
缓存 人工智能 文字识别
大模型应用:多模态图文精准识别:基于本地化OCR模型应用实践.78
Qwen2-VL-OCR-2B是仅2B参数的轻量多模态OCR智能体,深度融合视觉感知与语言理解,可精准识别倾斜文字、复杂排版及多语言混合内容。支持CPU/GPU自动适配、指令式调用与全格式图片,本地部署安全高效,适用于文档、合同、海报等场景。
273 10
|
5月前
|
存储 缓存 JSON
小红书item_get - 获得商品详情接口对接全攻略:从入门到精通
小红书item_get接口是获取商品详情的核心工具,支持获取价格、库存、销量、图文等数据,广泛用于竞品分析、电商选品与舆情监测。因无官方公开接口,需通过合规第三方服务商接入。本文详解接口参数、调用流程、Python实现、调试技巧及生产优化策略,涵盖签名生成、异常处理、批量请求优化与合规要点,助力开发者高效稳定对接,适用于电商数据分析与聚合平台开发。(239字)
|
5月前
|
数据可视化 前端开发 数据挖掘
期货数据API对接与可视化分析全攻略:从数据获取到K线图生成
本文系统讲解期货数据API对接与K线图可视化全流程,涵盖WebSocket实时行情获取、RESTful历史数据调用、Pandas数据清洗处理及mplfinance、ECharts等多方案图表生成,助你构建完整的期货分析系统。
|
12天前
|
人工智能 开发框架 文字识别
Qwen3.6 正式发布!阿里云百炼同步开启“AI大模型节省计划”超值优惠
阿里云发布千问Qwen3.6系列大模型,大模型官网:https://t.aliyun.com/U/JbblVp 实现编程、智能体(Agent)及多模态能力的范式跃迁:代码生成与调试更精准,原生支持LangChain等框架,工具调用更稳定,图文识别与推理全面升级。Qwen3.6-Flash轻量高效,开发体验优化。同步推出百炼「全模型通享」限时特惠,新客首月立减最高500元。
679 1
|
3月前
|
机器学习/深度学习 传感器 人工智能
【轴承故障检测】滚动轴承中进行基于振动的故障诊断研究(Matlab代码实现)
【轴承故障检测】滚动轴承中进行基于振动的故障诊断研究(Matlab代码实现)
323 1
|
5月前
|
存储 人工智能 自然语言处理
LlamaIndex 深度实战:用《长安的荔枝》学会构建智能问答系统
本文深入浅出地讲解了RAG(检索增强生成)原理与LlamaIndex实战,通过《长安的荔枝》案例,从AI如何“读书”讲起,详解三大关键参数(chunk_size、top_k、overlap)对问答效果的影响,并结合真实实验展示不同配置下的回答质量差异。内容兼顾新手引导与进阶优化,帮助读者快速构建高效的文档问答系统。
821 22
LlamaIndex 深度实战:用《长安的荔枝》学会构建智能问答系统
|
6月前
|
人工智能 Java API
Java 正式进入 Agentic AI 时代:Spring AI Alibaba 1.1 发布背后的技术演进
Spring AI Alibaba 1.1 正式发布,提供极简方式构建企业级AI智能体。基于ReactAgent核心,支持多智能体协作、上下文工程与生产级管控,助力开发者快速打造可靠、可扩展的智能应用。
4580 43
|
人工智能 监控 机器人
阿里云开发者社区博文规范及指引
阿里云开发者社区博文规范及指引
5001 32
阿里云开发者社区博文规范及指引

热门文章

最新文章