1. 引言
在电商数据爬取过程中,商品ID(Product ID)是最关键的字段之一,它通常用于唯一标识商品,并可用于构建商品详情页URL、价格监控、库存查询等场景。然而,不同电商网站的HTML结构差异较大,如何高效、精准地定位商品ID成为爬虫开发的重要挑战。
本文将介绍如何使用Python结合XPath技术,精准抓取电商网站的商品ID,涵盖以下内容:
- XPath基础语法:快速掌握XPath的核心用法
- 商品ID的常见位置分析:不同电商网站的ID存储方式
- 实战案例:以京东、淘宝为例,演示XPath定位商品ID
- 优化策略:提高XPath匹配的稳定性和效率
- 完整代码实现:提供可运行的Python爬虫示例
2. XPath基础与商品ID定位思路
2.1 XPath简介
XPath(XML Path Language)是一种用于在XML和HTML文档中定位节点的查询语言。在爬虫开发中,XPath常用于从网页中提取特定数据。
常用XPath语法
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">//</font>**
:从任意层级查找**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">/</font>**
:从根节点查找**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">[@属性="值"]</font>**
:按属性筛选**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">text()</font>**
:获取节点文本**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">contains()</font>**
:模糊匹配
例如:
//div[@class="product"]/@id # 获取class="product"的div的id属性
//a[contains(@href, "product_id")]/@href # 获取包含"product_id"的链接
2.2 商品ID的常见存储方式
电商网站的商品ID通常出现在以下位置:
- HTML标签属性:如
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">data-productid</font>**
、**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">data-id</font>**
- URL参数:如
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">https://item.jd.com/100123456.html</font>**
(ID为**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">100123456</font>**
) - JavaScript变量:如
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">var productId = "123456"</font>**
- Meta标签:如
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);"><meta name="product-id" content="123"></font>**
本文将重点讨论HTML属性和URL参数两种方式的XPath定位方法。
3. 实战案例:京东商品ID抓取
3.1 目标分析
京东的商品ID通常出现在:
- 商品详情页URL:如
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">https://item.jd.com/100012043978.html</font>**
(ID=**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">100012043978</font>**
) - HTML标签属性:如
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">data-sku</font>**
3.2 实现代码
使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">requests</font>**
和**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">lxml</font>**
库进行爬取:
import requests
from lxml import html
def fetch_jd_product_id(url):
# 代理服务器配置
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"
# 构造代理认证信息
proxyMeta = f"http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}"
proxies = {
"http": proxyMeta,
"https": proxyMeta,
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Proxy-Authorization": f"Basic {proxyUser}:{proxyPass}" # 部分代理可能需要此头部
}
try:
# 发送带代理的HTTP请求
response = requests.get(url, headers=headers, proxies=proxies, timeout=10)
if response.status_code != 200:
print(f"请求失败,状态码: {response.status_code}")
return None
# 解析HTML
tree = html.fromstring(response.text)
# 方式1:从URL提取商品ID(适用于京东)
product_id = url.split("/")[-1].split(".")[0]
print(f"从URL提取的商品ID: {product_id}")
# 方式2:从HTML属性提取(如data-sku)
product_id_attr = tree.xpath('//*[@data-sku]/@data-sku')
if product_id_attr:
print(f"从HTML属性提取的商品ID: {product_id_attr[0]}")
return product_id
except requests.exceptions.RequestException as e:
print(f"请求发生异常: {str(e)}")
return None
# 示例:京东商品页
jd_url = "https://item.jd.com/100012043978.html"
fetch_jd_product_id(jd_url)
输出示例
从URL提取的商品ID: 100012043978
从HTML属性提取的商品ID: 100012043978
4. 实战案例:淘宝商品ID抓取
4.1 目标分析
淘宝的商品ID存储方式较为复杂,常见位置:
- URL参数:如
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">https://item.taobao.com/item.htm?id=123456789</font>**
(ID=**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">123456789</font>**
) - JavaScript变量:如
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">itemId: "123456789"</font>**
4.2 实现代码
淘宝有反爬机制,需模拟浏览器访问(使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">selenium</font>**
):
from selenium import webdriver
from lxml import html
import time
def fetch_taobao_product_id(url):
options = webdriver.ChromeOptions()
options.add_argument("--headless") # 无头模式
driver = webdriver.Chrome(options=options)
driver.get(url)
time.sleep(3) # 等待页面加载
# 方式1:从URL提取ID
product_id = url.split("id=")[-1].split("&")[0]
print(f"从URL提取的商品ID: {product_id}")
# 方式2:从HTML解析(淘宝可能动态渲染,需检查JS)
page_source = driver.page_source
tree = html.fromstring(page_source)
# 尝试匹配JS变量(淘宝可能存储为window.g_config.itemId)
js_id = tree.xpath('//script[contains(text(), "itemId")]/text()')
if js_id:
print("从JS变量提取的商品ID:", js_id[0].split("itemId:")[1].split(",")[0].strip(' "'))
driver.quit()
return product_id
# 示例:淘宝商品页
taobao_url = "https://item.taobao.com/item.htm?id=123456789"
fetch_taobao_product_id(taobao_url)
输出示例
从URL提取的商品ID: 123456789
从JS变量提取的商品ID: 123456789
5. XPath优化策略
5.1 提高XPath的稳定性
- 避免绝对路径:如
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">/html/body/div[1]/div[2]/...</font>**
容易因页面变动失效 - 使用
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">contains()</font>**
模糊匹配:如**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">//div[contains(@class, "product")]</font>**
- 结合
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">@class</font>**
和**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">@id</font>**
:如**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">//div[@class="product-info" and @data-id]</font>**
5.2 动态页面的处理
- Selenium/Auto.js:适用于JS渲染的页面(如淘宝)
- Pyppeteer/Playwright:更高效的Headless浏览器方案
5.3 异常处理
try:
product_id = tree.xpath('//div[@data-productid]/@data-productid')[0]
except IndexError:
print("未找到商品ID,尝试备用方案...")
product_id = url.split("id=")[1]
6. 结论
本文介绍了如何利用XPath精准抓取电商商品ID,并提供了京东、淘宝的实战代码。关键点总结:
- 优先从URL提取(如京东、淘宝的URL包含ID)
- 结合HTML属性(如
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">data-sku</font>**
、**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">data-productid</font>**
) - 动态页面需用Selenium(如淘宝的JS渲染)
- 优化XPath表达式(避免绝对路径,使用模糊匹配)