京东关键词搜索商品列表 Python 爬虫实战
你想要实现京东关键词搜索商品的爬虫,我会从合规声明、环境准备、页面分析、代码实现、反爬优化五个方面展开,帮助你完成实战项目。
一、前置声明(重要!)
- 京东拥有商品数据的版权,爬虫仅可用于个人学习、研究,禁止用于商业用途、批量爬取造成京东服务器压力。
- 遵守京东《用户协议》和
robots.txt协议(京东https://www.jd.com/robots.txt明确限制了部分爬虫行为)。 - 本实战仅演示基础爬虫思路,爬取频率极低,避免对平台造成影响。
二、环境准备
需要安装 3 个核心 Python 库,打开终端执行以下命令:
bash
运行
pip install requests beautifulsoup4 fake-useragent
requests:发送 HTTP 网络请求,获取页面数据。beautifulsoup4:解析 HTML 页面,提取目标商品信息。fake-useragent:生成随机 User-Agent,规避简单的反爬检测。
三、京东搜索页面分析
-
搜索 URL 构造 :打开京东官网,搜索关键词(例如 "Python 书籍"),观察浏览器地址栏,得到搜索 URL 格式:
plaintext
https://search.jd.com/Search?keyword=关键词&enc=utf8&page=页码keyword:需要搜索的商品关键词(需 URL 编码,requests会自动处理)。page:商品列表页码(京东每页展示 60 件商品,页码为 1、3、5... 奇数递增,对应第 1、2、3... 页)。
-
商品标签定位 :京东商品列表的核心 HTML 标签为
<li class="gl-item">,每个该标签对应一件商品,包含商品 ID、名称、价格、链接、店铺等信息。 -
价格特殊说明 :京东商品价格采用动态加载(JS 渲染),直接爬取静态 HTML 无法获取准确价格,需单独请求价格接口或后续通过 JS 解析补充,本实战先提取静态页面可获取的核心信息,再补充价格接口优化方案。
四、完整代码实现(基础版)
版本 1:基础爬虫(提取商品核心信息)
实现功能:指定关键词,爬取第 1 页商品的商品 ID、商品名称、商品链接、店铺名称(价格后续优化)。
python
运行
# 导入所需模块
import requests
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
import time
def get_jd_goods(keyword, page=1):
"""
爬取京东关键词搜索商品列表
:param keyword: 搜索关键词
:param page: 页码(默认第1页)
:return: 商品信息列表
"""
# 1. 构造请求参数
url = "https://search.jd.com/Search"
params = {
"keyword": keyword,
"enc": "utf8",
"page": page, # 京东页码为奇数,1=第1页,3=第2页,以此类推
"wq": keyword # 补充参数,提高请求成功率
}
# 2. 构造请求头(规避简单反爬)
ua = UserAgent()
headers = {
"User-Agent": ua.random, # 随机生成User-Agent
"Referer": "https://www.jd.com/", # 来源页,模拟浏览器跳转
"Accept-Language": "zh-CN,zh;q=0.9", # 接受语言
"Connection": "keep-alive"
}
try:
# 3. 发送GET请求(设置超时,避免卡死;禁止重定向,提高效率)
response = requests.get(
url=url,
params=params,
headers=headers,
timeout=15,
allow_redirects=False
)
response.raise_for_status() # 若请求状态码不是200,抛出异常
response.encoding = "utf-8" # 指定编码,避免中文乱码
# 4. 解析HTML页面,提取商品信息
soup = BeautifulSoup(response.text, "lxml") # lxml解析器,高效快速
goods_list = [] # 存储最终商品信息
# 定位所有商品标签 <li class="gl-item">
goods_items = soup.find_all("li", class_="gl-item")
for item in goods_items:
# 提取商品ID
goods_id = item.get("data-sku", "未知ID")
# 提取商品名称
goods_name_tag = item.find("div", class_="p-name").find("em")
goods_name = goods_name_tag.get_text(strip=True) if goods_name_tag else "未知名称"
# 提取商品链接
goods_href_tag = item.find("a", class_="p-img")
goods_href = "https:" + goods_href_tag.get("href", "") if goods_href_tag else "未知链接"
# 提取店铺名称
shop_name_tag = item.find("div", class_="p-shop").find("a")
shop_name = shop_name_tag.get_text(strip=True) if shop_name_tag else "未知店铺"
# 组装商品信息
goods_info = {
"商品ID": goods_id,
"商品名称": goods_name,
"商品链接": goods_href,
"店铺名称": shop_name
}
goods_list.append(goods_info)
# 打印单条商品信息(实时查看进度)
print(f"已提取商品:{goods_name[:30]}...")
# 5. 模拟人类操作,添加延时(核心反爬手段之一)
time.sleep(2)
return goods_list
except requests.exceptions.RequestException as e:
print(f"请求失败:{e}")
return []
def save_goods_to_txt(goods_list, keyword):
"""
将商品信息保存到本地TXT文件
:param goods_list: 商品信息列表
:param keyword: 搜索关键词(用于文件名)
"""
if not goods_list:
print("无商品信息可保存")
return
filename = f"京东_{keyword}_商品列表.txt"
with open(filename, "w", encoding="utf-8") as f:
f.write(f"京东关键词「{keyword}」商品搜索结果\n")
f.write("-" * 100 + "\n")
for index, goods in enumerate(goods_list, 1):
f.write(f"第{index}件商品\n")
f.write(f"商品ID:{goods['商品ID']}\n")
f.write(f"商品名称:{goods['商品名称']}\n")
f.write(f"商品链接:{goods['商品链接']}\n")
f.write(f"店铺名称:{goods['店铺名称']}\n")
f.write("-" * 100 + "\n")
print(f"商品信息已成功保存到:{filename}")
# 主函数调用
if __name__ == "__main__":
target_keyword = "Python书籍" # 自定义搜索关键词
target_page = 1 # 自定义页码(奇数)
# 爬取商品信息
jd_goods = get_jd_goods(keyword=target_keyword, page=target_page)
# 保存到本地
if jd_goods:
save_goods_to_txt(goods_list=jd_goods, keyword=target_keyword)
else:
print("未爬取到任何商品信息")
版本 2:优化版(补充准确价格获取)
由于京东静态页面价格为空,需单独请求价格接口获取准确价格,优化后的核心代码如下(仅修改价格提取部分):
python
运行
# 新增:获取商品准确价格的函数
def get_goods_price(goods_id):
"""
调用京东价格接口,获取商品准确价格
:param goods_id: 商品ID(data-sku)
:return: 商品价格
"""
price_url = f"https://p.3.cn/prices/mgets"
params = {
"skuIds": f"J_{goods_id}", # 价格接口需要J_前缀+商品ID
"type": "1"
}
headers = {
"User-Agent": UserAgent().random,
"Referer": "https://search.jd.com/"
}
try:
response = requests.get(price_url, params=params, headers=headers, timeout=10)
response.raise_for_status()
price_data = response.json()
return price_data[0].get("p", "未知价格") if price_data else "未知价格"
except Exception as e:
print(f"获取商品{goods_id}价格失败:{e}")
return "未知价格"
# 修改解析部分,添加价格获取
# 在for item in goods_items: 循环中,添加:
goods_price = get_goods_price(goods_id)
# 然后在goods_info中补充:
"商品价格": f"{goods_price} 元"
五、反爬策略与注意事项
1. 核心反爬应对措施
- 随机 User-Agent :使用
fake-useragent生成不同浏览器的 UA,避免固定 UA 被识别为爬虫。 - 请求延时 :通过
time.sleep(2)添加 2 秒延时,模拟人类浏览节奏,避免高频请求。 - 完整请求头 :补充
Referer、Accept-Language等字段,让请求更接近浏览器行为。 - 避免重定向 :设置
allow_redirects=False,防止被京东重定向到验证页面。 - 分页爬取限制:若需爬取多页,页码递增间隔≥5 秒,且总页数不超过 5 页(仅用于学习)。
2. 常见问题与解决方案
- 问题 1 :中文乱码。解决方案:指定
response.encoding = "utf-8",保存文件时指定encoding="utf-8"。 - 问题 2:返回空商品列表。解决方案:检查页码是否为奇数、请求头是否完整、是否被京东限制(可更换关键词或重启网络)。
- 问题 3 :价格接口返回空值。解决方案:增加价格接口请求延时、更换 UA,部分商品需登录后才能获取价格(进阶需求可使用
requests.Session()保持登录状态)。
六、后续扩展方向
- 数据持久化:将商品信息保存到 CSV、Excel 或 MySQL 数据库,方便后续分析。
- 多页爬取:实现自动遍历多页(1、3、5...),批量获取商品列表。
- 多线程 / 异步爬取 :使用
threading或aiohttp提高爬取效率(需严格控制并发量,避免反爬)。 - 商品详情页爬取:通过商品链接,进一步爬取商品参数、评价等信息。
- 反爬进阶 :处理京东的验证码、Cookie 验证(可使用
selenium模拟浏览器,但效率较低,仅用于学习)。
总结
- 京东爬虫核心是构造合法请求、定位商品标签、规避反爬检测,基础版可满足个人学习的信息提取需求。
- 动态加载的价格需单独请求专用接口,这是电商平台爬虫的常见特点。
- 爬虫的核心原则是 "低调"------ 低频率、低并发、非商用,避免触碰平台红线和法律边界。
- 本实战的代码可直接运行,修改
target_keyword即可爬取不同商品,运行后会在当前目录生成 TXT 格式的商品列表文件。