新闻详情

新闻详情

首页 / 资讯中心 / 详情

Selenium与Requests爬取东方财富财务数据:接口与动态页面分工实践

发布时间:2026/9/26 21:46:48来源:尧图网络
Selenium与Requests爬取东方财富财务数据:接口与动态页面分工实践
简介面向金融数据分析与网络爬虫学习者这份资源提供了一个基于东方财富网的上市公司财务数据采集项目。项目包含两套Python实现方案方案A基于Selenium自动化框架适合需模拟浏览器点击、处理动态加载页面的场景但采集速率相对较低方案B基于Requests库直接请求HTTP接口数据处理效率提升约两个数量级被定为主要实施方案。资源包共19个文件核心为2个Python脚本和10个CSV结果文件另含备份、许可证及说明文档等压缩包整体约37.96MB。脚本支持灵活配置会计年度2018—2023、财季标识、报表分类资产负债表/利润表/现金流量表与页码区间运行后自动输出CSV结构化数据并保存至预设目录可直接用于量化分析、财务教学或企业财报研究。目前已有47人学习下载适合有一定Python基础、希望快速获取上市公司结构化财报数据的开发者参考。1. 用Selenium加Requests抓东方财富网财务数据先想清楚接口在哪一层老板丢过来一句话把沪深两市上市公司近三年的资产负债表、利润表、现金流量表全爬下来月底前入库。 打开东方财富网一看每家公司几十张页面光点鼠标就能点到手软。这时候基于Selenium与Requests的东方财富网上市公司财务报表数据爬取实践就成了大多数人的第一反应——浏览器能看的Selenium就能自动化接口能拿的Requests一条请求就够。但真正动手你会发现这个标题里的分工很微妙东财的数据站点有七八成报表数据藏在JSON接口里Requests几分钟就能拉完剩下那些异步渲染的F10明细表和需要登录态的页面才轮到Selenium出场。先拆清楚数据对象再决定用哪个工具反爬问题和抓取效率就解决了一半。适合谁做量化选股、行研复核、财务异常筛查的工程师和数据分析师这篇把从选型到排错的完整路径讲完照着能跑通。2. 摸清数据源边界东方财富网的三个数据层与两种拿法2.1 三层数据结构行情层、数据中心层、F10详情层东方财富网面向普通用户的页面很多但数据逻辑上可以切成三层。第一层是行情层以push2系列接口为主提供实时价格、市盈率、市净率这类交易衍生指标数据粒度细、更新快但对财务报表爬取来说只是辅助信息。第二层是数据中心层对应的是 datacenter-web 这类接口它是东财数据团队整理过的结构化输出报表数据、业绩预告、主营构成、机构调研都在这一层JSON格式字段命名规范是爬财务报表的主战场。第三层是F10详情层也就是个股页面上财务分析那一整套页面展示上最接近阅读习惯但结构复杂有页签切换、有异步加载甚至有的区块包在iframe里是Selenium发挥作用的地方。选型理由很简单能用Requests拿JSON绝不开浏览器。JSON接口带宽消耗小、解析稳定、不需要等待渲染单位时间能抓的股票数量比Selenium高一个数量级。我一般会先打开开发者工具、切到Network面板在财务页面里翻几页把返回JSON的关键接口找出来能走接口的走接口。Selenium的价值在于兜底那些数据不在接口里、必须靠浏览器执行脚本才能渲染出来的页面以及需要维持登录态才能访问的受保护数据。这个判断顺序如果反了后面所有努力都会变成在错误的地方做优化。2.2 什么时候必须上Selenium动态表格、页签切换与iframe判断一个财务页面是否需要Selenium我有个简单的测试方法用Requests直接请求页面URL看返回的HTML里有没有你要的表格数据。资产负债表如果出现在原始HTML中直接解析就行如果只在页面源代码里看到一个空的table容器、数据靠后面的JS填充那就得上Selenium。典型场景是F10页面的财务分析模块报告期切年、切季、切半年报每一次切换都触发一次异步请求表格区域整体重绘Requests拿到的只是一层空壳。另一个必须用Selenium的场景是带登录态的数据。有些深度财务指标或导出功能需要登录后可见这时候Selenium的作用不是渲染而是帮你走一遍登录流程、把Cookie取出来。取到之后的请求依然可以交回给Requests用带着Cookie的Session去访问接口速度和稳定性都更好。这种混合用法是爬东财数据最常见的架构——Selenium负责拿入场券Requests负责大规模搬运。不需要整个项目都浸泡在浏览器自动化里那是新手最容易犯的过度设计。3. 用Requests拿数据中心JSON从单表请求到三表串联3.1 资产负债表接口的最小请求代码东方财富网的数据中心接口遵循一套统一的查询风格路径一般是 datacenter-web.eastmoney.com/api/data/v1/get通过reportName指定报表类型通过columns指定要返回的字段。以资产负债表为例核心参数里filter用股票代码过滤sortColumns指定报告期排序pageNumber和pageSize控制分页。下面这段代码是一个可运行的最小闭环抓取特定股票最近一份资产负债表并解析出关键字段。import requests import pandas as pd from datetime import datetime # 数据中心统一入口用 reportName 区分报表 url https://datacenter-web.eastmoney.com/api/data/v1/get params { reportName: RPT_LICO_FN_CPZ, # 资产负债表 columns: ALL, # 拿全部字段先探路 filter: (SECURITY_CODE600519), # 贵州茅台 sortColumns: REPORT_DATE, # 按报告期排序 sortTypes: -1, # 降序最新报告期在最前 pageNumber: 1, pageSize: 1, # 先拿一条验证结构 } headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36, Referer: https://data.eastmoney.com/, } resp requests.get(url, paramsparams, headersheaders, timeout10) resp.raise_for_status() data resp.json() rows data[result][data] # 时间戳字段转日期方便核对报告期 for row in rows: row[REPORT_DATE] datetime.fromtimestamp(row[REPORT_DATE] / 1000).strftime(%Y-%m-%d) df pd.DataFrame(rows) print(df[[SECURITY_CODE, SECURITY_NAME_ABBR, REPORT_DATE, TOTAL_ASSETS, TOTAL_LIABILITIES, TOTAL_EQUITY]].to_string())这段代码里值得注意的有三处。第一是filter的写法字段名用引号包裹、值用双引号整体作为一个字符串传进去多条件用逗号连接。第二是REPORT_DATE是毫秒时间戳直接丢给DataFrame会被当成数字先转换再核对。第三是columnsALL在探路阶段很有用你可以把返回的JSON完整打印出来看清楚字段有哪些、命名规律是什么后面精确指定字段时就不会翻车。提示东方财富网的接口字段命名整体接近直译TOTAL_ASSETS是总资产TOTAL_LIABILITIES是总负债TOTAL_EQUITY是所有者权益合计。实际字段以返回的JSON为准不同报表的命名风格有差异别靠着记忆写死。3.2 利润表与现金流量表三张报表按股票和报告期对齐资产负债表只是第一张利润表和现金流量表的请求套路完全一致变的只是reportName和字段名。利润表是RPT_LICO_FN_INCOME现金流量表是RPT_LICO_FN_CASHFLOW。三条请求打出去拿回三个DataFrame但这时的数据还不能直接入库——需要按股票代码 报告期对齐。同一家公司在同一份财报发布日期下三张报表具有相同的报告期对齐键就是这两个字段。实际操作里我习惯把请求封装成一个通用函数参数只要传reportName、filter、columns返回DataFrame。然后循环调用三次分别拼股票代码前缀最后用merge或concat对齐。对齐不光是索引匹配还要留意金额单位。东财接口大部分金额字段以元为单位但有些衍生指标是万元甚至亿元如果三张表混在一起入库后面算毛利率、资产负债率时会出现量级差出四位数的血泪事故。判断方法很笨但可靠把贵州茅台的总资产字段拉到网页上人工核对一遍数字对上了再大规模跑。def fetch_report(report_name: str, stock_code: str, page_size: int 20) - pd.DataFrame: 通用财务报表抓取函数 url https://datacenter-web.eastmoney.com/api/data/v1/get params { reportName: report_name, columns: ALL, filter: f(SECURITY_CODE{stock_code}), sortColumns: REPORT_DATE, sortTypes: -1, pageNumber: 1, pageSize: str(page_size), } headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), Referer: https://data.eastmoney.com/, } resp requests.get(url, paramsparams, headersheaders, timeout15) payload resp.json() if payload.get(result) is None: return pd.DataFrame() df pd.DataFrame(payload[result][data]) if df.empty: return df df[REPORT_DATE] pd.to_datetime(df[REPORT_DATE], unitms) return df # 三张报表各取最近5期按股票代码和报告期对齐 stock 600519 balance fetch_report(RPT_LICO_FN_CPZ, stock, page_size5) income fetch_report(RPT_LICO_FN_INCOME, stock, page_size5) cashflow fetch_report(RPT_LICO_FN_CASHFLOW, stock, page_size5) merged balance.merge( income, on[SECURITY_CODE, REPORT_DATE], suffixes(_BAL, _INC), ).merge( cashflow, on[SECURITY_CODE, REPORT_DATE], suffixes(_INC, _CAS), )这个函数能跑通的前提是pageSize不要贪大。数据中心接口单页返回超过两百条时接口响应时间会明显变长偶发超时。我一般控制在50条以内宁可多循环几次也不要一次拉全量然后等超时重试。对齐之后建议立刻做一次完整性校验三张表行数是否一致、报告期集合是否相同、关键字段是否有空值。只有这三关都过了数据才配进数据库。4. 用Selenium补齐F10动态表格渲染、页签与iframe的兜底方案4.1 启动参数配置关闭自动化特征与资源占用数据中心接口覆盖了大部分报表数据但总有几家公司的特殊字段只在F10页面里出现比如审计意见类型、研发投入明细、分红送配详情。这些页面是典型的JS动态渲染Requests拿到的是空壳。这时才轮到Selenium出场。许多人对Selenium又爱又恨其实是没配置好启动参数导致浏览器被识别为自动化控制、页面加载慢、内存占用高。下面是经过反复验证的最小配置。from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service options Options() # 去掉Chrome正在受到自动软件控制的提示条降低被检测概率 options.add_experimental_option(excludeSwitches, [enable-automation]) options.add_experimental_option(useAutomationExtension, False) # 关闭图片加载F10页面图片多但对数据抓取无用 prefs {profile.managed_default_content_settings.images: 2} options.add_experimental_option(prefs, prefs) # 必要配置很多F10表格在这个窗口宽度下布局最稳定 options.add_argument(--window-size1440,900) # 隐藏自动软件标记的CDP命令不少站点会检测这个 options.add_argument(--disable-blink-featuresAutomationControlled) driver webdriver.Chrome(serviceService(), optionsoptions) driver.set_page_load_timeout(30) driver.implicitly_wait(10)这套参数解决的问题很具体。excludeSwitches去掉了浏览器顶部的提示条useAutomationExtension配合CDP命令能减少webdriver特征被页面脚本读到的概率。关闭图片是个很实用的提速点F10页面一张图表几百KB爬几百家公司光是下载图片就多耗十几分钟而数据本身都在DOM表格里图片关掉不影响。窗口大小固定也很重要有些前端框架在窄窗口下会改变表格渲染方式把窗口固定成预设尺寸能减少这类不确定性。注意Selenium的防检测只是提高成功率不是绝对保障。如果页面出现了验证码或滑块别硬刚先退出去检查请求频率。4.2 从进入财务分析页到拿到整张表显式等待与iframe切换用Selenium爬F10财务分析页第一步是定位到正确的URL。传统F10页面的URL格式比较稳定股票代码拼进去就能访问。但真正进了页面才是考验的开始。财务分析模块里有资产负债表、利润表、现金流量表三个大页签每个页签下面还有报告期选择下拉框。每一次切换页签或切换报告期表格区域都会异步刷新。如果代码里没有等待逻辑Selenium会在表格还没渲染出来时就去读DOM返回空数据这是最常见的翻车现场。from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 进入F10财务分析页 stock_code 600519 url fhttps://emweb.securities.eastmoney.com/PC_HSF10/NewFinanceAnalysis/Index?typewebcode{stock_code} driver.get(url) # 等待页签区域出现确认页面主框架加载完成 WebDriverWait(driver, 20).until( EC.presence_of_element_located((By.CSS_SELECTOR, .mainTable)) ) # 切到资产负债表页签按钮文本定位不用XPath路径写死位置 tabs driver.find_elements(By.CSS_SELECTOR, .tab li) for tab in tabs: if 资产负债 in tab.text: tab.click() break # 页签切换后表格是异步加载的必须等新表格出现 table WebDriverWait(driver, 15).until( EC.visibility_of_element_located((By.CSS_SELECTOR, #table1)) ) # 读取表头 thead_rows table.find_elements(By.CSS_SELECTOR, thead tr) headers [th.text.strip() for th in thead_rows[-1].find_elements(By.TAG_NAME, th)] # 读取表体注意有些单元格带span标签需要取text属性 data_rows [] tbody table.find_element(By.CSS_SELECTOR, tbody) for tr in tbody.find_elements(By.CSS_SELECTOR, tr): row [td.text.strip() for td in tr.find_elements(By.TAG_NAME, td)] data_rows.append(row) # 组装成列表每行是一个报表科目 report [dict(zip(headers, row)) for row in data_rows] print(report[:5])这里关键的坑有三个。第一是页签点击后必须用显式等待visibility_of_element_located比implicitly_wait更可靠因为它是轮询等待而后者是固定超时。第二是iframe问题新版F10页面大部分表格不在iframe里但老版本页面有嵌套iframe如果driver.find_element找不到元素优先检查是否用了driver.switch_to.frame()。第三是表头结构东财F10表格的表头往往有两行一行是分类、一行是具体科目取最后一行作为列名才完整否则会出现科目错位。F10页面的表格一次最多展示最近五年或最近十几期超过这个范围的数据还是得回到数据中心接口去取。这也再次印证了架构判断Selenium在这个项目里是补缺口的不是主力。数据量大、要覆盖全市场的任务交给Requests个别字段、个别页面的补漏用Selenium精准打击。混用得当整个项目的耗时和反爬风险都能控制在合理范围。5. 避坑东方财富网财务数据爬取的五个真实踩坑点5.1 429 too many requests限流与退避重试现象脚本连续抓了十几个股票后突然报出类似exceeded retry limit, last status: 429 too many requests的错误再过一会儿连正常访问首页都变慢。原因数据中心接口对单个IP的QPS有限制并发一高或循环太快就触发限流。解决在每次请求之间加入随机延时并对429状态码做指数退避重试而不是报错就停。import time import random def robust_get(url, params, headers, max_retries5): for attempt in range(max_retries): resp requests.get(url, paramsparams, headersheaders, timeout15) if resp.status_code 200: return resp if resp.status_code 429: # 退避时间随尝试次数递增抖动随机值避免所有线程同时重试 wait (2 ** attempt) random.uniform(0.5, 1.5) print(f触发限流等待 {wait:.2f}s 后重试) time.sleep(wait) else: resp.raise_for_status() raise RuntimeError(多次重试后仍然失败)延时取值我常用0.5到1.5秒随机整体抓取速度大约每秒一个请求对全市场近五千家公司的资产负债表来说单表耗时大约一个多小时。看起来不慢但你要是用Selenium逐个页面点这个时间会放大到十几小时。不要把延时写成固定值固定间隔容易被识别成脚本特征。5.2 Cookie与User-Agent不一致导致字段为空现象用Requests访问接口时返回的JSON里result不为空但部分字段的值是null。原因接口校验了请求来源Referer缺失或不合法时服务端会选择性地不返回敏感字段。解决请求头里带上Referer为https://data.eastmoney.com/且保持User-Agent与浏览器一致。这是最简单但最容易被忽略的一步有些字段就像挤牙膏头没带对就藏着不给。5.3 金额单位错位元、万元、亿元混用现象同一张表里总资产显示为万亿级数字但利息支出只有几百万看起来比例失衡。原因不同接口、不同字段使用了不同的金额单位个别衍生指标按万元计算。解决每个字段入库前都跟网页端核对一次重点核对大额科目。不要相信字段名的后缀约定要相信眼睛核过的数字。我在这个坑里翻过车把某公司的净利润当成元入库导致后续算出来的市盈率差了四位。5.4 同一报告期多条记录预告、快报与正式财报并存现象按股票代码报告期去重后发现某公司2023年年报有两条记录一条是业绩快报一条是正式财报。原因数据中心会保留同一报告期的多个公告版本字段值不同。解决入库时增加公告类型字段并按公告日期取最新一条。常见做法是优先取正式财报其次才是快报和预告。如果不区分后面做同比分析时会把快报数据和正式数据混在一起算结论自然失真。5.5 Selenium等待超时懒加载与滚动加载现象F10页面的表格明明存在但WebDriverWait等了二十秒还是找不到元素。原因部分区块采用了懒加载策略只有在页面滚动到底部时才触发数据加载。解决在等待之前先执行JavaScript把页面滚动到底部再回到表格位置让懒加载有触发机会。代码就一行driver.execute_script(window.scrollTo(0, document.body.scrollHeight))。如果还不出来检查是否被反爬识别先手动打开页面看看能否正常显示。6. 从爬下来的报表到可信数据库校验技巧与入库习惯数据抓下来只是第一步它能不能用于决策取决于有没有经过校验。我有一套固定的验证流程先随机抽三家公司覆盖大盘股、中盘股、ST股每家公司手工打开东财网页把总资产、净利润、经营现金流三个字段跟抓下来的数据逐条核对。三家公司全对才认为这批数据的口径是统一的。如果有一家对不上先别急着排查代码而是去确认是否拿错了报告期版本——这比调试代码更常见。全市场跑批的耗时要做一次预估算沪深两市约五千家公司每家三张表按每秒一个请求算大约四个小时能跑完一轮。如果需要季度更新这个速度完全跟得上。建议把抓取脚本和校验脚本分开抓取脚本只负责落库校验脚本独立运行输出不一致记录。这样每次跑批后能自动生成一份质量报告而不是全靠人工抽查。入库时我有个仪式感很强的习惯每张表写完后立刻执行SELECT COUNT(*)验证行数再执行一次主键冲突检查。前者保证没丢数据后者保证可重复抓取。这个习惯救过我很多次——某次调整参数后脚本少翻了一页正是这个检查在第一时间发现了问题。另外一个进阶用法是把请求频率控制做成可配置的参数写在配置文件里而不是埋在代码中根据当前是首次全量还是增量更新切换不同的限速策略。增量更新可以稍微激进一点全量更新则保守为妙。把Redis或SQLite当作简单的进度记录器每抓完一只股票就写入状态断点续跑时能跳过已完成的部分。这样爬取任务可以拆成多轮执行不用担心中途挂了要全部重来。用Selenium与Requests混搭爬东方财富网的财务数据本质是给不同数据形态选最合适的工具JSON接口能解决的绝不开浏览器浏览器渲染才能拿到的再让Selenium上。我如今接任何数据爬取需求都先问一句这数据在接口里有没有然后才考虑自动化方案。这套方法论比数据本身更值钱。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

IDA 7.0逆向实战:固件加载、脚本化与动态调试全解析 2026/9/26 22:34:53

IDA 7.0逆向实战:固件加载、脚本化与动态调试全解析

简介:IDA Pro 7.0是一款面向逆向工程与安全研究人员的交互式反汇编利器,广泛应用于恶意软件分析、漏洞挖掘、二进制审计与软件破解等场景。资源包约200.83MB,共1002个文件,含283个dll插件模块、174个sig签名库、107个py脚本、87个…

阅读更多 →
Ollama 本地部署完整指南:模型目录、GGUF 导入与 AnythingLLM 接入 2026/9/26 22:34:53

Ollama 本地部署完整指南:模型目录、GGUF 导入与 AnythingLLM 接入

简介:针对Ollama本地私有化部署的安装指导小资源,适合需要在Linux/macOS环境快速完成大模型运行平台搭建的中初级开发者或运维人员。压缩包仅13KB,由3个文件构成,包括1个txt说明文档、1个sh安装脚本和1个php下载入口脚本&#xff…

阅读更多 →
大学生心理咨询系统毕业设计:从需求分析到Spring Boot+Vue落地全解析 2026/9/26 22:34:47

大学生心理咨询系统毕业设计:从需求分析到Spring Boot+Vue落地全解析

到了毕业设计这个环节,最怕的不是不会写代码,而是选了一个自己都讲不清楚的题目。大学生心理咨询系统这个选题我前后带过几届学生做过,也在不少开源平台上看过同类项目,客观说,它是一个"看起来很普通、做起来很顺…

阅读更多 →
专升本数据结构C语言核心考点:顺序表、链表与排序算法 2026/9/26 22:34:47

专升本数据结构C语言核心考点:顺序表、链表与排序算法

简介:数据结构是专升本计算机类考试的重点科目,《数据结构1800例题与答案》复习资料包正是为备考专升本的考生及需要系统复习数据结构基础的学习者准备。包里共34个文件,约1.09MB,以23个htm格式的例题页面和11个doc格式的试题、答…

阅读更多 →
告别模板丑感:wordpress导航小图标实战与保姆级建站教程 2026/9/26 22:34:40

告别模板丑感:wordpress导航小图标实战与保姆级建站教程

告别模板丑感:wordpress导航小图标实战与保姆级建站教程 模板网站太丑不够用?这是很多刚接触 WordPress 的站长最真实的痛点。你花了大几千买个主题,结果导航栏光秃秃的,像个没做完的半成品,客户一眼就看穿这是“套壳”站。今天这篇…

阅读更多 →
我的家乡网页设计实战:纯HTML+CSS+JS从零构建高分作品 2026/9/26 22:34:34

我的家乡网页设计实战:纯HTML+CSS+JS从零构建高分作品

1. 项目构思与整体设计思路1.1 为什么要做“我的家乡”主题网页很多人一听到期末网页设计作业,第一反应就是“随便做个静态页面交差得了”。但我在实际带项目、帮人改作业的过程里发现,越是抱着敷衍心态做的作品,越容易在答辩时被老师问住——…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉