热线电话:13121318867

登录
首页大数据时代【CDA干货】Python爬取163网易财经上市公司财务报表:实操指南与数据应用
【CDA干货】Python爬取163网易财经上市公司财务报表:实操指南与数据应用
2026-03-11
收藏

上市公司财务报表是反映企业经营状况、盈利能力、偿债能力的核心数据载体,是投资者决策、研究者分析、从业者复盘的重要依据。163网易财经作为国内权威的财经数据平台,整合了全A股、港股、美股上市公司的完整财务数据,涵盖资产负债表、利润表、现金流量表及核心财务指标,且数据更新及时、格式规范,是爬取上市公司财务数据的优选数据源。

相较于交易所官网的繁琐下载、第三方工具的付费限制,使用Python爬取163网易财经的财务报表,可实现“批量获取、自动整理、高效分析”,大幅提升数据获取效率,尤其适合需要批量处理多只股票财务数据的场景。本文将从爬取原理、环境准备、完整实操步骤、反爬应对、数据清洗与应用五个维度,手把手教你用Python爬取163网易财经上市公司财务报表,兼顾新手友好性与实操落地性,避开常见爬取误区。

一、爬取核心原理:读懂163财经的页面结构与数据规律

在动手写代码前,需先明确163网易财经财务报表的页面结构与数据加载逻辑——这是爬取成功的关键,也是避开反爬的核心前提。

1. 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格式数据)。

  • 数据格式:所有财务数据均为标准化格式,包含报告日期、指标名称、具体数值、单位等信息,且同一类型报表(如利润表)的表头结构一致,便于后续批量解析与整理。

2. 爬取核心逻辑

本次爬取采用“请求页面→解析页面→提取数据→保存数据”的核心流程,依托Python的requests库发送HTTP请求,获取页面HTML源码,再通过BeautifulSoup库解析HTML结构,提取表格中的财务数据,最后将数据整理为Excel或CSV格式,便于后续分析使用。

需注意:163网易财经存在基础反爬机制(如User-Agent检测、请求频率限制),无需复杂的加密破解,只需模拟真实浏览器行为、控制请求频率,即可顺利爬取数据,新手可轻松上手。

二、前置准备:环境搭建与工具安装

爬取前需完成Python环境搭建与相关库安装,所有操作均适用于Windows、MacOS系统,步骤简单可复制。

1. 环境要求

Python版本:3.7及以上(推荐3.9版本,兼容性更好),可通过Python官网下载安装,安装时勾选“Add Python to PATH”,便于后续命令行调用。

2. 必备库安装

本次爬取需用到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源码,定位表格位置,提取财务指标与数值;

  • pandas:将提取的原始数据整理为DataFrame格式,清洗空值、异常值,保存为Excel/CSV文件;

  • fake_useragent:生成随机的浏览器User-Agent,模拟真实用户访问,避免被网站识别为爬虫。

三、完整实操:Python爬取163财经财务报表(以A股为例)

本次以爬取“贵州茅台(600519)”的财务报表为例,实现“单只股票爬取”,后续可扩展为“批量爬取多只股票”,代码全程注释,新手可直接复制运行,每一步均有详细说明。

1. 导入所需库

# 导入核心库
import requests
from bs4 import BeautifulSoup
import pandas as pd
from fake_useragent import UserAgent
import time
import random

2. 配置核心参数(可灵活修改)

# 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"
}

3. 发送请求,获取页面源码

通过requests库发送GET请求,获取目标页面的HTML源码,加入异常处理与请求延迟,避免请求失败或触发反爬。

def get_page_html(url):
    """获取页面HTML源码,加入异常处理和请求延迟"""
    try:
        # 控制请求频率,随机延迟1-3秒,避免频繁请求触发反爬
        time.sleep(random.uniform(13))
        # 发送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)

4. 解析页面,提取财务数据

163财经的财务数据以HTML表格形式呈现,通过BeautifulSoup定位表格,提取“利润表”“资产负债表”“现金流量表”三大核心报表数据,整理为DataFrame格式。

def parse_financial_data(html):
    """解析HTML源码,提取三大财务报表数据"""
    if not html:
        return NoneNoneNone
    
    # 初始化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)

5. 数据清洗,处理异常值

爬取的原始数据可能存在空值、空格、异常符号(如“--”“暂无数据”),需进行清洗,确保数据可用性,便于后续分析。

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, "现金流量表")

6. 保存数据,便于后续应用

将清洗后的财务数据保存为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)

7. 完整代码整合(可直接复制运行)

# 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(13))
        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 NoneNoneNone
    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()

8. 批量爬取扩展(可选)

若需爬取多只上市公司财务报表,只需将股票代码和名称整理为列表,循环调用主函数即可,核心修改代码如下:

# 批量爬取多只股票财务报表
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(24))  # 批量爬取时,增加延迟,避免反爬

四、避坑指南:163财经爬取的5个关键注意事项

爬取过程中,新手容易遇到请求失败、数据提取为空、被反爬限制等问题,以下5个注意事项,帮你规避风险,确保爬取顺利。

1. 控制请求频率,规避反爬限制

163网易财经对单一IP的请求频率有一定限制,若频繁发送请求,会被识别为爬虫,导致IP被临时封禁(表现为请求状态码403)。解决方案:在请求之间加入随机延迟(1-3秒),批量爬取时延迟可增加至2-4秒,模拟真实用户浏览行为,避免触发反爬机制。

2. 模拟真实浏览器,完善请求头

若仅使用默认请求头,网站会识别为爬虫,拒绝返回数据。解决方案:使用fake_useragent库生成随机User-Agent,同时添加Referer字段(模拟页面来源),完善请求头信息,提升爬取成功率,代码中已集成该逻辑,无需额外修改。

3. 处理动态加载数据(特殊情况)

部分上市公司的财务数据采用JavaScript动态加载(如部分港股数据),直接爬取HTML源码无法获取数据。解决方案:通过浏览器开发者工具(F12)抓包,找到动态加载的JSON接口,直接请求接口获取数据,无需解析HTML,具体可参考163财经的接口规律(如主要财务指标的JSON接口)。

4. 数据清洗要彻底,避免后续分析出错

爬取的原始数据中,常见“--”“暂无数据”等异常符号,若不清洗,会导致后续数值分析失败。解决方案:代码中已集成空值、异常值处理逻辑,若遇到特殊异常符号,可在clean_data函数中添加替换规则(如df = df.replace("异常符号", pd.NA))。

5. 遵守合规性,不滥用爬虫技术

163网易财经的财务数据为公开信息,但爬取时需遵守网站robots协议,不进行恶意爬取(如高频请求、批量爬取大量数据),不将爬取的数据用于商业用途,仅用于个人学习、研究,避免违反相关法律法规和网站使用条款。

五、数据应用:爬取后的财务报表能做什么?

爬取并清洗后的财务报表数据,可用于多种场景,无论是个人学习、投资分析,还是数据分析实操,都具有很高的实用价值,结合Python可实现更深度的分析:

1. 财务指标分析

通过pandas计算核心财务指标,如净资产收益率(ROE)、毛利率、资产负债率、净利润增长率等,分析企业的盈利能力、偿债能力、成长能力。例如,计算贵州茅台的毛利率,判断其产品竞争力;计算资产负债率,评估其财务风险,这也是财报分析的核心环节之一。

2. 多公司对比分析

批量爬取同行业多家上市公司的财务数据,对比其核心指标,筛选优质企业。例如,爬取白酒行业(茅台、五粮液、泸州老窖)的财务报表,对比三者的净利润、毛利率,分析行业竞争格局。

3. 数据可视化呈现

结合matplotlibseaborn等库,将财务数据可视化,如绘制净利润趋势图、资产负债结构饼图、现金流变化折线图,直观呈现企业经营状况,让分析结果更具说服力,这也契合163财经新版页面的图表化展示趋势。

4. 个人学习与实操练习

对于数据分析新手而言,爬取财务报表是练习Python爬虫、数据清洗数据处理的优质案例,涵盖requests、BeautifulSoup、pandas等核心库的使用,同时可熟悉财务数据的结构,提升数据分析实操能力,为后续从事金融数据分析打下基础。

六、总结:Python爬取163财经财务报表的核心优势与价值

相较于传统的手动下载、复制粘贴,使用Python爬取163网易财经上市公司财务报表,核心优势在于“高效、批量、可复用”——无需手动操作,即可快速获取单只或多只股票的完整财务数据,自动整理清洗,大幅节省时间成本;同时,163财经的数据共识性高、格式规范,爬取难度低,适合新手入门实操。

本文的实操代码可直接复制运行,修改股票代码即可适配不同上市公司,批量爬取扩展简单,兼顾实用性与易懂性。需要注意的是,爬取过程中需遵守反爬规则与合规要求,控制请求频率,模拟真实用户行为,避免出现IP封禁等问题。

无论是金融从业者、投资者,还是数据分析新手,掌握Python爬取163财经财务报表的方法,都能让财务数据获取与分析更高效,让数据成为决策、学习、研究的有力支撑,真正发挥数据的价值。

推荐学习书籍 《CDA一级教材》适合CDA一级考生备考,也适合业务及数据分析岗位的从业者提升自我。完整电子版已上线CDA网校,累计已有10万+在读~ !

免费加入阅读:https://edu.cda.cn/goods/show/3151?targetId=5147&preview=0

数据分析师资讯
更多

OK
客服在线
立即咨询
客服在线
立即咨询