京公网安备 11010802034615号
经营许可证编号:京B2-20210330
上市公司财务报表是反映企业经营状况、盈利能力、偿债能力的核心数据载体,是投资者决策、研究者分析、从业者复盘的重要依据。163网易财经作为国内权威的财经数据平台,整合了全A股、港股、美股上市公司的完整财务数据,涵盖资产负债表、利润表、现金流量表及核心财务指标,且数据更新及时、格式规范,是爬取上市公司财务数据的优选数据源。
相较于交易所官网的繁琐下载、第三方工具的付费限制,使用Python爬取163网易财经的财务报表,可实现“批量获取、自动整理、高效分析”,大幅提升数据获取效率,尤其适合需要批量处理多只股票财务数据的场景。本文将从爬取原理、环境准备、完整实操步骤、反爬应对、数据清洗与应用五个维度,手把手教你用Python爬取163网易财经上市公司财务报表,兼顾新手友好性与实操落地性,避开常见爬取误区。
在动手写代码前,需先明确163网易财经财务报表的页面结构与数据加载逻辑——这是爬取成功的关键,也是避开反爬的核心前提。
163网易财经的上市公司财务数据页面,采用固定URL规则与统一的HTML结构,便于Python解析。其核心规律如下:
URL规则:单只上市公司的财务数据页面URL格式为 http://quotes.money.163.com/hkstock/cwsj_股票代码.html(港股)、http://quotes.money.163.com/股票代码.html(A股),其中“股票代码”为上市公司的交易代码(如茅台600519、宁德时代300750),通过修改股票代码即可批量获取不同公司的数据。
数据分类:页面内包含“主要财务指标”“利润表”“资产负债表”“现金流量表”四大核心模块,每个模块对应独立的HTML表格,数据以明文形式嵌入页面,未进行复杂加密(部分动态加载数据可通过抓包获取JSON格式数据)。
数据格式:所有财务数据均为标准化格式,包含报告日期、指标名称、具体数值、单位等信息,且同一类型报表(如利润表)的表头结构一致,便于后续批量解析与整理。
本次爬取采用“请求页面→解析页面→提取数据→保存数据”的核心流程,依托Python的requests库发送HTTP请求,获取页面HTML源码,再通过BeautifulSoup库解析HTML结构,提取表格中的财务数据,最后将数据整理为Excel或CSV格式,便于后续分析使用。
需注意:163网易财经存在基础反爬机制(如User-Agent检测、请求频率限制),无需复杂的加密破解,只需模拟真实浏览器行为、控制请求频率,即可顺利爬取数据,新手可轻松上手。
爬取前需完成Python环境搭建与相关库安装,所有操作均适用于Windows、MacOS系统,步骤简单可复制。
Python版本:3.7及以上(推荐3.9版本,兼容性更好),可通过Python官网下载安装,安装时勾选“Add Python to PATH”,便于后续命令行调用。
本次爬取需用到4个核心Python库,打开命令行(Win+R输入cmd,Mac打开终端),执行以下命令批量安装:
# 安装核心库
pip install requests # 发送HTTP请求,获取页面源码
pip install beautifulsoup4 # 解析HTML页面,提取数据
pip install pandas # 整理、清洗数据,保存为Excel/CSV
pip install fake_useragent # 生成随机User-Agent,规避反爬
库功能说明:
requests:核心库,用于向163财经发送请求,获取财务数据页面的HTML源码;
beautifulsoup4:解析HTML源码,定位表格位置,提取财务指标与数值;
fake_useragent:生成随机的浏览器User-Agent,模拟真实用户访问,避免被网站识别为爬虫。
本次以爬取“贵州茅台(600519)”的财务报表为例,实现“单只股票爬取”,后续可扩展为“批量爬取多只股票”,代码全程注释,新手可直接复制运行,每一步均有详细说明。
# 导入核心库
import requests
from bs4 import BeautifulSoup
import pandas as pd
from fake_useragent import UserAgent
import time
import random
# 1. 配置目标股票信息(可修改股票代码和名称)
stock_code = "600519" # 贵州茅台股票代码
stock_name = "贵州茅台" # 股票名称,用于保存文件命名
# 2. 配置163财经财务报表页面URL(A股通用格式)
base_url = f"http://quotes.money.163.com/{stock_code}.html"
# 3. 生成随机User-Agent,模拟真实浏览器访问
ua = UserAgent()
headers = {
"User-Agent": ua.random, # 随机User-Agent,避免反爬
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Referer": "http://quotes.money.163.com/", # 模拟来源页面,提升爬取成功率
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.8"
}
通过requests库发送GET请求,获取目标页面的HTML源码,加入异常处理与请求延迟,避免请求失败或触发反爬。
def get_page_html(url):
"""获取页面HTML源码,加入异常处理和请求延迟"""
try:
# 控制请求频率,随机延迟1-3秒,避免频繁请求触发反爬
time.sleep(random.uniform(1, 3))
# 发送GET请求
response = requests.get(url=url, headers=headers, timeout=10)
# 设置编码格式,避免中文乱码
response.encoding = "utf-8"
# 验证请求是否成功(状态码200表示成功)
if response.status_code == 200:
return response.text # 返回页面HTML源码
else:
print(f"请求失败,状态码:{response.status_code}")
return None
except Exception as e:
print(f"请求异常:{str(e)}")
return None
# 调用函数,获取财务报表页面HTML源码
page_html = get_page_html(base_url)
163财经的财务数据以HTML表格形式呈现,通过BeautifulSoup定位表格,提取“利润表”“资产负债表”“现金流量表”三大核心报表数据,整理为DataFrame格式。
def parse_financial_data(html):
"""解析HTML源码,提取三大财务报表数据"""
if not html:
return None, None, None
# 初始化BeautifulSoup解析器
soup = BeautifulSoup(html, "lxml")
# 定义函数,提取单个报表数据(通用函数,可复用)
def extract_table(table_id):
"""根据表格标识,提取单个报表数据"""
table = soup.find("table", id=table_id)
if not table:
return None
# 提取表头(表格第一行)
headers = [th.text.strip() for th in table.find_all("th")]
# 提取表格内容(除表头外的所有行)
rows = []
for tr in table.find_all("tr")[1:]: # 跳过表头行
row = [td.text.strip() for td in tr.find_all("td")]
if row: # 过滤空行
rows.append(row)
# 转换为DataFrame格式
df = pd.DataFrame(rows, columns=headers)
return df
# 提取三大报表数据(163财经表格标识固定,可直接使用)
income_statement = extract_table("f10-lrb-table") # 利润表
balance_sheet = extract_table("f10-zcfz-table") # 资产负债表
cash_flow = extract_table("f10-xjll-table") # 现金流量表
return income_statement, balance_sheet, cash_flow
# 调用函数,解析三大报表数据
income_df, balance_df, cash_df = parse_financial_data(page_html)
爬取的原始数据可能存在空值、空格、异常符号(如“--”“暂无数据”),需进行清洗,确保数据可用性,便于后续分析。
def clean_data(df, report_type):
"""数据清洗:处理空值、异常值,规范数据格式"""
if df is None:
print(f"{report_type}数据为空,跳过清洗")
return None
# 1. 处理空值和异常符号(将“--”“暂无数据”替换为NaN)
df = df.replace(["--", "暂无数据", ""], pd.NA)
# 2. 过滤完全空的行和列
df = df.dropna(how="all", axis=0) # 删除完全空的行
df = df.dropna(how="all", axis=1) # 删除完全空的列
# 3. 规范数值格式(将字符串类型的数值转换为浮点型,忽略非数值列)
for col in df.columns[1:]: # 跳过第一列(指标名称)
df[col] = pd.to_numeric(df[col], errors="coerce")
# 4. 添加股票名称和股票代码列,便于批量爬取时区分数据
df["股票代码"] = stock_code
df["股票名称"] = stock_name
return df
# 清洗三大报表数据
income_clean = clean_data(income_df, "利润表")
balance_clean = clean_data(balance_df, "资产负债表")
cash_clean = clean_data(cash_df, "现金流量表")
将清洗后的财务数据保存为Excel文件(支持多工作表,分别存储三大报表),也可保存为CSV格式,便于用Excel、PowerBI或Python进行后续分析。
def save_data(income_df, balance_df, cash_df):
"""保存清洗后的财务数据为Excel文件"""
# 定义保存路径(当前文件夹,以股票名称命名)
save_path = f"{stock_name}_{stock_code}_财务报表.xlsx"
# 使用ExcelWriter保存多工作表
with pd.ExcelWriter(save_path, engine="openpyxl") as writer:
if income_df is not None:
income_df.to_excel(writer, sheet_name="利润表", index=False)
if balance_df is not None:
balance_df.to_excel(writer, sheet_name="资产负债表", index=False)
if cash_df is not None:
cash_df.to_excel(writer, sheet_name="现金流量表", index=False)
print(f"✅ 数据保存成功!保存路径:{save_path}")
# 调用函数,保存数据
save_data(income_clean, balance_clean, cash_clean)
# Python爬取163网易财经上市公司财务报表(完整代码)
import requests
from bs4 import BeautifulSoup
import pandas as pd
from fake_useragent import UserAgent
import time
import random
# 配置参数
stock_code = "600519" # 股票代码
stock_name = "贵州茅台" # 股票名称
base_url = f"http://quotes.money.163.com/{stock_code}.html"
# 生成随机User-Agent
ua = UserAgent()
headers = {
"User-Agent": ua.random,
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Referer": "http://quotes.money.163.com/",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.8"
}
# 1. 获取页面HTML源码
def get_page_html(url):
try:
time.sleep(random.uniform(1, 3))
response = requests.get(url=url, headers=headers, timeout=10)
response.encoding = "utf-8"
if response.status_code == 200:
return response.text
else:
print(f"请求失败,状态码:{response.status_code}")
return None
except Exception as e:
print(f"请求异常:{str(e)}")
return None
# 2. 解析财务数据
def parse_financial_data(html):
if not html:
return None, None, None
soup = BeautifulSoup(html, "lxml")
def extract_table(table_id):
table = soup.find("table", id=table_id)
if not table:
return None
headers = [th.text.strip() for th in table.find_all("th")]
rows = []
for tr in table.find_all("tr")[1:]:
row = [td.text.strip() for td in tr.find_all("td")]
if row:
rows.append(row)
return pd.DataFrame(rows, columns=headers)
income_statement = extract_table("f10-lrb-table")
balance_sheet = extract_table("f10-zcfz-table")
cash_flow = extract_table("f10-xjll-table")
return income_statement, balance_sheet, cash_flow
# 3. 数据清洗
def clean_data(df, report_type):
if df is None:
print(f"{report_type}数据为空,跳过清洗")
return None
df = df.replace(["--", "暂无数据", ""], pd.NA)
df = df.dropna(how="all", axis=0)
df = df.dropna(how="all", axis=1)
for col in df.columns[1:]:
df[col] = pd.to_numeric(df[col], errors="coerce")
df["股票代码"] = stock_code
df["股票名称"] = stock_name
return df
# 4. 保存数据
def save_data(income_df, balance_df, cash_df):
save_path = f"{stock_name}_{stock_code}_财务报表.xlsx"
with pd.ExcelWriter(save_path, engine="openpyxl") as writer:
if income_df is not None:
income_df.to_excel(writer, sheet_name="利润表", index=False)
if balance_df is not None:
balance_df.to_excel(writer, sheet_name="资产负债表", index=False)
if cash_df is not None:
cash_df.to_excel(writer, sheet_name="现金流量表", index=False)
print(f"✅ 数据保存成功!保存路径:{save_path}")
# 主函数:执行爬取流程
def main():
print(f"开始爬取{stock_name}({stock_code})财务报表...")
page_html = get_page_html(base_url)
income_df, balance_df, cash_df = parse_financial_data(page_html)
income_clean = clean_data(income_df, "利润表")
balance_clean = clean_data(balance_df, "资产负债表")
cash_clean = clean_data(cash_df, "现金流量表")
save_data(income_clean, balance_clean, cash_clean)
print("爬取完成!")
# 执行主函数
if __name__ == "__main__":
main()
若需爬取多只上市公司财务报表,只需将股票代码和名称整理为列表,循环调用主函数即可,核心修改代码如下:
# 批量爬取多只股票财务报表
stock_list = [
{"code": "600519", "name": "贵州茅台"},
{"code": "300750", "name": "宁德时代"},
{"code": "000333", "name": "美的集团"},
{"code": "601933", "name": "永辉超市"}
]
# 循环爬取每只股票
for stock in stock_list:
stock_code = stock["code"]
stock_name = stock["name"]
base_url = f"http://quotes.money.163.com/{stock_code}.html"
main() # 调用主函数,爬取单只股票数据
time.sleep(random.uniform(2, 4)) # 批量爬取时,增加延迟,避免反爬
爬取过程中,新手容易遇到请求失败、数据提取为空、被反爬限制等问题,以下5个注意事项,帮你规避风险,确保爬取顺利。
163网易财经对单一IP的请求频率有一定限制,若频繁发送请求,会被识别为爬虫,导致IP被临时封禁(表现为请求状态码403)。解决方案:在请求之间加入随机延迟(1-3秒),批量爬取时延迟可增加至2-4秒,模拟真实用户浏览行为,避免触发反爬机制。
若仅使用默认请求头,网站会识别为爬虫,拒绝返回数据。解决方案:使用fake_useragent库生成随机User-Agent,同时添加Referer字段(模拟页面来源),完善请求头信息,提升爬取成功率,代码中已集成该逻辑,无需额外修改。
部分上市公司的财务数据采用JavaScript动态加载(如部分港股数据),直接爬取HTML源码无法获取数据。解决方案:通过浏览器开发者工具(F12)抓包,找到动态加载的JSON接口,直接请求接口获取数据,无需解析HTML,具体可参考163财经的接口规律(如主要财务指标的JSON接口)。
爬取的原始数据中,常见“--”“暂无数据”等异常符号,若不清洗,会导致后续数值分析失败。解决方案:代码中已集成空值、异常值处理逻辑,若遇到特殊异常符号,可在clean_data函数中添加替换规则(如df = df.replace("异常符号", pd.NA))。
163网易财经的财务数据为公开信息,但爬取时需遵守网站robots协议,不进行恶意爬取(如高频请求、批量爬取大量数据),不将爬取的数据用于商业用途,仅用于个人学习、研究,避免违反相关法律法规和网站使用条款。
爬取并清洗后的财务报表数据,可用于多种场景,无论是个人学习、投资分析,还是数据分析实操,都具有很高的实用价值,结合Python可实现更深度的分析:
通过pandas计算核心财务指标,如净资产收益率(ROE)、毛利率、资产负债率、净利润增长率等,分析企业的盈利能力、偿债能力、成长能力。例如,计算贵州茅台的毛利率,判断其产品竞争力;计算资产负债率,评估其财务风险,这也是财报分析的核心环节之一。
批量爬取同行业多家上市公司的财务数据,对比其核心指标,筛选优质企业。例如,爬取白酒行业(茅台、五粮液、泸州老窖)的财务报表,对比三者的净利润、毛利率,分析行业竞争格局。
结合matplotlib、seaborn等库,将财务数据可视化,如绘制净利润趋势图、资产负债结构饼图、现金流变化折线图,直观呈现企业经营状况,让分析结果更具说服力,这也契合163财经新版页面的图表化展示趋势。
对于数据分析新手而言,爬取财务报表是练习Python爬虫、数据清洗、数据处理的优质案例,涵盖requests、BeautifulSoup、pandas等核心库的使用,同时可熟悉财务数据的结构,提升数据分析实操能力,为后续从事金融数据分析打下基础。
相较于传统的手动下载、复制粘贴,使用Python爬取163网易财经上市公司财务报表,核心优势在于“高效、批量、可复用”——无需手动操作,即可快速获取单只或多只股票的完整财务数据,自动整理清洗,大幅节省时间成本;同时,163财经的数据共识性高、格式规范,爬取难度低,适合新手入门实操。
本文的实操代码可直接复制运行,修改股票代码即可适配不同上市公司,批量爬取扩展简单,兼顾实用性与易懂性。需要注意的是,爬取过程中需遵守反爬规则与合规要求,控制请求频率,模拟真实用户行为,避免出现IP封禁等问题。
无论是金融从业者、投资者,还是数据分析新手,掌握Python爬取163财经财务报表的方法,都能让财务数据获取与分析更高效,让数据成为决策、学习、研究的有力支撑,真正发挥数据的价值。

数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
为什么学习数据分析? 当下,我们已然步入数据要素价值全面释放的智能时代。数据不再只是零散的数字记录,更是驱动新质生产力运 ...
2026-07-24【核心关键词】客户、数据分析、指标体系、数据采集、数据指标、业务数据、分析思路、业务需求、分析方法 【专访摘要】本次 CDA ...
2026-07-24在数据分析、业务建模与数字化运营体系中,原始业务数据普遍存在缺失、重复、异常、口径不一致等质量问题,直接用于分析与建模会 ...
2026-07-24 很多数据分析师能熟练计算均值、标准差,但当被问到“如何用一张图让业务方3秒内看懂核心结论”“面对不同数据类型该怎么选 ...
2026-07-24在数据驱动的精细化运营体系中,指标是业务判断、效果复盘、策略优化的核心依据。随着企业数据化程度提升,指标数量持续膨胀,但 ...
2026-07-23在用户运营与产品增长体系中,留存是衡量产品真实价值与用户粘性的核心标尺,也是决定用户生命周期价值、获客投产比的底层因素。 ...
2026-07-23 很多数据分析师精通Excel、SQL、Python等工具,但当被问到“面对一个具体的业务问题,该用什么分析方法”“描述性分析和诊断 ...
2026-07-23【核心关键词】埋点、产品、互联网、数据库、决策、数据分析、产品经理、商业模式、移动互联网、指标体系、运营模块、大数据平 ...
2026-07-22在高并发、大数据量的业务系统中,单表数据量达到千万级甚至亿级后,会出现查询性能骤降、索引维护成本飙升、存储扩容困难等问题 ...
2026-07-22 很多企业团队并非缺乏指标,而是陷入“指标失控”:仪表盘上堆满实时跳动的数据,却无法回答“当前瓶颈在哪、下一步该做什么 ...
2026-07-22在金融风控、企业运营、行业研究等数据分析场景中,大量数据以面板数据形态存在:例如多家分支机构连续多个季度的风险指标、多位 ...
2026-07-21 很多数据分析师每天都在计算指标、制作报表,但当被问到“什么叫指标数据元”“指标数据标准包含哪些核心维度”“指标数据质 ...
2026-07-21一、活动介绍 2026暑期CDA备考冲刺季,为想利用假期拿证的你量身打造。考点胶囊内容搭配多重硬核福利,让你在旅行、实习、居家 ...
2026-07-21金融行业的运营风险贯穿业务全流程,涵盖交易欺诈、操作违规、流程漏洞、合规偏差、客户信用异常等多元场景,是银行、保险、证券 ...
2026-07-17财产保险作为金融行业的核心板块,涵盖车险、家财险、责任险、企财险等多元品类,是个人与企业抵御财产风险、经营风险的重要保障 ...
2026-07-17 很多数据分析师能熟练写SQL、做透视表,但当被问到“数据是从哪里来的?经过哪些加工才进入数据仓库?ETL具体做了什么?”时 ...
2026-07-17【核心关键词】模块、餐饮、客户、门店、企业、订单、供应链、多样化、产品、生产计划、数据分析、生产管理、物料管理、业务分 ...
2026-07-16在数字化分析时代,原始数据本身不具备业务价值,只有通过科学的统计学方法加工、拆解、验证与解读,才能挖掘数据背后的规律、差 ...
2026-07-16 很多数据分析师能熟练地写SQL、做透视表、算描述性统计,但当被问到“如何预测用户流失概率”“如何归因销量下滑的关键因素 ...
2026-07-16在描述性统计分析、数据预处理、异常值排查与多组数据分布对比工作中,箱线图(Box Plot)是应用最广泛的可视化与统计工具之一。 ...
2026-07-15