实战:使用 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用于解析HTML2. 核心代码实现
import re
import json
import requests
from parsel import Selectorclass 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 Noneexcept Exception as e:print(f"请求异常:{str(e)}")return Nonedef parse_item_data(self, html):"""解析HTML中的商品数据"""selector = Selector(text=html)# 提取HTML中的JSON数据(通过正则匹配)script_data = selector.re(r'window\.product = (.*?);')if not script_data:return Nonetry:# 解析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 resultexcept json.JSONDecodeError:print("JSON解析失败")return Noneif __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 scrapy2. 项目创建与实现
scrapy startproject jd_spider
cd jd_spider
scrapy genspider jd_item item.m.jd.com2.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 JdSpiderItemclass 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:returntry: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 Noneitem['is_in_stock'] = item_data.get("stock", {}).get("stockState") == 3item['tags'] = [tag.get("name") for tag in item_data.get("tags", [])]yield itemexcept json.JSONDecodeError:self.logger.error("JSON解析失败")2.3 数据模型(items.py)
import scrapyclass JdSpiderItem(scrapy.Item):item_id = scrapy.Field() # 商品IDname = scrapy.Field() # 商品名称price = scrapy.Field() # 售价market_price = scrapy.Field() # 市场价shop_name = scrapy.Field() # 店铺名称shop_id = scrapy.Field() # 店铺IDimage_url = scrapy.Field() # 商品图片is_in_stock = scrapy.Field() # 是否有货tags = scrapy.Field() # 标签2.4 运行爬虫
scrapy crawl jd_item -o jd_items.csv # 结果保存为CSV文件四、数据结构解析与扩展
京东商品数据结构复杂,核心字段解析如下:
- 基础信息:
id(商品 ID)、name(商品名称)、brand(品牌信息) - 价格信息:
jdPrice包含op(当前价)、m(市场价)、t(促销价) - 库存信息:
stock中的stockState(3 表示有货,0 表示无货) - 店铺信息:
shop包含店铺 ID、名称、评分等 - 图片信息:
imageList包含多张大图 URL - 规格参数:
sku2info包含不同规格(颜色、尺寸等)的库存和价格
可根据业务需求扩展字段,例如提取商品详情描述、用户评价等信息(需分析对应接口)。
五、注意事项
反爬策略:
- 合理设置请求间隔(
DOWNLOAD_DELAY) - 使用随机 User-Agent 池
- 必要时配置代理 IP 池
- 合理设置请求间隔(
合法性:
- 遵守网站 robots 协议
- 采集数据仅供个人学习使用,不得用于商业用途
- 避免对服务器造成过大压力
接口稳定性:
- 京东接口可能不定期更新,需定期维护解析规则
- 建议添加异常捕获和日志记录,提高程序健壮性
通过本文的实战案例,你可以快速掌握使用 Python 采集京东商品数据的方法。Requests 适合快速验证和小规模采集,而 Scrapy 更适合构建大规模、可扩展的采集系统。根据实际需求选择合适的工具,并注意合规性和反爬策略,才能稳定高效地获取数据。
