服装网(聚焦服饰、鞋包、配饰等时尚品类)的商品搜索功能(item_search接口,非官方命名)是获取服装类商品列表的核心入口。数据包含风格标签、尺码范围、材质成分、价格区间等时尚特有字段,对电商选品、潮流分析、比价工具等场景具有关键价值。由于平台无公开官方 API,开发者需通过页面解析实现搜索对接。本文系统讲解接口逻辑、参数解析、技术实现及时尚场景适配策略,助你构建稳定的服装商品列表获取系统。
一、接口基础认知(核心功能与场景)
核心功能服装网item_search接口通过关键词、分类、风格、价格等条件筛选商品,返回符合条件的列表数据,核心字段聚焦时尚特性:
基础信息:商品 ID(item_id)、标题(含风格 / 季节,如 “2024 秋季复古风衣”)、主图、品牌、类目(如 “女装 > 外套”)、详情页 URL
价格信息:当前价、原价、优惠标签(如 “限时 8 折”)、价格区间(多规格商品)
规格摘要:核心尺码(如 “S/M/L”)、颜色选项(如 “黑 / 白 / 粉”)、库存状态(如 “现货”“预售”)
商品特性:风格标签(如 “通勤”“甜辣”)、材质关键词(如 “纯棉”“真皮”)、适用季节、版型(如 “宽松”“修身”)
热度数据:销量(如 “月销 1000+”)、收藏数、评分(如 “4.8 分”)
典型应用场景
电商选品工具:搜索 “冬季羽绒服”,按 “90% 白鸭绒 + 修身版型” 筛选高性价比款式
潮流趋势分析:跟踪 “牛仔裤” 的风格标签变化(如 “直筒→微喇”),预测流行趋势
精准营销:筛选 “大码女装” 类目下 “通勤风格 + 价格 200-500 元” 的商品,定向推送目标用户
比价监控:对比同款连衣裙在不同平台的价格、优惠活动及库存状态
接口特性
时尚导向性:筛选条件与数据字段深度结合服饰场景(如 “风格”“版型”“材质”)
非官方性:依赖 HTML 解析,无公开 API,动态加载内容多(如分页数据、筛选条件联动)
反爬机制:包含 IP 限制(高频请求封锁)、User-Agent 校验、Cookie 验证(部分价格 / 库存需登录)
分页结构:默认每页 40 条,最多支持 50 页(约 2000 条结果),分页参数通过 URL 传递
多维度筛选:支持按分类、价格、风格、材质、尺码、发货地等多条件组合筛选
二、对接前置准备(参数与 URL 结构)
开发环境
开发语言:Python(推荐,适合处理动态筛选与反爬)
核心库:
网络请求:requests(同步)、aiohttp(异步批量搜索)
页面解析:BeautifulSoup(静态 HTML)、lxml(XPath 提取列表数据)
反爬工具:fake_useragent(随机 UA)、proxy_pool(代理 IP 池)
数据处理:re(正则提取销量、价格)、urllib.parse(URL 参数编码)
搜索 URL 结构与核心参数服装网搜索页基础 URL 为:https://www.fuzhuang.com/search/,核心参数通过查询字符串传递:
筛选条件 参数名 示例值 说明
关键词 keyword 羽绒服 → 编码后为%E7%BE%BD%E7%BB%92%E6%9C%8D 支持商品名、风格(如 “通勤风”)、材质(如 “纯棉”)
分类 ID cat_id 101(女装)、203(男鞋) 分类 ID 需从导航栏解析获取(如 “女装> 外套” 对应101_305)
价格区间(始) price_min 200 最低单价(元)
价格区间(终) price_max 500 最高单价(元)
风格 style 通勤 → 编码后为%E9%80%9A%E5%8B%89 支持多风格(用逗号分隔,如 “通勤,复古”)
材质 material 棉、真皮 单一材质(如 “棉”)或组合(如 “棉 + 聚酯纤维”)
尺码范围 size_range 大码、均码 筛选特定尺码商品(如 “大码” 含 XL 及以上)
库存状态 stock 1(现货)、2(预售) 区分现货与预售商品
排序方式 sort price_asc(价格升序)、sales(销量降序) 见 “排序参数表”
分页 page 1 2 ... 50 页码,默认 1,最大 50
排序参数表服装网搜索支持时尚电商常用排序方式,对应sort参数值如下:
排序方式 sort参数值 适用场景
综合推荐 空值 默认排序,平衡相关性与热度
价格升序 price_asc 平价商品筛选(如基础款 T 恤)
价格降序 price_desc 高端商品筛选(如真皮包包)
销量降序 sales 爆款商品筛选(如当季流行款)
最新上架 new 新品趋势跟踪(如季节新款)
好评优先 rating 品质优先筛选(如高评分连衣裙)
分类 ID 与风格映射
分类 ID:访问服装网分类页(https://www.fuzhuang.com/category/),通过开发者工具查看类目链接的href(如/category/101_305/中101_305为 “女装> 外套” 的 ID);
风格映射:通过搜索页筛选栏的 “风格” 选项提取关键词(如 “通勤”“甜辣”“复古”),直接作为style参数值(需 URL 编码)。
三、接口调用流程(基于页面解析)
以 “搜索 200-500 元的通勤风格纯棉连衣裙,仅看现货,按销量降序排序” 为例,流程为参数组装→URL 构建→请求发送→列表解析→分页遍历:
URL 构建示例组合参数生成目标搜索 URL:
python
运行
keyword = "连衣裙"
cat_id = "101_208" # 女装>连衣裙分类ID
price_min = 200
price_max = 500
style = "通勤" # 风格
material = "棉" # 材质
stock = 1 # 仅现货
sort = "sales" # 销量降序
page = 1
关键词与风格URL编码
encoded_keyword = urllib.parse.quote(keyword, encoding="utf-8")
encoded_style = urllib.parse.quote(style, encoding="utf-8")
构建URL
url = f"https://www.fuzhuang.com/search/?keyword={encoded_keyword}&cat_id={cat_id}&price_min={price_min}&price_max={price_max}&style={encoded_style}&material={material}&stock={stock}&sort={sort}&page={page}"
请求头与反爬伪装模拟用户浏览行为,需包含登录态 Cookie 以获取完整价格和库存信息:
python
运行
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
"Referer": "https://www.fuzhuang.com/category/women/",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8",
"Cookie": "session_id=xxx; user_id=xxx" # 登录后从浏览器获取
}
页面解析与数据提取搜索结果列表通常在 HTML 的
字段 解析方式(CSS 选择器示例) 说明
商品 ID 从a标签的href中提取(如/item/123.html得123) 唯一标识
标题 .product-title的文本 如 “2024 秋季纯棉通勤连衣裙 修身”
主图 .product-img img的src属性 商品主图 URL
价格 .price-current的文本(去除 “¥”) 如 “359.00”(元)
风格标签 .style-tags span的文本列表 如["通勤", "修身", "秋季"]
规格摘要 .spec-brief的文本 如 “颜色:黑 / 白 / 灰 尺码:S-L”
销量 .sales-count的文本(提取数字) 如 “月销 890” 提取 “890”
品牌 .brand-name的文本 如 “XX 女装”
库存状态 .stock-tag的文本 如 “现货”“预售(7 天发)”
分页处理
分页通过page参数控制,前 50 页为有效数据,超过则返回空结果;
终止条件:当前页商品数量 < 40(最后一页)或页码≥50;
分页间隔:每页请求间隔 2-4 秒(随机波动),避免触发反爬(服装网对高频搜索敏感)。
四、代码实现示例(Python)
以下是item_search接口的完整实现,包含多条件筛选、分页遍历、数据解析及反爬处理:
import requests
import time
import random
import re
import urllib.parse
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
from typing import List, Dict
class FuzhuangSearchApi:
def init(self, proxy_pool: List[str] = None, cookie: str = ""):
self.base_url = "https://www.fuzhuang.com/search/"
self.ua = UserAgent()
self.proxy_pool = proxy_pool # 代理池列表,如["http://ip:port", ...]
self.cookie = cookie # 登录态Cookie(用于完整价格和库存)
# 分类ID映射(简化版)
self.category_map = {
"女装-连衣裙": "101_208",
"男装-牛仔裤": "301_402",
"女鞋-马丁靴": "501_603"
}
def _get_headers(self) -> Dict[str, str]:
"""生成随机请求头"""
headers = {
"User-Agent": self.ua.random,
"Referer": "https://www.fuzhuang.com/category/",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
}
if self.cookie:
headers["Cookie"] = self.cookie
return headers
def _get_proxy(self) -> Dict[str, str]:
"""随机获取代理"""
if self.proxy_pool and len(self.proxy_pool) > 0:
proxy = random.choice(self.proxy_pool)
return {"http": proxy, "https": proxy}
return None
def _clean_price(self, price_str: str) -> float:
"""清洗价格字符串(去除¥、文字)"""
if not price_str:
return 0.0
price_str = re.sub(r"[^\d.]", "", price_str)
return float(price_str) if price_str else 0.0
def _clean_sales(self, sales_str: str) -> int:
"""清洗销量(提取数字,支持“1000+”)"""
if not sales_str:
return 0
sales_num = re.search(r"\d+", sales_str)
return int(sales_num.group()) if sales_num else 0
def _parse_item(self, item_soup) -> Dict[str, str]:
"""解析单条商品数据"""
# 提取商品ID
link = item_soup.select_one("a.product-title")["href"] if item_soup.select_one("a.product-title") else ""
item_id = re.search(r"/item/(\w+)\.html", link).group(1) if link else ""
# 提取风格标签
style_tags = [tag.text.strip() for tag in item_soup.select(".style-tags span")]
# 提取规格摘要(颜色+尺码)
spec_brief = item_soup.select_one(".spec-brief")?.text.strip() or ""
colors = []
sizes = []
if "颜色:" in spec_brief:
colors_part = re.split(r"颜色:", spec_brief)[1].split("|")[0].strip()
colors = [c.strip() for c in colors_part.split("/")]
if "尺码:" in spec_brief:
sizes_part = re.split(r"尺码:", spec_brief)[1].strip()
sizes = [s.strip() for s in sizes_part.split("/")]
return {
"item_id": item_id,
"title": item_soup.select_one(".product-title")?.text.strip() or "",
"main_image": item_soup.select_one(".product-img img")?.get("src") or "",
"url": f"https://www.fuzhuang.com{link}" if link.startswith("/") else link,
"price": {
"current": self._clean_price(item_soup.select_one(".price-current")?.text or ""),
"original": self._clean_price(item_soup.select_one(".price-original")?.text or "")
},
"style_tags": style_tags,
"specs": {
"colors": colors,
"sizes": sizes
},
"brand": item_soup.select_one(".brand-name")?.text.strip() or "",
"sales": {
"count": self._clean_sales(item_soup.select_one(".sales-count")?.text or ""),
"unit": "月销" if "月销" in (item_soup.select_one(".sales-count")?.text or "") else "总销"
},
"stock_status": item_soup.select_one(".stock-tag")?.text.strip() or "",
"rating": float(item_soup.select_one(".product-rating")?.text or "0")
}
def _parse_page(self, html: str) -> List[Dict]:
"""解析页面的商品列表"""
soup = BeautifulSoup(html, "lxml")
# 商品列表容器(需根据实际页面结构调整)
item_list = soup.select("div.product-item")
return [self._parse_item(item) for item in item_list if item]
def _get_total_pages(self, html: str) -> int:
"""获取总页数"""
soup = BeautifulSoup(html, "lxml")
page_box = soup.select_one(".pagination")
if not page_box:
return 1
# 提取最后一页页码
last_page = page_box.select("a")[-1].text.strip()
return int(last_page) if last_page.isdigit() else 1
def item_search(self,
keyword: str = "",
category: str = "",
price_min: float = None,
price_max: float = None,
style: List[str] = None,
material: str = "",
size_range: str = "",
stock: int = 0,
sort: str = "",
page_limit: int = 5) -> Dict:
"""
搜索服装网商品列表
:param keyword: 搜索关键词
:param category: 分类名称(如“女装-连衣裙”)或分类ID
:param price_min: 最低价格(元)
:param price_max: 最高价格(元)
:param style: 风格列表(如["通勤", "复古"])
:param material: 材质(如“棉”“真皮”)
:param size_range: 尺码范围(如“大码”“均码”)
:param stock: 库存状态(1=现货,2=预售,0=全部)
:param sort: 排序方式(price_asc/sales等)
:param page_limit: 最大页数(默认5)
:return: 标准化搜索结果
"""
try:
# 1. 参数预处理
if not keyword and not category:
return {"success": False, "error_msg": "关键词(keyword)和分类(category)至少需提供一个"}
# 转换分类名称为ID
if category in self.category_map:
cat_id = self.category_map[category]
else:
cat_id = category if category else ""
# 处理风格参数(多风格用逗号分隔并编码)
style_str = ""
if style and len(style) > 0:
encoded_styles = [urllib.parse.quote(s, encoding="utf-8") for s in style]
style_str = ",".join(encoded_styles)
# 编码关键词
encoded_keyword = urllib.parse.quote(keyword, encoding="utf-8") if keyword else ""
all_items = []
current_page = 1
while current_page <= page_limit:
# 构建参数
params = {
"page": current_page
}
if encoded_keyword:
params["keyword"] = encoded_keyword
if cat_id:
params["cat_id"] = cat_id
if price_min is not None:
params["price_min"] = price_min
if price_max is not None:
params["price_max"] = price_max
if style_str:
params["style"] = style_str
if material:
params["material"] = material
if size_range:
params["size_range"] = size_range
if stock in (0, 1, 2):
params["stock"] = stock
if sort:
params["sort"] = sort
# 发送请求(带随机延迟)
time.sleep(random.uniform(2, 4)) # 服装网反爬较严,延迟需适中
headers = self._get_headers()
proxy = self._get_proxy()
response = requests.get(
url=self.base_url,
params=params,
headers=headers,
proxies=proxy,
timeout=10
)
response.raise_for_status()
html = response.text
# 解析当前页商品
items = self._parse_page(html)
if not items:
break # 无数据,终止分页
all_items.extend(items)
# 获取总页数(仅第一页需要)
if current_page == 1:
total_pages = self._get_total_pages(html)
# 修正最大页数(不超过page_limit和50)
total_pages = min(total_pages, page_limit, 50)
if total_pages < current_page:
break
# 若当前页是最后一页,终止
if current_page >= total_pages:
break
current_page += 1
# 去重(基于item_id)
seen_ids = set()
unique_items = []
for item in all_items:
if item["item_id"] not in seen_ids:
seen_ids.add(item["item_id"])
unique_items.append(item)
return {
"success": True,
"total": len(unique_items),
"page_processed": current_page,
"items": unique_items
}
except requests.exceptions.HTTPError as e:
if "403" in str(e):
return {"success": False, "error_msg": "触发反爬,建议更换代理或Cookie", "code": 403}
if "401" in str(e):
return {"success": False, "error_msg": "需要登录,请提供有效Cookie", "code": 401}
return {"success": False, "error_msg": f"HTTP错误: {str(e)}", "code": response.status_code}
except Exception as e:
return {"success": False, "error_msg": f"搜索失败: {str(e)}", "code": -1}
使用示例
if name == "main":
# 代理池(替换为有效代理)
PROXIES = [
"http://123.45.67.89:8888",
"http://98.76.54.32:8080"
]
# 登录态Cookie(从浏览器获取,用于完整价格)
COOKIE = "session_id=xxx; user_id=xxx"
# 初始化API客户端
search_api = FuzhuangSearchApi(proxy_pool=PROXIES, cookie=COOKIE)
# 搜索“连衣裙”,分类“女装-连衣裙”,价格200-500元,风格通勤+复古,材质棉,仅现货,按销量降序,最多3页
result = search_api.item_search(
keyword="连衣裙",
category="女装-连衣裙",
price_min=200,
price_max=500,
style=["通勤", "复古"],
material="棉",
stock=1,
sort="sales",
page_limit=3
)
if result["success"]:
print(f"搜索成功:共找到 {result['total']} 件商品,处理 {result['page_processed']} 页")
for i, item in enumerate(result["items"][:5]): # 打印前5条
print(f"\n商品 {i+1}:")
print(f"标题:{item['title'][:50]}...") # 截断长标题
print(f"价格:当前¥{item['price']['current']} | 原价¥{item['price']['original']}")
print(f"风格:{', '.join(item['style_tags'])} | 品牌:{item['brand']}")
print(f"规格:颜色{', '.join(item['specs']['colors'][:3])} | 尺码{', '.join(item['specs']['sizes'][:3])}")
print(f"销售:{item['sales']['unit']}{item['sales']['count']}件 | 评分:{item['rating']}分 | 库存:{item['stock_status']}")
print(f"详情页:{item['url']}")
else:
print(f"搜索失败:{result['error_msg']}(错误码:{result.get('code')})")
五、关键技术难点与解决方案
多维度筛选参数整合
问题:服装搜索依赖多条件组合(如 “风格 + 材质 + 价格”),参数格式多样(需 URL 编码、多值用逗号分隔),易出现拼接错误导致筛选失效。
解决方案:
建立参数预处理函数,自动编码中文关键词(如urllib.parse.quote("通勤"));
多风格参数用逗号拼接(如["通勤", "复古"]→"通勤,复古"),适配平台筛选逻辑;
示例代码中item_search函数对style参数的处理,确保多风格筛选生效。
规格摘要解析(颜色 + 尺码)
问题:列表页的规格信息通常以文本形式展示(如 “颜色:黑 / 白 | 尺码:S-L”),需拆分为结构化的颜色和尺码列表,便于后续筛选。
解决方案:
用正则匹配 “颜色:”“尺码:” 关键词,分割文本提取对应内容;
按 “/” 拆分多值(如 “黑 / 白”→["黑", "白"]),结构化存储为colors和sizes字段;
示例代码中_parse_item函数的specs解析逻辑,支持快速筛选 “含黑色 + 大码” 的商品。
反爬机制对抗
问题:服装网作为时尚电商,对异常搜索行为敏感,高频请求会触发 IP 封锁(403 错误),尤其针对热门风格(如 “通勤风”)的搜索。
解决方案:
代理 IP 策略:使用高匿代理池,每 2 页切换一次 IP,优先选择国内 IP(服装网用户以国内为主);
请求频率控制:单 IP 每分钟请求≤2 次,两次请求间隔 2-4 秒(模拟用户浏览服装的节奏);
Cookie 池管理:维护多个登录态 Cookie(通过不同用户账号获取),随机携带以降低单一账号风险;
动态 UA:每次请求使用fake_useragent生成随机 User-Agent,避免固定标识被识别。
分页数据完整性
问题:服装网搜索结果分页可能存在 “幽灵页”(页码存在但无数据),或因反爬导致中间页数据缺失,影响结果完整性。
解决方案:
第一页解析总页数后,动态调整遍历范围(不超过page_limit和 50);
对每一页返回的商品列表进行校验,若连续 2 页无数据则终止遍历;
实现去重逻辑(基于item_id),避免分页重复数据(部分平台存在重复展示)。
六、最佳实践与合规要点
系统架构设计采用 “分布式低频率采集” 架构,适配服装类商品特性:
任务调度层:通过定时任务(如 Celery)分发搜索任务,控制单任务并发数≤1;
采集层:多节点分散请求,每个节点绑定独立代理池,节点间请求间隔≥10 秒;
存储层:用 Redis 缓存热门搜索结果(2 小时过期,服装价格波动较快),MySQL 存储历史趋势数据(用于潮流分析);
监控层:实时监控代理存活率、筛选条件有效性,异常时通过钉钉告警。
性能优化策略
异步批量搜索:使用aiohttp并发处理多关键词(如 “连衣裙”“半身裙”),控制并发数≤2,适配低频率限制;
按需解析:列表页优先提取item_id、价格、风格标签等核心字段,详细规格通过后续item_get接口补充;
热点抑制:对同一关键词 + 参数组合的搜索,1 小时内仅处理 1 次(返回缓存结果)。
合规性与风险控制
访问限制:单 IP 日搜索请求≤300 次,避免对平台服务器造成压力,符合 robots 协议;
数据使用边界:不得将商品数据用于恶意比价、虚假宣传或侵犯品牌权益,需注明数据来源 “服装网”;
图片版权:服装图片可能涉及品牌版权,使用时需遵守《著作权法》,不得擅自用于商业盈利。
七、总结
服装网item_search接口的对接核心在于多维度筛选参数的精准整合、规格摘要的结构化解析及低频率高稳定性的采集策略。开发者需重点关注:
风格、材质等中文参数的 URL 编码与多值拼接(确保筛选条件生效);
颜色和尺码的文本拆分逻辑(便于后续精准筛选);
代理池与请求频率的精细化控制(应对严格反爬)。
通过本文的技术方案,可构建稳定的服装商品搜索系统,为电商选品、潮流分析等场景提供可靠数据支持。实际应用中,需根据平台最新页面结构动态调整解析规则,平衡数据获取效率与合规性。
需要进一步了解服装分类 ID 的完整映射表或风格关键词的扩展列表,可以告诉我,我会补充相关内容