58 同城 item_search 接口(官方标准命名 58 同城.item.search)是按多维度条件筛选本地生活全品类信息列表的核心检索接口,覆盖房产、招聘、二手车、二手物品、家政服务等主流业务线。该接口采用 HTTPS+AppKey/Secret 签名认证,支持 JSON/XML 双格式返回,具备筛选维度丰富、多业务线适配、数据实时性强的特点,是联动 item_get 接口获取详情的前置依赖。本攻略从接口认知、权限准备、实操对接、调试排错到生产级优化,提供全链路标准化指导。
一、接口核心认知:功能与适配场景
1. 接口定位与核心价值
核心功能:输入城市编码、业务线分类、关键词、价格区间等筛选条件,返回分页信息列表;支持按发布时间、价格、热度等维度排序,单页最大返回 50 条数据;可联动
city_list接口获取标准城市编码,实现精准地域筛选。58 同城数据特性
多业务线统一适配:一套接口支持所有本地生活品类检索,无需为不同业务线单独对接接口,降低集成成本;
筛选维度贴合用户需求:针对不同品类提供专属筛选条件(如房产支持户型 / 朝向筛选、二手车支持品牌 / 里程筛选);
数据实时性强:信息上架、下架、价格调整等动态数据1 分钟内同步,保障列表数据时效性;
权限分级管控:基础列表数据对所有权限开放,敏感筛选条件(如个人房源、急售信息)需企业资质授权。
典型应用场景
本地生活服务平台:构建多品类信息检索页面,支持用户按城市、品类、价格等条件筛选;
垂直领域获客工具:针对房产 / 招聘 / 二手车等单一品类,批量获取信息列表,生成目标客户清单;
市场行情分析系统:定时检索指定品类信息,统计价格走势、供需变化等市场数据;
个性化推荐工具:基于用户历史筛选行为,推送相似条件的信息列表。
2. 核心参数与返回字段
(1)请求参数(GET/POST 提交,需签名认证)
| 参数类型 | 参数名称 | 类型 | 是否必填 | 说明 | 应用示例 |
|---|---|---|---|---|---|
| 公共参数 | app_key | string | 是 | 应用密钥(开放平台获取) | 58_appkey_2026_abc123 |
| secret | string | 是 | 应用秘钥(开放平台获取) | 58_secret_2026_def456 |
|
| api_name | string | 是 | 接口名称,固定为item_search |
58同城.item.search |
|
| format | string | 否 | 响应格式,默认 JSON | json/xml |
|
| v | string | 是 | 接口版本,固定为1.0 |
1.0 |
|
| timestamp | string | 是 | 秒级时间戳,与服务器时差≤10 分钟 | 1735689600 |
|
| 业务参数 | city_id | string | 是 | 城市编码(从city_list接口获取) |
1(北京)/2(上海) |
| cate_id | string | 是 | 业务线分类 ID | 1(房产)/2(招聘)/3(二手车) |
|
| q | string | 否 | 搜索关键词,需 URL 编码 | 两室一厅 地铁房/二手车 大众 |
|
| price_min | float | 否 | 最低价格(单位随品类变化) | 房产(万元)/ 招聘(元 / 月)/ 二手车(万元) | |
| price_max | float | 否 | 最高价格 | 同上 | |
| sort_type | string | 否 | 排序方式 | pub_time_desc(最新发布)/price_asc(低价优先)/hot_desc(热度优先) |
|
| page_num | int | 否 | 页码,默认 1 | 2 |
|
| page_size | int | 否 | 单页条数,默认 20,最大 50 | 50 |
|
| filter | string | 否 | 品类专属筛选条件(JSON 格式) | 房产:{"house_style":"2室1厅","orientation":"南向"} |
注意事项
city_id和cate_id为必填业务参数,需分别从city_list接口和开放平台品类文档获取标准值;
timestamp参数为秒级时间戳,与服务器时间误差超过 10 分钟会直接导致签名验证失败;
filter参数需为标准 JSON 字符串,不同品类的筛选字段不同,需参考官方文档传入;签名生成需包含所有非空参数,按参数名 ASCII 升序排序后拼接
secret进行 MD5 加密,参数缺失会导致认证失败。
(2)返回核心字段(按业务线分类)
| 字段分类 | 核心字段 | 说明 |
|---|---|---|
| 公共字段 | item_id、title、cate_name、price、publish_time、update_time、status、view_count、support_tags | status:有效 / 已下架 / 审核中;support_tags:配套标签列表 |
| 房产类 | house_style、area_build、orientation、floor、metro_tag | metro_tag:是否地铁房(是 / 否) |
| 招聘类 | company_name、salary、work_address、job_type | salary:薪资范围(如 “5000-8000 元 / 月”) |
| 二手车类 | brand、model、year、mileage、displacement | year:上牌年份;mileage:万公里数 |
| 二手物品类 | new_degree、address | new_degree:新旧程度(如 “9 成新”) |
| 分页信息 | total、page_num、page_size、has_next | total:搜索结果总条数;has_next:是否有下一页 |
提示:
item_search接口仅返回信息基础属性,联系人、详细地址、媒体资源等深度信息需调用item_get接口获取。
3. 接口限制与注意事项
| 权限类型 | 日调用上限 | 调用频率 | 适用场景 |
|---|---|---|---|
| 个人测试权限 | 200 次 / 天 | 2 次 / 秒 | 功能调试、个人信息查询 |
| 企业基础权限 | 2000 次 / 天 | 5 次 / 秒 | 中小型本地服务平台、中介系统 |
| 企业高级权限 | 20000 次 / 天 | 15 次 / 秒 | 大型数据服务商、全国性本地生活平台 |
数据缓存规则:列表数据缓存10 分钟,短时间内重复调用相同筛选条件的接口会直接返回缓存数据;
调用频率限制:超出频率上限会触发临时封禁 15 分钟,多次超限会导致账号权限降级;
地域限制:部分城市的房产、招聘信息受本地监管政策限制,仅对本地备案企业开放;
合规要求:数据仅可用于自有平台展示或合法商业分析,严禁转售、篡改或用于骚扰式营销。
二、对接前准备:权限与环境搭建
1. 获取接口权限(官方唯一合规路径)
58 同城 item_search 接口的权限需通过58 同城开放平台申请,步骤如下:
登录 58 同城开放平台,注册企业 / 个人开发者账号;
提交资质审核:
企业用户:上传营业执照、法人身份证、业务范围说明(如 “本地生活信息平台开发”);
个人用户:上传身份证,填写应用用途(如 “个人租房信息检索工具”);
创建应用,填写应用名称、服务器 IP 白名单、数据用途说明,提交审核;
审核通过后,在 “应用管理 - 密钥管理” 中获取
app_key和secret(接口调用核心凭证);申请
58同城.item.search接口权限,基础权限审核周期为 1-3 个工作日,高级权限需额外提交《数据合规使用承诺书》。
风险提示:严禁通过非官方爬虫抓取 58 同城列表数据,违反协议会导致账号封禁并承担法律责任。
2. 技术环境准备
(1)支持语言与协议
协议:HTTPS(强制),HTTP 请求会被直接拦截并返回 403 错误;
开发语言:Python、Java、PHP、Go 等主流语言均可,推荐 Python(代码简洁,适配异步并发与多品类数据解析)。
(2)必备工具与依赖
| 工具类型 | 推荐工具 | 用途 |
|---|---|---|
| 调试工具 | 58 同城开放平台调试工具 | 在线填写参数、生成签名、测试接口响应 |
| Postman | 模拟 GET/POST 请求,保存不同品类的筛选测试用例 | |
| 开发依赖(Python) | requests | 发送 HTTPS 请求 |
| hashlib | 生成 MD5 签名 | |
| jsonpath-ng | 快速解析 JSON 格式的列表数据 | |
| pandas | 整理多品类信息列表并导出 Excel | |
| 辅助工具 | Redis | 缓存搜索结果,减少重复调用 |
| logging | 记录接口调用日志,便于问题排查与审计 |
三、实操步骤:接口对接全流程(Python 示例)
步骤 1:理解签名认证规则(核心,必掌握)
58 同城所有接口采用统一的 app_key+secret+timestamp 签名认证 机制,item_search 接口的签名生成步骤如下:
收集所有非空请求参数(含公共参数
app_key/api_name/timestamp等 + 业务参数city_id/cate_id等);按参数名ASCII 升序排序(如
api_name排在app_key之前);拼接参数为
key1value1key2value2...的字符串格式(无分隔符,参数值需与传入一致);将
secret拼接在参数串末尾,生成签名原串;对原串进行 MD5 加密,转为大写字符串,即为签名
sign;将
sign添加到请求参数中,发送 HTTPS GET 请求。
步骤 2:完整代码实现(含签名生成 + 多品类适配 + 数据标准化)
(1)依赖安装
(2)Python 代码实现
import requests
import hashlib
import time
import json
import logging
import pandas as pd
from urllib.parse import quote
from typing import Optional, Dict, List
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
# 日志配置:记录调用日志,便于问题排查与审计
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[logging.FileHandler("58_item_search.log"), logging.StreamHandler()]
)
# 配置信息(替换为你的开放平台app_key/secret)
CONFIG = {
"app_key": "你的app_key",
"secret": "你的secret",
"api_url": "https://openapi.58.com/item_search",
"format": "json",
"version": "1.0"
}
# 业务线分类映射(参考58开放平台文档)
CATE_MAP = {
"1": "房产",
"2": "招聘",
"3": "二手车",
"4": "二手物品"
}
def generate_sign(params: Dict[str, str], secret: str) -> str:
"""生成58同城接口签名(MD5加密,大写)"""
# 1. 按参数名ASCII升序排序
sorted_params = sorted(params.items(), key=lambda x: x[0])
# 2. 拼接参数为 key1value1key2value2 格式
param_str = "".join([f"{k}{v}" for k, v in sorted_params])
# 3. 拼接secret并MD5加密,转大写
sign_str = param_str + secret
sign = hashlib.md5(sign_str.encode("utf-8")).hexdigest().upper()
return sign
def standardize_item_data(raw_item: Dict, cate_id: str) -> Dict:
"""标准化信息列表数据,适配不同业务线"""
# 公共字段标准化
standard_data = {
"信息ID": raw_item.get("item_id", ""),
"标题": raw_item.get("title", ""),
"业务线": CATE_MAP.get(cate_id, "未知"),
"分类名称": raw_item.get("cate_name", ""),
"发布时间": raw_item.get("publish_time", ""),
"更新时间": raw_item.get("update_time", ""),
"信息状态": raw_item.get("status", ""),
"浏览量": raw_item.get("view_count", 0),
"配套标签": ",".join(raw_item.get("support_tags", [])),
"数据请求时间": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
}
# 价格字段适配(不同业务线单位不同)
price = raw_item.get("price", 0.0)
if cate_id == "1": # 房产
price_unit = "万元" if raw_item.get("cate_name") in ["新房", "二手房"] else "元/月"
elif cate_id == "2": # 招聘
price_unit = "元/月"
price = raw_item.get("salary", "面议")
elif cate_id == "3": # 二手车
price_unit = "万元"
else: # 二手物品
price_unit = "元"
standard_data["价格"] = f"{price}{price_unit}" if isinstance(price, (int, float)) else price
# 品类专属字段适配
if cate_id == "1": # 房产
standard_data.update({
"户型": raw_item.get("house_style", ""),
"建筑面积(㎡)": raw_item.get("area_build", 0.0),
"朝向": raw_item.get("orientation", ""),
"楼层": raw_item.get("floor", ""),
"是否地铁房": raw_item.get("metro_tag", "否")
})
elif cate_id == "2": # 招聘
standard_data.update({
"公司名称": raw_item.get("company_name", ""),
"工作地址": raw_item.get("work_address", ""),
"职位类型": raw_item.get("job_type", "")
})
elif cate_id == "3": # 二手车
standard_data.update({
"品牌型号": f"{raw_item.get('brand', '')} {raw_item.get('model', '')}",
"上牌年份": raw_item.get("year", ""),
"里程数(万公里)": raw_item.get("mileage", 0.0)
})
elif cate_id == "4": # 二手物品
standard_data.update({
"新旧程度": raw_item.get("new_degree", ""),
"物品地址": raw_item.get("address", "")
})
return standard_data
def item_search_58(
city_id: str,
cate_id: str,
q: Optional[str] = None,
price_min: Optional[float] = None,
price_max: Optional[float] = None,
sort_type: str = "pub_time_desc",
page_num: int = 1,
page_size: int = 20,
filter_json: Optional[Dict] = None
) -> Dict:
"""调用58同城item_search接口获取信息列表"""
# 1. 校验必填参数
if not (city_id and cate_id):
return {"success": False, "error_msg": "city_id和cate_id为必填参数", "data": [], "pagination": {}}
# 2. 构建公共参数
params = {
"app_key": CONFIG["app_key"],
"api_name": "item_search",
"format": CONFIG["format"],
"v": CONFIG["version"],
"timestamp": str(int(time.time())), # 秒级时间戳
"city_id": city_id,
"cate_id": cate_id,
"sort_type": sort_type,
"page_num": str(page_num),
"page_size": str(min(page_size, 50)) # 限制最大条数为50
}
# 3. 添加工业务参数
if q:
params["q"] = quote(q, encoding="utf-8")
if price_min is not None:
params["price_min"] = str(price_min)
if price_max is not None:
params["price_max"] = str(price_max)
if filter_json:
params["filter"] = json.dumps(filter_json, ensure_ascii=False)
# 4. 生成签名
sign = generate_sign(params, CONFIG["secret"])
params["sign"] = sign
try:
# 5. 发送HTTPS请求
response = requests.get(
url=CONFIG["api_url"],
params=params,
timeout=15,
verify=True # 生产环境必须开启证书验证
)
response.raise_for_status() # 抛出HTTP状态码异常
result = response.json()
# 6. 解析响应结果
if result.get("status") != "success":
error_msg = f"[{result.get('error_code', '未知错误')}] {result.get('error_msg', '无错误信息')}"
logging.error(f"搜索失败(城市:{city_id},品类:{cate_id}):{error_msg}")
return {"success": False, "error_msg": error_msg, "data": [], "pagination": {}}
raw_items = result.get("data", {}).get("item_list", [])
pagination = {
"total": result.get("data", {}).get("total", 0),
"page_num": page_num,
"page_size": page_size,
"has_next": result.get("data", {}).get("has_next", False)
}
if not raw_items:
logging.warning(f"无匹配信息(城市:{city_id},品类:{cate_id})")
return {"success": True, "error_msg": "", "data": [], "pagination": pagination}
# 7. 标准化数据
standard_items = [standardize_item_data(item, cate_id) for item in raw_items]
return {
"success": True,
"error_msg": "",
"data": standard_items,
"pagination": pagination
}
except requests.exceptions.RequestException as e:
logging.error(f"网络请求异常(城市:{city_id},品类:{cate_id}):{str(e)}")
return {"success": False, "error_msg": f"网络异常:{str(e)}", "data": [], "pagination": {}}
except Exception as e:
logging.error(f"数据解析异常(城市:{city_id},品类:{cate_id}):{str(e)}")
return {"success": False, "error_msg": f"解析异常:{str(e)}", "data": [], "pagination": {}}
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
# 调用示例
if __name__ == "__main__":
# 示例1:搜索北京市房产类信息(city_id=1,cate_id=1)
# 筛选条件:两室一厅 地铁房 价格50-80万元
city_id = "1" # 北京
cate_id = "1" # 房产
keyword = "两室一厅 地铁房"
price_min = 50.0
price_max = 80.0
# 品类专属筛选条件
filter_json = {
"house_style": "2室1厅",
"orientation": "南向"
}
result = item_search_58(
city_id=city_id,
cate_id=cate_id,
q=keyword,
price_min=price_min,
price_max=price_max,
sort_type="pub_time_desc",
page_num=1,
page_size=20,
filter_json=filter_json
)
if result["success"]:
print(f"搜索成功!共找到 {result['pagination']['total']} 条信息")
print("=== 前5条信息 ===")
for item in result["data"][:5]:
print(f"{item['信息ID']} | {item['标题']} | {item['价格']} | {item['是否地铁房']}")
# 保存为Excel
df = pd.DataFrame(result["data"])
df.to_excel(f"58同城{CATE_MAP[cate_id]}搜索结果_{keyword}.xlsx", index=False)
# 翻页示例
if result["pagination"]["has_next"]:
next_page_result = item_search_58(
city_id=city_id,
cate_id=cate_id,
q=keyword,
price_min=price_min,
price_max=price_max,
page_num=2,
page_size=20,
filter_json=filter_json
)
print(f"下一页获取到 {len(next_page_result['data'])} 条信息")
else:
print(f"获取失败:{result['error_msg']}")四、调试与问题排查:快速解决对接异常
1. 优先用官方工具调试(排除签名与参数问题)
登录 58 同城开放平台调试工具,选择
item_search接口;输入
city_id、cate_id、q等参数,点击 “生成签名” 并发送请求;若官方工具调用成功 → 问题出在代码的签名生成逻辑或参数拼接错误(如关键词未 URL 编码、filter 参数未转 JSON 字符串);
若官方工具调用失败 → 问题出在权限配置或参数有效性(如城市编码错误、IP 未加入白名单)。
2. 高频问题排查表
| 问题现象 | 常见原因 | 解决方案 |
|---|---|---|
| 签名验证失败(401) | 1. app_key/secret 错误或过期;2. 参数未按 ASCII 升序排序;3. timestamp 非秒级或与服务器时差 > 10 分钟;4. filter 参数非标准 JSON 字符串 | 1. 核对开放平台的 app_key/secret,过期则重新申请;2. 严格按参数名 ASCII 升序排序所有非空参数;3. 确保 timestamp 为秒级时间戳,同步服务器时间;4. 将 filter 字典转为标准 JSON 字符串,避免特殊字符 |
| 权限不足(403) | 1. 未申请item_search接口权限;2. 服务器 IP 不在白名单;3. 调用频率超限;4. 使用敏感筛选条件但无高级权限 | 1. 在开放平台 “权限管理” 中申请对应接口;2. 添加服务器公网 IP 到应用白名单;3. 降低调用频率,控制并发数≤权限上限;4. 移除敏感筛选条件或升级企业高级权限 |
| 参数错误(400) | 1. city_id/cate_id 为空或非法;2. price_min > price_max;3. filter 参数字段与 cate_id 不匹配 | 1. 从city_list接口获取标准城市编码,参考文档确认 cate_id;2. 校验价格区间合法性,确保 price_min ≤ price_max;3. 仅传入当前品类支持的筛选字段,参考官方文档 |
| 无数据返回(200 但 data 为空) | 1. 筛选条件过严(如价格区间过小);2. city_id 正确但无对应品类信息;3. 信息受地域监管限制 | 1. 放宽筛选条件(如扩大价格区间、移除部分 filter 字段);2. 更换 city_id 或 cate_id 测试;3. 联系开放平台客服确认地域权限 |
| 响应超时(504) | 1. 网络波动或服务器负载高;2. page_size 设置过大(如 50)且筛选结果多;3. 高峰期调用(工作日 9:00-12:00/14:00-18:00) | 1. 添加重试机制,设置超时时间为 15 秒;2. 减小 page_size(如改为 20),分批次获取数据;3. 避开高峰期调用,调度到凌晨低峰期 |
五、进阶优化:生产级稳定性提升
1. 性能与配额优化
批量翻页优化:通过
pagination.has_next字段判断是否继续翻页,采用 异步并发框架(如 Python 的aiohttp)批量获取多页数据,并发数严格控制在权限允许的频率上限内(如企业基础权限 5 次 / 秒);避免同步循环翻页导致的效率低下。智能缓存策略:用 Redis 缓存搜索结果,缓存 key 设计为
58_search_城市ID_品类ID_关键词_价格区间,缓存时间区分场景:热门城市 / 高频关键词:缓存 10 分钟;
冷门城市 / 低频关键词:缓存 30 分钟;
缓存失效触发条件:当接口返回的
total数据量变化超过 10% 时,主动更新缓存。筛选条件预处理:前端筛选组件做参数合法性校验,例如:
限制
price_min≤price_max;仅展示当前品类支持的筛选字段;
对关键词做长度和敏感词过滤;
减少无效的接口调用。
2. 数据质量优化
数据清洗与标准化:
按
item_id去重,避免同一信息重复出现在不同页码或不同筛选条件的结果中;过滤异常值(如价格≤0、面积≤0 的房产信息);
统一字段格式(如薪资范围统一为 “X-Y 元 / 月”,新旧程度统一为 “X 成新”);
缺失值填充(如无朝向信息的房产填充为 “未知朝向”)。
多品类适配优化:根据
cate_id动态解析和展示字段,避免非目标品类字段干扰(如查询二手车时隐藏房产相关字段)。
3. 合规与安全优化
密钥安全管理:生产环境禁止硬编码 app_key/secret,推荐两种存储方式:
配置中心存储:将密钥存入 Nacos、Apollo 等配置中心,应用启动时动态拉取;
环境变量存储:通过
os.environ.get("58_APP_KEY")读取,避免代码泄露风险;定期轮换密钥(建议每 3 个月一次)。
重试与熔断机制:
对临时性错误(403 频率超限、504 超时),采用指数退避重试策略(首次间隔 1 秒,之后翻倍,最多重试 3 次);
对永久性错误(401 签名错误、400 参数错误),直接抛出异常,不重试;
引入熔断机制(如
pybreaker库),当接口连续失败次数≥5 次时,暂停调用 5 分钟,避免雪崩效应。日志审计:记录每次调用的城市 ID、品类 ID、筛选条件、响应状态、耗时、返回数据量等信息,日志保留至少 30 天,满足合规审计要求。
六、扩展场景:接口联动与功能升级
全链路数据采集:联动
city_list获取城市编码 →item_search按城市 / 品类筛选信息列表 →item_get批量获取详情,实现 “城市→列表→详情” 的完整数据链路;本地生活服务平台搭建:整合多品类搜索结果,搭建一站式本地生活检索平台,支持用户按城市、品类、价格等条件筛选和比价;
信息监控预警系统:定时调用
item_search接口,监控指定品类的信息发布、价格变化,当出现符合条件的信息(如低价二手房、高薪职位)时,通过邮件 / 短信推送预警;商家获客智能助手:针对二手物品、家政服务等品类,批量获取信息列表,筛选高意向客户(如价格低于市场价的卖家),辅助商家精准跟进。