
东方财富网股票数据接口逆向工程实战指南1. 理解JSONP接口的核心机制在金融数据抓取领域JSONPJSON with Padding是一种常见的数据交互方式。东方财富网的股票数据接口采用了典型的JSONP实现方案这种技术本质上是为了解决跨域请求的限制而设计的。JSONP的工作原理可以概括为客户端动态创建script标签其src属性指向目标API地址服务器返回的不是纯JSON而是包裹在回调函数中的JSON数据客户端预先定义同名回调函数来处理返回的数据东方财富网的接口URL通常包含以下关键参数cb回调函数名称格式如jQuery1123029641287609778977_1731375129708ut认证token如b2884a393a59ad64002292a3e90d46a5fields指定返回字段如f12,f14,f2,f127pz每页数据量pn当前页码提示JSONP接口的识别特征是响应内容以回调函数开头如jQueryxxx(...)并以括号结尾。2. 接口参数深度解析2.1 核心参数映射表参数名示例值含义说明fidf267数据分类标识po1排序方式pz50每页记录数pn1当前页码fltt2价格精度invt2投资类型fsm:0t:6市场筛选条件2.2 字段映射关系东方财富网使用简写字段标识数据项常见字段包括FIELD_MAPPING { f12: 股票代码, f14: 股票名称, f2: 最新价, f172: 三日涨跌幅, f267: 主力净流入额, # 其他字段... }3. 实战抓取流程3.1 基础请求构造首先需要模拟浏览器请求头这是绕过基础反爬的关键headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), Referer: https://data.eastmoney.com/ }3.2 数据处理方法对比方法一正则表达式提取import re def parse_by_regex(response_text): json_match re.search(r\((.*)\), response_text) if json_match: return json.loads(json_match.group(1)) return None方法二字符串截取def parse_by_slice(response_text): json_str response_text[response_text.find(()1:-1] return json.loads(json_str)注意正则方法更健壮但性能略低字符串截取效率更高但对格式要求严格。4. 分页抓取实现方案4.1 分页参数处理东方财富网的分页通过pn参数控制以下是三种URL构造方式字符串替换法base_url https://...pn1 page_url base_url.replace(pn1, fpn{page})URL编码法from urllib.parse import urlencode params {pn: page} query_string urlencode(params)参数对象法def build_url(base_url, page): from urllib.parse import urlparse, parse_qs, urlunparse parts urlparse(base_url) query_dict parse_qs(parts.query) query_dict[pn] [str(page)] new_query urlencode(query_dict, doseqTrue) return urlunparse(parts._replace(querynew_query))4.2 数据存储方案推荐使用pandas进行数据整理和存储import pandas as pd def save_to_excel(data_list, filename): df pd.DataFrame(data_list) # 处理特殊值如- df.replace(-, 0, inplaceTrue) df.to_excel(filename, indexFalse)5. 反爬应对策略5.1 请求频率控制import time import random def safe_request(url): time.sleep(random.uniform(0.5, 1.5)) return requests.get(url, headersheaders)5.2 Token动态获取观察发现ut参数会定期变化可通过以下方式获取最新值从首页HTML中提取从其他API响应中获取通过JS逆向分析生成逻辑6. 完整案例实现import requests import pandas as pd from urllib.parse import urlencode from typing import List, Dict class EastMoneySpider: BASE_URL https://push2.eastmoney.com/api/qt/clist/get def __init__(self): self.session requests.Session() self.session.headers.update({ User-Agent: Mozilla/5.0, Referer: https://data.eastmoney.com/ }) def get_page_data(self, page: int) - List[Dict]: params { cb: jQuery1124, fid: f267, pn: page, pz: 50, fields: f12,f14,f2,f172,f267,f268 } try: resp self.session.get(self.BASE_URL, paramsparams) data_str resp.text[resp.text.find(()1:-1] json_data json.loads(data_str) return self._parse_items(json_data) except Exception as e: print(f请求失败: {e}) return [] def _parse_items(self, raw_data: Dict) - List[Dict]: items [] for item in raw_data[data][diff]: items.append({ 代码: item.get(f12), 名称: item.get(f14), 最新价: float(item.get(f2, 0)), 三日涨跌幅: float(item.get(f172, 0)) }) return items # 使用示例 spider EastMoneySpider() all_data [] for page in range(1, 6): # 抓取前5页 all_data.extend(spider.get_page_data(page)) pd.DataFrame(all_data).to_excel(stock_data.xlsx, indexFalse)7. 常见问题排查返回数据为空检查ut参数是否过期验证fields参数是否包含必要字段确认网络请求是否被重定向数据解析失败检查JSONP回调函数格式是否变化验证响应内容编码是否为UTF-8处理特殊字符和转义问题请求被拦截轮换User-Agent添加Referer头使用代理IP池在实际项目中我发现东方财富网的接口对请求频率较为敏感建议控制在每秒1-2次请求并合理设置超时时间。对于长期运行的任务最好实现断点续传功能记录已成功获取的页码避免重复请求。