Python中如何爬取新浪财经的股票三表数据?

http://vip.stock.finance.sina.com.cn/usstock/balance.php?s=MSFT
这种表准确不?
这种表格是不是可以直接用 pandas 直接爬下来?
还有更好的办法吗?
Python中如何爬取新浪财经的股票三表数据?

7 回复

pandas 什么时候也可以当爬虫用了吗?是我对 pandas 有什么误解吗


import requests
import pandas as pd
from io import StringIO
import time

class SinaFinanceCrawler:
    def __init__(self):
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }
    
    def get_stock_code(self, symbol):
        """将股票代码转换为新浪财经格式"""
        if symbol.startswith('6'):
            return f'sh{symbol}'
        elif symbol.startswith(('0', '3')):
            return f'sz{symbol}'
        else:
            raise ValueError("不支持的股票代码格式")
    
    def get_balance_sheet(self, symbol, year=2023, quarter=4):
        """获取资产负债表"""
        stock_code = self.get_stock_code(symbol)
        url = f'https://quotes.sina.com.cn/corp/go.php/vFD_BalanceSheet/stockid/{symbol}/ctrl/{year}/displaytype/4.phtml'
        
        try:
            response = requests.get(url, headers=self.headers, timeout=10)
            response.encoding = 'gb2312'
            
            # 使用pandas直接解析HTML表格
            tables = pd.read_html(StringIO(response.text))
            
            if len(tables) >= 2:
                # 通常第二个表格是资产负债表数据
                df = tables[1]
                df.columns = df.iloc[0]  # 设置表头
                df = df[1:]  # 移除重复的表头行
                return df
            else:
                print("未找到资产负债表数据")
                return None
                
        except Exception as e:
            print(f"获取资产负债表失败: {e}")
            return None
    
    def get_income_statement(self, symbol, year=2023, quarter=4):
        """获取利润表"""
        stock_code = self.get_stock_code(symbol)
        url = f'https://quotes.sina.com.cn/corp/go.php/vFD_ProfitStatement/stockid/{symbol}/ctrl/{year}/displaytype/4.phtml'
        
        try:
            response = requests.get(url, headers=self.headers, timeout=10)
            response.encoding = 'gb2312'
            
            tables = pd.read_html(StringIO(response.text))
            
            if len(tables) >= 2:
                df = tables[1]
                df.columns = df.iloc[0]
                df = df[1:]
                return df
            else:
                print("未找到利润表数据")
                return None
                
        except Exception as e:
            print(f"获取利润表失败: {e}")
            return None
    
    def get_cash_flow(self, symbol, year=2023, quarter=4):
        """获取现金流量表"""
        stock_code = self.get_stock_code(symbol)
        url = f'https://quotes.sina.com.cn/corp/go.php/vFD_CashFlow/stockid/{symbol}/ctrl/{year}/displaytype/4.phtml'
        
        try:
            response = requests.get(url, headers=self.headers, timeout=10)
            response.encoding = 'gb2312'
            
            tables = pd.read_html(StringIO(response.text))
            
            if len(tables) >= 2:
                df = tables[1]
                df.columns = df.iloc[0]
                df = df[1:]
                return df
            else:
                print("未找到现金流量表数据")
                return None
                
        except Exception as e:
            print(f"获取现金流量表失败: {e}")
            return None
    
    def get_all_statements(self, symbol, year=2023):
        """一次性获取三张财务报表"""
        print(f"正在获取 {symbol} {year}年年报数据...")
        
        balance_sheet = self.get_balance_sheet(symbol, year)
        income_statement = self.get_income_statement(symbol, year)
        cash_flow = self.get_cash_flow(symbol, year)
        
        return {
            'balance_sheet': balance_sheet,
            'income_statement': income_statement,
            'cash_flow': cash_flow
        }

# 使用示例
if __name__ == "__main__":
    crawler = SinaFinanceCrawler()
    
    # 获取贵州茅台(600519)的财务报表
    stock_symbol = "600519"
    year = 2023
    
    statements = crawler.get_all_statements(stock_symbol, year)
    
    # 打印结果
    for statement_name, df in statements.items():
        if df is not None:
            print(f"\n=== {statement_name.upper()} ===")
            print(df.head())
            print(f"数据形状: {df.shape}")

这个爬虫类可以直接获取新浪财经的三大财务报表。核心思路是:

  1. 通过分析新浪财经的URL规律,构建不同报表的请求地址
  2. 使用requests库获取网页内容
  3. 利用pandas的read_html直接解析HTML表格
  4. 对数据进行简单的清洗和整理

代码里我做了错误处理,确保某个表获取失败时不会影响其他表的获取。实际使用时你可以根据需要调整年份参数,或者批量获取多只股票的数据。

注意新浪财经的页面编码是gb2312,所以需要正确设置编码。另外建议在批量爬取时添加适当的延时,避免给服务器造成压力。

直接运行就能看到贵州茅台2023年的三表数据了。

可以的,tushare 就是用 pandas.read_html 直接爬的

pandas 支持表格的。

还不如爬雪球的

雪球更专业?话说如何实现一个股价提醒系统呢

做股价提醒就是按你的策略做

回到顶部