京公网安备 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-04-24在游戏行业竞争白热化的当下,用户流失已成为制约游戏生命周期、影响营收增长的核心痛点。据行业报告显示,2024年移动游戏平均次 ...
2026-04-24 很多业务负责人开会常说“我们要数据驱动”,最后却变成“看哪张报表数据多就用哪个”,往往因为缺乏一套结构性的方法去搭建 ...
2026-04-24在Power BI数据可视化分析中,切片器是连接用户与数据的核心交互工具,其核心价值在于帮助使用者快速筛选目标数据、聚焦分析重点 ...
2026-04-23以数为据,以析促优——数据分析结果指导临床技术改进的实践路径 临床技术是医疗服务的核心载体,其水平直接决定患者诊疗效果、 ...
2026-04-23很多数据分析师每天盯着GMV、DAU、转化率,但当被问到“哪些指标是所有企业都需要的”“哪些指标是因行业而异的”“北极星指标和 ...
2026-04-23近日,由 CDA 数据科学研究院重磅发布的《2026 全球数智化人才指数报告》,被中国教育科学研究院官方账号正式收录, ...
2026-04-22在数字化时代,客户每一次点击、浏览、下单、咨询等行为,都在传递其潜在需求与决策倾向——这些按时间顺序串联的行为轨迹,构成 ...
2026-04-22数据是数据分析、建模与业务决策的核心基石,而“数据清洗”作为数据预处理的核心环节,是打通数据从“原始杂乱”到“干净可用” ...
2026-04-22 很多数据分析师每天盯着GMV、转化率、DAU等数字看,但当被问到“什么是指标”“指标和维度有什么区别”“如何搭建一套完整的 ...
2026-04-22在数据分析与业务决策中,数据并非静止不变的数值,而是始终处于动态波动之中——股市收盘价的每日涨跌、企业月度销售额的起伏、 ...
2026-04-21在数据分析领域,当研究涉及多个自变量与多个因变量之间的复杂关联时,多变量一般线性分析(Multivariate General Linear Analys ...
2026-04-21很多数据分析师精通描述性统计,能熟练计算均值、中位数、标准差,但当被问到“用500个样本如何推断10万用户的真实满意度”“这 ...
2026-04-21在数据处理与分析的全流程中,日期数据是贯穿业务场景的核心维度之一——无论是业务报表统计、用户行为追踪,还是风控规则落地、 ...
2026-04-20在机器学习建模全流程中,特征工程是连接原始数据与模型效果的关键环节,而特征重要性分析则是特征工程的“灵魂”——它不仅能帮 ...
2026-04-20很多数据分析师沉迷于复杂的机器学习算法,却忽略了数据分析最基础也最核心的能力——描述性统计。事实上,80%的商业分析问题, ...
2026-04-20在数字化时代,数据已成为企业决策的核心驱动力,数据分析与数据挖掘作为解锁数据价值的关键手段,广泛应用于互联网、金融、医疗 ...
2026-04-17在数据处理、后端开发、报表生成与自动化脚本中,将 SQL 查询结果转换为字符串是一项高频且实用的操作。无论是拼接多行数据为逗 ...
2026-04-17面对一份上万行的销售明细表,要快速回答“哪个地区卖得最好”“哪款产品增长最快”“不同客户类型的购买力如何”——这些看似复 ...
2026-04-17数据分析师一天的工作,80% 的时间围绕表格结构数据展开。从一张销售明细表到一份完整的分析报告,表格结构数据贯穿始终。但你真 ...
2026-04-16