实战:使用 Python(Requests/Scrapy)接入京东商品详情 API 并解析数据结构

在电商数据分析、竞品监控等场景中,获取商品详情数据是常见需求。本文将通过实战案例,分别使用 Requests 库和 Scrapy 框架接入京东商品详情 API,解析数据结构并提取关键信息,帮助开发者快速掌握电商数据采集技巧。

一、京东商品详情 API 分析

京东未公开官方商品详情 API,但通过浏览器开发者工具可发现其移动端接口具有较好的稳定性。本文以移动端商品详情接口为例进行开发:

接口特征

  • 请求 URL:https://item.m.jd.com/product/{商品ID}.html(HTML 页面,包含 JSON 数据)
  • 关键参数:商品 ID(可从商品详情页 URL 获取)
  • 数据格式:HTML 中嵌入 JSON 格式的商品信息(需提取解析)

二、使用 Requests 实现商品数据采集

Requests 是 Python 中常用的 HTTP 请求库,适合快速开发轻量级数据采集工具。

1. 环境准备

pip install requests parsel  # parsel用于解析HTML

2. 核心代码实现

import re
import json
import requests
from parsel import Selector

class JDItemSpider:
    def __init__(self):
        # 设置请求头,模拟移动端浏览器
        self.headers = {
            "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1",
            "Referer": "https://m.jd.com/"
        }

    def get_item_detail(self, item_id):
        """获取商品详情数据"""
        url = f"https://item.m.jd.com/product/{item_id}.html"
        
        try:
            response = requests.get(url, headers=self.headers, timeout=10)
            response.encoding = "utf-8"
            
            if response.status_code == 200:
                return self.parse_item_data(response.text)
            else:
                print(f"请求失败,状态码:{response.status_code}")
                return None
                
        except Exception as e:
            print(f"请求异常:{str(e)}")
            return None

    def parse_item_data(self, html):
        """解析HTML中的商品数据"""
        selector = Selector(text=html)
        
        # 提取HTML中的JSON数据(通过正则匹配)
        script_data = selector.re(r'window\.product = (.*?);')
        if not script_data:
            return None
            
        try:
            # 解析JSON数据
            item_data = json.loads(script_data[0])
            
            # 提取关键信息
            result = {
                "商品ID": item_data.get("id"),
                "商品名称": item_data.get("name"),
                "售价": item_data.get("jdPrice", {}).get("op"),
                "市场价": item_data.get("jdPrice", {}).get("m"),
                "店铺名称": item_data.get("shop", {}).get("name"),
                "店铺ID": item_data.get("shop", {}).get("shopId"),
                "商品图片": item_data.get("imageList", [])[0].get("url") if item_data.get("imageList") else None,
                "是否有货": item_data.get("stock", {}).get("stockState") == 3,  # 3表示有货
                "标签": [tag.get("name") for tag in item_data.get("tags", [])]
            }
            return result
            
        except json.JSONDecodeError:
            print("JSON解析失败")
            return None

if __name__ == "__main__":
    spider = JDItemSpider()
    # 测试商品ID(可替换为任意京东商品ID)
    item_info = spider.get_item_detail("100012345678")
    if item_info:
        print("商品详情:")
        for key, value in item_info.items():
            print(f"{key}: {value}")

三、使用 Scrapy 框架实现分布式采集

Scrapy 是专业的爬虫框架,适合大规模、高并发的数据采集场景,支持自动处理异步请求、代理池等高级功能。

1. 环境准备

pip install scrapy

2. 项目创建与实现

scrapy startproject jd_spider
cd jd_spider
scrapy genspider jd_item item.m.jd.com
2.1 配置文件(settings.py)
USER_AGENT = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"
ROBOTSTXT_OBEY = False  # 不遵守robots协议
CONCURRENT_REQUESTS = 16  # 并发请求数
DOWNLOAD_DELAY = 1  # 下载延迟(秒)
2.2 爬虫实现(jd_item.py)
import re
import json
import scrapy
from scrapy.selector import Selector
from jd_spider.items import JdSpiderItem

class JdItemSpider(scrapy.Spider):
    name = 'jd_item'
    allowed_domains = ['item.m.jd.com']
    
    # 初始请求(可替换为实际需要采集的商品ID列表)
    start_urls = ['https://item.m.jd.com/product/100012345678.html']

    def parse(self, response):
        """解析商品详情页"""
        item = JdSpiderItem()
        html = response.text
        
        # 提取JSON数据
        script_data = Selector(text=html).re(r'window\.product = (.*?);')
        if not script_data:
            return
            
        try:
            item_data = json.loads(script_data[0])
            
            # 填充Item字段
            item['item_id'] = item_data.get("id")
            item['name'] = item_data.get("name")
            item['price'] = item_data.get("jdPrice", {}).get("op")
            item['market_price'] = item_data.get("jdPrice", {}).get("m")
            item['shop_name'] = item_data.get("shop", {}).get("name")
            item['shop_id'] = item_data.get("shop", {}).get("shopId")
            item['image_url'] = item_data.get("imageList", [])[0].get("url") if item_data.get("imageList") else None
            item['is_in_stock'] = item_data.get("stock", {}).get("stockState") == 3
            item['tags'] = [tag.get("name") for tag in item_data.get("tags", [])]
            
            yield item
            
        except json.JSONDecodeError:
            self.logger.error("JSON解析失败")
2.3 数据模型(items.py)
import scrapy

class JdSpiderItem(scrapy.Item):
    item_id = scrapy.Field()       # 商品ID
    name = scrapy.Field()          # 商品名称
    price = scrapy.Field()         # 售价
    market_price = scrapy.Field()  # 市场价
    shop_name = scrapy.Field()     # 店铺名称
    shop_id = scrapy.Field()       # 店铺ID
    image_url = scrapy.Field()     # 商品图片
    is_in_stock = scrapy.Field()   # 是否有货
    tags = scrapy.Field()          # 标签
2.4 运行爬虫
scrapy crawl jd_item -o jd_items.csv  # 结果保存为CSV文件

四、数据结构解析与扩展

京东商品数据结构复杂,核心字段解析如下:

  1. 基础信息id(商品 ID)、name(商品名称)、brand(品牌信息)
  2. 价格信息jdPrice包含op(当前价)、m(市场价)、t(促销价)
  3. 库存信息stock中的stockState(3 表示有货,0 表示无货)
  4. 店铺信息shop包含店铺 ID、名称、评分等
  5. 图片信息imageList包含多张大图 URL
  6. 规格参数sku2info包含不同规格(颜色、尺寸等)的库存和价格

可根据业务需求扩展字段,例如提取商品详情描述、用户评价等信息(需分析对应接口)。

五、注意事项

  1. 反爬策略

    • 合理设置请求间隔(DOWNLOAD_DELAY
    • 使用随机 User-Agent 池
    • 必要时配置代理 IP 池
  2. 合法性

    • 遵守网站 robots 协议
    • 采集数据仅供个人学习使用,不得用于商业用途
    • 避免对服务器造成过大压力
  3. 接口稳定性

    • 京东接口可能不定期更新,需定期维护解析规则
    • 建议添加异常捕获和日志记录,提高程序健壮性

通过本文的实战案例,你可以快速掌握使用 Python 采集京东商品数据的方法。Requests 适合快速验证和小规模采集,而 Scrapy 更适合构建大规模、可扩展的采集系统。根据实际需求选择合适的工具,并注意合规性和反爬策略,才能稳定高效地获取数据。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值