大麦网API实战指南:关键字搜索与详情数据获取全解析

在票务数据采集、演出信息监控等开发场景中,大麦网作为国内领先的演出票务平台,其数据接口具有极高的应用价值。但需明确的是,大麦网未正式开放公共API,当前开发者使用的接口均来自移动端/网页端的抓包分析(非官方接口)。本文将聚焦核心的关键字搜索列表API详情数据API,从接口规范、参数解析、Python调用实现到风险提示进行完整梳理,助力开发者合规高效地获取演出数据。

一、前置认知:大麦网API核心特性

在开始接口调用前,需先掌握大麦网接口的基础特性,避免因参数缺失或格式错误导致调用失败:

  • 认证机制 :公开信息接口(如搜索列表、演出详情)无需登录态,仅需配置标准请求头;涉及购票、订单等敏感操作的接口需携带登录Cookie(核心为damai.cn域名下的SESSIONuserId)。

  • 请求规范 :必须携带User-Agent(模拟移动端/PC端)和Referer(防盗链);部分接口需传入毫秒级时间戳(ts参数),用于防缓存和请求验证。

  • 响应格式 :所有接口均返回JSON格式数据,包含状态码(status)、提示信息(msg)和核心数据(如pageData)三大核心字段。

  • 稳定性风险:非官方接口可能随时调整参数格式或接口地址,建议做好异常捕获和动态适配;同时需控制请求频率,避免IP被封禁。

二、核心接口解析

本文重点解析两个最常用的公开接口:关键字搜索列表API (获取符合关键词的演出列表)和详情数据API(获取单场演出的详细信息),以下均为抓包验证后的可用接口规范。

2.1 关键字搜索列表API

该接口用于根据关键词、城市、品类等条件搜索演出,返回分页的演出列表数据(含演出ID、名称、时间、场馆等基础信息)。

2.1.1 接口信息
  • 请求URL:https://search.damai.cn/searchajax.html

  • 请求方法:GET

  • 是否需要登录:否

2.1.2 核心请求参数
参数名 类型 是否必须 示例值 描述
city String 101010100 城市ID,北京为101010100,其他城市需查询对应ID映射表
keyword String 周杰伦 搜索关键词,为空时返回全品类演出
ctl Int 1 演出品类:1-演唱会、2-话剧、5-体育赛事、0-全部
page Int 1 分页页码,从1开始
ts Int 1736700000000 毫秒级时间戳,用于请求有效性验证
order Int 1 排序方式:1-热门排序、2-时间排序
2.1.3 响应数据解析

响应示例(精简):

{ "status": 1, "msg": "success", "pageData": { "totalCount": 5, "resultData": [ { "id": "12345678", "name": "周杰伦2026世界巡回演唱会-北京", "categoryName": "演唱会", "showTime": "2026-06-15 19:30", "venueName": "国家体育场(鸟巢)", "priceStr": "880-2280元", "statusName": "预售" }, // 更多演出... ] } }

核心字段说明:

  • status:1表示请求成功,0表示失败(失败原因见msg字段)。

  • totalCount:符合条件的演出总数,用于分页计算。

  • resultData:演出列表数组,每个元素包含单场演出的基础信息(id为演出唯一标识,用于调用详情API)。

2.2 详情数据API

该接口通过演出ID获取单场演出的详细信息,包括演出介绍、场次安排、票价明细、取票规则等核心数据。

2.2.1 接口信息
  • 请求URL:https://detail.damai.cn/item.htm?id={演出ID}

  • 请求方法:GET

  • 是否需要登录:否

2.2.2 核心请求参数
参数名 类型 是否必须 示例值 描述
id String 12345678 演出唯一ID(从搜索列表API的resultData.id获取)

补充说明:该接口为网页端详情页接口,返回的是HTML内容,核心数据嵌入在页面的JSON脚本中(key为window.__INITIAL_STATE__),需通过解析HTML提取JSON数据。

2.2.3 响应数据解析

步骤1:获取HTML后,提取window.__INITIAL_STATE__对应的JSON字符串;步骤2:解析JSON得到核心数据,关键字段如下:

  • projectDetail:演出基础信息(名称、分类、演出时间、场馆地址等)。

  • performList:场次列表(每场的时间、票价、剩余库存、售票状态等)。

  • notice:购票须知(儿童政策、取票规则、退票规则等)。

  • artistList:艺人信息(适用于演唱会、话剧等有明确艺人的演出)。

三、Python实战:完整调用实现

以下实现基于Python3.8+,使用requests库发送请求,lxml库解析HTML,封装为DamaiAPI类,包含关键字搜索和详情获取两个核心方法。

3.1 环境准备

安装依赖库:

pip install requests lxml logging

3.2 完整代码实现

import requests import json import time import logging from typing import Dict, List, Optional from lxml import etree from requests.exceptions import RequestException # 配置日志 logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s" ) class DamaiAPI: def __init__(self, city_id: str = "101010100"): """ 初始化大麦网API客户端 :param city_id: 城市ID(默认北京:101010100,其他城市需查询对应ID) """ self.city_id = city_id # 模拟移动端请求头,提升兼容性 self.headers = { "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Damai/7.2.0", "Referer": "https://m.damai.cn/", "Origin": "https://m.damai.cn", "Accept": "application/json, text/plain, */*" } # 会话保持,处理Cookie self.session = requests.Session() self.session.headers.update(self.headers) def _get_timestamp(self) -> int: """生成毫秒级时间戳""" return int(time.time() * 1000) def search_performances(self, keyword: str = "", category: int = 0, page: int = 1) -> Optional[List[Dict]]: """ 关键字搜索演出列表 :param keyword: 搜索关键词(如"周杰伦") :param category: 品类(1:演唱会,2:话剧,5:体育,0:全部) :param page: 页码 :return: 格式化后的演出列表,失败返回None """ url = "https://search.damai.cn/searchajax.html" params = { "city": self.city_id, "keyword": keyword, "ctl": category, "page": page, "ts": self._get_timestamp(), "stype": 0, "order": 1 # 1:热门排序,2:时间排序 } try: response = self.session.get(url, params=params, timeout=10) response.raise_for_status() # 抛出HTTP请求异常 result = response.json() # 解析并格式化演出数据 if result.get("status") == 1: performances = result.get("pageData", {}).get("resultData", ()) if not performances: logging.info(f"未搜索到符合条件的演出,关键词:{keyword},页码:{page}") return [] # 提取核心字段,返回格式化列表 formatted_data = [ { "id": item.get("id"), "name": item.get("name"), "category": item.get("categoryName"), "time": item.get("showTime"), "venue": item.get("venueName"), "price": item.get("priceStr"), "status": item.get("statusName") # 售票状态:预售/在售/售罄 } for item in performances ] logging.info(f"搜索成功,关键词:{keyword},页码:{page},共{len(formatted_data)}场演出") return formatted_data else: logging.error(f"搜索失败:{result.get('msg')}") return None except RequestException as e: logging.error(f"搜索请求异常:{str(e)}") return None except json.JSONDecodeError as e: logging.error(f"响应数据解析失败:{str(e)}") return None def get_performance_detail(self, performance_id: str) -> Optional[Dict]: """ 获取演出详情 :param performance_id: 演出ID(从search_performances方法获取) :return: 格式化后的演出详情,失败返回None """ url = f"https://detail.damai.cn/item.htm?id={performance_id}" try: response = self.session.get(url, timeout=10) response.raise_for_status() response.encoding = "utf-8" # 设置编码,避免中文乱码 # 解析HTML,提取window.__INITIAL_STATE__对应的JSON数据 html = etree.HTML(response.text) script_content = html.xpath('//script[contains(text(), "window.__INITIAL_STATE__")]/text()') if not script_content: logging.error(f"未找到核心数据脚本,演出ID:{performance_id}") return None # 提取JSON字符串(截取window.__INITIAL_STATE__ = 后面的内容,去掉末尾的;) json_str = script_content[0].split("window.__INITIAL_STATE__ = ")[1].rstrip(";") detail_data = json.loads(json_str) # 格式化详情数据,提取关键信息 formatted_detail = { "performance_id": performance_id, "name": detail_data.get("projectDetail", {}).get("name"), "category": detail_data.get("projectDetail", {}).get("categoryName"), "show_time": detail_data.get("projectDetail", {}).get("showTime"), "venue": { "name": detail_data.get("projectDetail", {}).get("venueName"), "address": detail_data.get("projectDetail", {}).get("venueAddress") }, "performances": [ { "perform_id": item.get("performId"), "time": item.get("performTime"), "price_list": item.get("priceList", []), # 包含票价、库存等信息 "status": item.get("statusName") } for item in detail_data.get("performList", []) ], "ticket_notice": detail_data.get("notice", {}).get("ticketNotice"), # 购票须知 "artist_list": detail_data.get("artistList", []) # 艺人列表 } logging.info(f"详情获取成功,演出ID:{performance_id}") return formatted_detail except RequestException as e: logging.error(f"详情请求异常:{str(e)},演出ID:{performance_id}") return None except json.JSONDecodeError as e: logging.error(f"详情数据解析失败:{str(e)},演出ID:{performance_id}") return None except Exception as e: logging.error(f"详情获取未知异常:{str(e)},演出ID:{performance_id}") return None # 测试代码 if __name__ == "__main__": # 初始化客户端(默认北京,可替换为其他城市ID) damai_api = DamaiAPI(city_id="101010100") # 1. 搜索演出(关键词:周杰伦,品类:演唱会) search_result = damai_api.search_performances(keyword="周杰伦", category=1, page=1) if not search_result: print("搜索无结果") exit() # 2. 获取第一个演出的详情 first_performance_id = search_result[0]["id"] detail_result = damai_api.get_performance_detail(performance_id=first_performance_id) # 打印结果 print("\n=== 搜索结果 ===") print(json.dumps(search_result, ensure_ascii=False, indent=2)) print("\n=== 演出详情 ===") print(json.dumps(detail_result, ensure_ascii=False, indent=2))

3.3 代码说明

  • 封装性:将请求头、会话管理、时间戳生成等通用逻辑封装在DamaiAPI类中,降低复用成本。

  • 异常处理:捕获HTTP请求异常、JSON解析异常等,通过日志输出错误信息,便于问题排查。

  • 数据格式化:提取核心字段,过滤冗余数据,返回结构化的字典/列表,便于后续业务处理。

  • 测试代码:提供了完整的测试流程,可直接运行验证接口调用效果。

四、关键注意事项(必看)

本文涉及的接口均为非官方接口,使用前需严格遵守以下规则,避免法律风险和技术问题:

  1. 合规性优先:仅用于个人学习、研究,不得用于商业用途;不得大量抓取数据,避免侵犯大麦网的知识产权和数据权益。

  2. 控制请求频率:建议在请求中加入延时(如time.sleep(1)),避免短时间内高频请求导致IP被封禁。

  3. 接口适配:非官方接口可能随时变更,若出现调用失败,需重新抓包分析最新的接口地址和参数格式。

  4. 官方替代方案 :若需商业使用,建议联系大麦网商务团队申请官方合作,通过阿里开放平台获取正规API(如分销项目详情接口alibaba.damai.maitix.project.distribution.detail.query)。

五、总结

本文详细解析了大麦网关键字搜索列表API和详情数据API的核心规范,提供了可直接运行的Python调用代码。通过抓包分析非官方接口实现数据获取的方式,适合开发者进行技术研究和学习。但需重点强调:非官方接口存在天然的不稳定性和合规风险,商业场景下务必优先选择官方合作渠道。

若接口发生变更,可通过浏览器开发者工具(F12)重新抓包:切换到Network面板,筛选XHR/JS请求,找到包含搜索关键词或演出ID的请求,分析其参数和响应格式,即可完成适配调整。

欢迎在评论区交流接口适配经验或问题,共同完善技术方案!

相关推荐
dasi02272 小时前
Java 趣闻
java
蚍蜉撼树谈何易2 小时前
一、语音识别基础(1.1 语音特征的提取)
人工智能·语音识别
线束线缆组件品替网2 小时前
Conxall 防水线缆在户外工控中的布线实践
运维·人工智能·汽车·电脑·材料工程·智能电视
康一夏2 小时前
CSS盒模型(Box Model) 原理
前端·css
web前端1232 小时前
React Hooks 介绍与实践要点
前端·react.js
C雨后彩虹2 小时前
synchronized高频考点模拟面试过程
java·面试·多线程·并发·lock
我是小疯子662 小时前
JavaScriptWebAPI核心操作全解析
前端
JAVA+C语言2 小时前
Java ThreadLocal 的原理
java·开发语言·python
小二·2 小时前
Python Web 开发进阶实战:全链路测试体系 —— Pytest + Playwright + Vitest 构建高可靠交付流水线
前端·python·pytest