当前位置: 首页 > news >正文

实战解析:东方财富网股票数据爬取与多板块自动化抓取策略

1. 东方财富网数据接口分析实战

第一次接触东方财富网的数据抓取时,我也被它复杂的接口参数搞得一头雾水。但经过反复测试,发现其实只要掌握几个关键点,就能轻松获取到想要的股票数据。先来看看这个典型的接口URL:

url = "https://62.push2.eastmoney.com/api/qt/clist/get?cb=jQuery1124007675389012158473_1703949729655&pn=1&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&wbp2u=|0|0|0|web&fid=f3&fs=m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048&fields=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152&_=1703949729656"

这个URL虽然看起来很长,但真正需要关注的参数其实就几个:

  • pn:当前页码
  • pz:每页数据量(默认20条)
  • fid:接口类型标识
  • fs:板块筛选条件(最重要)
  • fields:需要返回的字段列表

实测发现,修改pn参数就能实现翻页,而fs参数决定了获取哪个板块的数据。比如把fs值改为"m:1+t:2"就只获取上证A股数据。这里有个小技巧:直接在浏览器地址栏修改参数测试,比反复运行脚本更高效。

2. JSONP数据处理技巧

东方财富的接口返回的是JSONP格式数据,常规的json解析方法会直接报错。我最初尝试用字符串截取处理,后来发现用正则表达式更可靠:

import re def parse_jsonp(jsonp_str): try: # 匹配JSONP前缀和后缀 json_str = re.sub(r'^.*?\(', '', jsonp_str) json_str = re.sub(r'\);$', '', json_str) return eval(json_str) except Exception as e: print(f"解析JSONP失败: {e}") return None

这里有几个坑需要注意:

  1. 正则表达式中的括号需要转义,否则会被识别为捕获组
  2. 返回数据中可能包含JavaScript变量null,需要提前声明null = None
  3. 不同接口的JSONP回调函数名可能变化,不要写死匹配规则

我建议封装一个通用的JSONP解析函数,在项目里复用。实际测试中,这个方法对东方财富所有接口都有效。

3. 多板块爬取策略

要实现全自动抓取所有板块数据,关键在于构建板块配置字典。经过分析,我整理出了完整的板块映射关系:

板块配置 = { "沪深京A股": "f3&fs=m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048", "上证A股": "f3&fs=m:1+t:2,m:1+t:23", "深证A股": "f3&fs=m:0+t:6,m:0+t:80", "创业板": "f3&fs=m:0+t:80", "科创板": "f3&fs=m:1+t:23", # 其他板块... }

爬取循环的逻辑要点:

  1. 外层循环遍历板块配置字典
  2. 内层while循环处理分页
  3. 当接口返回data为null时终止当前板块爬取
for 板块名称, 板块参数 in 板块配置.items(): 页码 = 1 while True: 数据 = 获取数据(板块参数, 页码) if 数据["data"] is None: break # 处理数据... 页码 += 1

实测发现,有些板块的页数会动态变化,所以不能依赖固定的页数判断,必须根据接口返回的data字段是否为null来判断终止条件。

4. 异常处理与优化建议

在实际爬取过程中,会遇到各种意外情况。根据我的经验,这几个地方最容易出问题:

网络请求方面:

  • 添加合理的超时设置(建议请求超时10秒,读取超时30秒)
  • 实现自动重试机制(3次重试,每次间隔递增)
  • 使用随机User-Agent避免被封
请求头 = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Accept": "application/json" } def 获取数据(url, 最大重试=3): for 尝试 in range(最大重试): try: resp = requests.get(url, headers=请求头, timeout=(10, 30)) return resp.text except Exception as e: if 尝试 == 最大重试 - 1: raise time.sleep(尝试 * 2) # 指数退避

数据存储优化:

  1. 使用Pandas直接保存为Excel会占用大量内存,建议:
    • 每100页保存一次临时文件
    • 最后合并所有临时文件
  2. 添加爬取进度日志,方便断点续爬
  3. 对关键字段进行数据校验(如股价不能为字符串)

反爬应对策略:

  • 控制请求频率(建议每请求间隔1-2秒)
  • 使用代理IP池(如果需要大规模抓取)
  • 模拟浏览器行为(如携带Cookies)

5. 完整代码实现

结合上述所有要点,这是优化后的完整实现:

import requests import re import pandas as pd import time from tqdm import tqdm class EastmoneySpider: def __init__(self): self.headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Referer": "https://quote.eastmoney.com/" } self.null = None # 处理接口返回的null值 def parse_jsonp(self, jsonp_str): try: json_str = re.sub(r'^.*?\(', '', jsonp_str) json_str = re.sub(r'\);$', '', json_str) return eval(json_str) except Exception as e: print(f"JSONP解析失败: {e}") return None def get_stock_data(self, cmd, page, retry=3): url = f"https://push2.eastmoney.com/api/qt/clist/get?pn={page}&pz=20&fid={cmd}" for i in range(retry): try: resp = requests.get(url, headers=self.headers, timeout=(10, 30)) data = self.parse_jsonp(resp.text) return data except Exception as e: if i == retry - 1: raise time.sleep(i * 2) def crawl_all_boards(self): 板块配置 = { "沪深京A股": "f3&fs=m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048", # 其他板块配置... } for 板块名称, 板块参数 in 板块配置.items(): print(f"开始爬取板块: {板块名称}") 所有数据 = [] 页码 = 1 with tqdm() as pbar: while True: try: 数据 = self.get_stock_data(板块参数, 页码) if 数据.get("data") is None: break for item in 数据["data"]["diff"]: 格式化数据 = { "代码": item.get("f12"), "名称": item.get("f14"), # 其他字段... } 所有数据.append(格式化数据) pbar.update(1) time.sleep(1) # 礼貌性延迟 页码 += 1 except Exception as e: print(f"爬取失败: {e}") break # 保存数据 pd.DataFrame(所有数据).to_excel(f"{板块名称}.xlsx", index=False) print(f"板块 {板块名称} 爬取完成,共 {len(所有数据)} 条数据") if __name__ == "__main__": spider = EastmoneySpider() spider.crawl_all_boards()

这个实现加入了进度条显示、异常处理和代码注释,实际使用时可以根据需要调整板块配置和字段映射。建议首次运行时先测试单个板块,确认无误后再开启全量爬取。

http://www.cnnetsun.cn/news/1612723.html

相关文章:

  • Transformer 从0到1:长时依赖问题的本质——梯度消失与爆炸
  • 3倍性能提升:ROCmLibs-for-gfx1103-AMD780M-APU性能调优方案与异构计算加速指南
  • 【7天Java面试突击版】100集Java面试八股文,巧拿高薪offer神器!
  • 如何高效使用draw.io桌面版:完整实用指南
  • 独立站SEO优化过程中常见的问题有哪些
  • Cosmos-Reason1-7B与卷积神经网络的融合应用探索
  • ARMv8-A异常处理实战:从SVC系统调用看Linux内核如何响应你的请求
  • 当nodepad遇见AI:利用快马平台快速集成智能代码补全与文本润色功能
  • [语音转文字工具] AsrTools:让音频转写效率提升300%的开源解决方案
  • 用快马AI五分钟搭建前端面试题库:交互式原型开发实战
  • 深度解析:相机、LiDAR与IMU紧耦合SLAM技术的最新进展与挑战
  • PaddleOCR-VL-WEB部署避坑指南:常见问题与优化建议汇总
  • C++ Move 构造函数性能优化
  • 利用快马平台快速原型origin风格的数据可视化应用
  • Watchy开源电子墨水屏手表:低功耗嵌入式系统全栈解析
  • 如何通过5个策略打造完美的Obsidian个性化主页:终极定制方案
  • 别再死记硬背!用Python+OpenCV手把手带你搞定直方图均衡化(附完整代码与避坑指南)
  • 【Simulink】基于FCS-MPC的LC滤波逆变器电压控制:从离散化方法到仿真实现
  • 别再走弯路了!用Docker在Ubuntu 20.04上搞定ROS2 Humble的ARM64交叉编译(保姆级避坑)
  • 别人推客越做越大,只因用对系统
  • YimMenu:GTA V增强与防护工具全面解析
  • DOL-CHS-MODS:一站式革新游戏体验的汉化美化整合方案
  • STM32L152C段式LCD驱动库深度解析与移植指南
  • 【20年C/Python双栈专家亲测】:无GIL Python中实现真正线程安全的7个反直觉法则(含LLVM IR级内存模型佐证)
  • 博图程序块(TIA) 多台电机依据电机变频、工频运行状态、死区设定自动判断是否增减电机运行数量
  • 嵌入式通信协议设计的7大黄金准则与实战优化
  • 从像素到概念:如何用Python+OpenCV一步步提取图像的底层与高层特征
  • 快马ai一键生成java八股文交互学习平台,快速原型验证学习路径
  • CMOS传感器选型指南:为什么OV2640仍是DIY项目的性价比之王?
  • 从课程设计到工程实践:FPGA数字钟的模块化设计与功能扩展