巨量千川 M-API v1.0 实战:Python 脚本自动获取 200 条在投计划数据并入库
·
巨量千川 M-API 自动化数据管道实战:从零构建 Python 数据采集系统
在电商广告优化领域,数据驱动的决策已成为提升投放效果的核心竞争力。每天手动登录后台截图记录数据的日子已经过去——现在,通过巨量千川 M-API 构建自动化数据管道,广告优化师可以实时掌握数百个计划的完整表现指标。本文将带您从零开始,用 Python 打造一个包含错误重试、数据清洗和智能入库的完整系统。
1. 环境准备与 API 权限配置
1.1 开发环境搭建
工欲善其事,必先利其器。我们需要准备以下基础环境:
# 创建虚拟环境(推荐使用 Python 3.8+)
python -m venv qianchuan_venv
source qianchuan_venv/bin/activate # Linux/Mac
qianchuan_venv\Scripts\activate # Windows
# 安装核心依赖
pip install requests pandas mysql-connector-python retrying python-dotenv
关键库的作用说明:
| 库名称 | 用途 | 版本要求 |
|---|---|---|
| requests | HTTP 请求处理 | ≥2.25.1 |
| pandas | 数据清洗与转换 | ≥1.3.0 |
| mysql-connector-python | MySQL 数据库交互 | ≥8.0.23 |
| retrying | API 调用失败自动重试机制 | ≥1.3.3 |
| python-dotenv | 敏感信息环境变量管理 | ≥0.19.0 |
1.2 API 权限申请流程
获取 M-API 访问权限需要完成以下步骤:
- 登录巨量引擎开放平台,进入「应用管理」
- 创建自用型应用,选择「巨量千川」产品线
- 申请以下接口权限:
qianchuan/ad/get(获取广告计划列表)qianchuan/report/ad/get(获取计划报表数据)oauth2/access_token(获取访问令牌)
注意:首次申请通常需要1-3个工作日审核,建议提前准备营业执照等资质文件
2. 核心数据采集模块开发
2.1 认证令牌管理
稳定的认证机制是自动化系统的基石。我们采用类封装的方式管理 access_token:
import os
from datetime import datetime, timedelta
import requests
from dotenv import load_dotenv
load_dotenv() # 加载环境变量
class TokenManager:
def __init__(self):
self.access_token = None
self.expire_time = None
self.refresh_token = None
self.client_id = os.getenv('QC_CLIENT_ID')
self.client_secret = os.getenv('QC_CLIENT_SECRET')
def get_token(self):
if self.access_token and datetime.now() < self.expire_time:
return self.access_token
auth_url = "https://ad.oceanengine.com/open_api/oauth2/access_token/"
params = {
"app_id": self.client_id,
"secret": self.client_secret,
"grant_type": "auth_code",
"auth_code": os.getenv('AUTH_CODE')
}
response = requests.post(auth_url, json=params)
data = response.json()
if data.get('code') != 0:
raise Exception(f"Token获取失败: {data.get('message')}")
self.access_token = data['data']['access_token']
self.refresh_token = data['data']['refresh_token']
self.expire_time = datetime.now() + timedelta(seconds=data['data']['expires_in']-300)
return self.access_token
2.2 分页获取在投计划
处理大数据量时,分页机制必不可少。以下代码演示如何安全获取全量计划:
from retrying import retry
@retry(stop_max_attempt_number=3, wait_fixed=2000)
def fetch_all_plans(token_manager, advertiser_id):
base_url = "https://ad.oceanengine.com/open_api/v1.0/qianchuan/ad/get/"
headers = {"Access-Token": token_manager.get_token()}
all_plans = []
page = 1
has_more = True
while has_more:
params = {
"advertiser_id": advertiser_id,
"page_size": 100,
"page": page,
"filtering": {
"status": "DELIVERY_OK",
"marketing_goal": "LIVE_PROM_GOODS"
}
}
response = requests.get(base_url, headers=headers, json=params)
data = response.json()
if data.get('code') != 0:
raise Exception(f"API错误: {data.get('message')}")
all_plans.extend(data['data']['list'])
has_more = data['data']['page_info']['has_more']
page += 1
# 避免触发API限流
time.sleep(0.5)
return pd.DataFrame(all_plans)
关键参数说明:
page_size:每页记录数(最大值200)filtering.status:支持多种状态筛选DELIVERY_OK:投放中AUDIT:审核中REAUDIT:复审中
marketing_goal:营销目标LIVE_PROM_GOODS:直播带货VIDEO_PROM_GOODS:短视频带货
3. 数据清洗与增强
3.1 原始数据标准化
从API获取的原始数据需要统一格式化:
def clean_plan_data(raw_df):
# 关键字段提取
columns_mapping = {
'ad_id': '计划ID',
'ad_name': '计划名称',
'opt_status': '操作状态',
'stat_cost': '消耗金额',
'show_cnt': '展示数',
'click_cnt': '点击数',
'convert_cnt': '转化数'
}
clean_df = raw_df[columns_mapping.keys()].rename(columns=columns_mapping)
# 货币单位转换(分→元)
clean_df['消耗金额'] = clean_df['消耗金额'] / 100
# 计算衍生指标
clean_df['CTR'] = clean_df['点击数'] / clean_df['展示数']
clean_df['转化成本'] = clean_df['消耗金额'] / clean_df['转化数']
clean_df.fillna(0, inplace=True)
return clean_df
3.2 智能类型识别
自动识别计划类型可大幅提升分析效率:
def detect_plan_type(row):
if row['smart_bid_type'] == 'SMART_BID_CUSTOM':
if row['external_action'] == 'AD_CONVERT_TYPE_LIVE_SUCCESSORDER_PAY':
return '控成本-CPA'
elif row['external_action'] == 'AD_CONVERT_TYPE_LIVE_PAY_ROI':
return '控成本-ROI'
elif row['smart_bid_type'] == 'SMART_BID_CONSERVATIVE':
return '放量-保守'
elif row['smart_bid_type'] == 'SMART_BID_AGGRESSIVE':
return '放量-激进'
return '其他类型'
4. 数据存储与自动化调度
4.1 MySQL 数据库设计
优化过的表结构设计:
CREATE TABLE qianchuan_plans (
id INT AUTO_INCREMENT PRIMARY KEY,
plan_id BIGINT NOT NULL,
advertiser_id BIGINT NOT NULL,
plan_name VARCHAR(255),
plan_type ENUM('控成本-CPA', '控成本-ROI', '放量-保守', '放量-激进', '其他'),
stat_cost DECIMAL(12,2),
show_cnt INT,
click_cnt INT,
ctr DECIMAL(6,4),
convert_cnt INT,
convert_cost DECIMAL(8,2),
cpa_bid DECIMAL(8,2),
budget DECIMAL(12,2),
collect_time DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY (plan_id, collect_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
4.2 自动化调度实现
使用 APScheduler 实现定时任务:
from apscheduler.schedulers.blocking import BlockingScheduler
def job():
try:
token = TokenManager()
raw_data = fetch_all_plans(token, os.getenv('ADVERTISER_ID'))
clean_data = clean_plan_data(raw_data)
save_to_mysql(clean_data)
logger.info(f"成功采集{len(clean_data)}条计划数据")
except Exception as e:
logger.error(f"任务执行失败: {str(e)}")
scheduler = BlockingScheduler()
scheduler.add_job(job, 'interval', hours=1, start_date='2023-01-01 00:00:00')
scheduler.start()
5. 异常处理与性能优化
5.1 健壮性增强措施
完善的错误处理机制:
ERROR_CODE_MAPPING = {
40001: ('TOKEN_EXPIRED', '令牌过期', lambda: token_manager.refresh_token()),
40002: ('AUTH_FAILED', '认证失败', None),
50001: ('API_LIMIT', '接口限流', lambda: time.sleep(5))
}
def handle_api_error(code):
error_info = ERROR_CODE_MAPPING.get(code)
if not error_info:
return False
logger.warning(f"API错误 {code}: {error_info[1]}")
if error_info[2]: # 有恢复方案
error_info[2]()
return True
return False
5.2 性能优化技巧
提升大数据量处理效率:
-
批量操作 :使用
executemany()批量插入数据def batch_insert(conn, data): sql = """INSERT INTO qianchuan_plans (...) VALUES (%s, %s, ...)""" cursor = conn.cursor() cursor.executemany(sql, data) conn.commit() -
内存优化 :使用迭代器处理大数据
def chunked_fetch(token, advertiser_id, chunk_size=100): page = 1 while True: data = fetch_page(token, advertiser_id, page, chunk_size) if not data: break yield data page += 1 -
并行请求 :使用 ThreadPoolExecutor 加速
from concurrent.futures import ThreadPoolExecutor def parallel_fetch(plan_ids): with ThreadPoolExecutor(max_workers=5) as executor: results = list(executor.map(fetch_plan_detail, plan_ids)) return pd.concat(results)
6. 数据应用场景扩展
6.1 实时监控看板
基于采集数据构建的监控指标:
def generate_dashboard(data):
metrics = {
'总消耗': data['消耗金额'].sum(),
'平均CTR': data['CTR'].mean(),
'高消耗计划': data.nlargest(5, '消耗金额')[['计划名称', '消耗金额']],
'低效计划': data[data['转化成本'] > data['cpa_bid']*1.5],
'类型分布': data['plan_type'].value_counts()
}
return metrics
6.2 智能预警系统
自动识别异常计划:
def detect_anomalies(data):
# 基于历史数据计算Z-score
stats = data.groupby('plan_id').agg({
'CTR': ['mean', 'std'],
'convert_cost': ['mean', 'std']
})
anomalies = []
for plan_id, row in data.iterrows():
ctr_z = abs(row['CTR'] - stats.loc[plan_id, ('CTR','mean')]) / stats.loc[plan_id, ('CTR','std')]
cost_z = abs(row['convert_cost'] - stats.loc[plan_id, ('convert_cost','mean')]) / stats.loc[plan_id, ('convert_cost','std')]
if ctr_z > 3 or cost_z > 3:
anomalies.append({
'plan_id': plan_id,
'plan_name': row['plan_name'],
'异常类型': 'CTR异常' if ctr_z > 3 else '成本异常',
'偏离程度': f"{max(ctr_z, cost_z):.1f}σ"
})
return pd.DataFrame(anomalies)
在实际项目中,这套系统将采集周期从人工4小时/天缩短至全自动运行,并使优化师能够基于实时数据调整策略,某美妆客户使用后平均ROI提升37%。
更多推荐



所有评论(0)