金融数据获取:获取上市公司财务报表

        前段时间介绍了selenium模拟爬虫,应对很多需要动态加载或鼠标点击的网页都非常有效,本期介绍一个js动态加载的网页爬虫。正好笔者也很久没有写爬虫了,当是练练手。目标定为新浪财经,获取上证指数成分股近3年的利润表数据,爬取完成后保存到本地csv中。


目录

1. 获取所有公司列表

2. 爬取单个公司历史财务数据

3. 批量爬取历史数据


        先导入一些必要模块:

import pandas as pd
import requests
import re

1. 获取所有公司列表

        打开新浪的行情中心,选择相关指数即可以查看所有成分股:行情中心_新浪财经。如图,每页如果显示80条,一共有25页,利用循环遍历爬取是没跑了。

         新浪的难点在于翻页是通过js请求完成的,也就是说无论点击哪一页,浏览器上显示的网址都是一样的。笔者通过Telerik fiddler工具抓取到翻页时的网址如下:

url = "https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeDataSimple?page=1&num=80&sort=symbol&asc=1&node=zhishu_000001&_s_r_a=page"

        当然,键盘F12在网络里一条条找访问记录也是可以找到这个网址的:

         观察该网址不难发现,"page="的字段就是翻页的参数。"num="的字段就是每页显示多少条记录的参数。

        下面改写一下,加入翻页循环。利用正则表达式匹配公司代码最后存进表格:

stock_list = []
for i in range(1, 26):
    url = "https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeDataSimple?page="+str(i)+"&num=80&sort=symbol&asc=1&node=zhishu_000001&_s_r_a=page"
    response = requests.get(url).text
    symbol = re.findall('"symbol":"(.*?)","name"',response,re.S)
    stock_list.extend(symbol)

print(stock_list[:5])
print("共获取:", len(stock_list))

# ['sh600000', 'sh600004', 'sh600006', 'sh600007', 'sh600008']
# 共获取: 2000

        共获取到2000家公司代码。

2. 爬取单个公司历史财务数据

        一样先观察网址,笔者找到一个较为容易的网址结构:http://money.finance.sina.com.cn/corp/go.php/vFD_ProfitStatement/stockid/600585/ctrl/2022/displaytype/4.phtml

        新浪这个网址不是通过js请求的,可以直接在浏览器上复制粘贴,只要改改公司代码和年份即可,内容属于可见即可爬的表格:

url = "http://money.finance.sina.com.cn/corp/go.php/vFD_ProfitStatement/stockid/600000/" \
    "ctrl/2022/displaytype/4.phtml"
df = pd.read_html(url, attrs = {"id": "ProfitStatementNewTable0"}, header=[1], index_col=0)[0]
df.dropna(axis=1, how="all", inplace=True)

print(df)

                2022-09-30	2022-06-30	2022-03-31
报表日期			
    NaN	            NaN	        NaN	        NaN
一、营业收入	14368000.00	9864400.00	5000200.00
利息净收入	10159200.00	6868100.00	3450200.00
其中:利息收入	22503100.00	15027800.00	7533200.00
减:利息支出	12343900.00	8159700.00	4083000.00
...

        但这样只能请求到三期的财报,如果要更多期就需要循环遍历了,不过也很简单:

url = "http://money.finance.sina.com.cn/corp/go.php/vFD_ProfitStatement/stockid/600000/ctrl/2022/displaytype/4.phtml"
df = pd.read_html(url, attrs = {"id": "ProfitStatementNewTable0"}, header=[1], index_col=0)[0]
df.dropna(axis=1, how="all", inplace=True)

for i in range(1, 4):
    url = "http://money.finance.sina.com.cn/corp/go.php/vFD_ProfitStatement/stockid/600000/ctrl/"+str(2022-i)+"/displaytype/4.phtml"
    df_1 = pd.read_html(url, attrs = {"id": "ProfitStatementNewTable0"}, header=[1], index_col=0)[0]
    df_1.dropna(axis=1, how="all", inplace=True)
    df = pd.concat([df, df_1], axis=1) 

df = df.dropna(how="all")
print(df)

报表日期         2022-09-30	2022-06-30	2022-03-31	2021-12-31	2021-09-30	2021-06-30	2021-03-31	2020-12-31	2020-09-30	2020-06-30	2020-03-31	2019-12-31	2019-09-30	2019-06-30	2019-03-31														
一、营业收入	14368000.00	9864400.00	5000200.00	19098200.00	14348400.00	9736500.00	4952200.00	19638400.00	14873100.00	10140700.00	5542400.00	19068800.00	14638600.00	9759900.00	5008400.00
利息净收入	10159200.00	6868100.00	3450200.00	13595800.00	10138900.00	6766200.00	3367200.00	13858100.00	9145600.00	6187500.00	3209600.00	12885000.00	9782200.00	6426400.00	3144600.00

3. 批量爬取历史数据

        将上面的代码改写成函数传参,遍历所有的公司代码即可。封装好后加入一些进度显示,时间计算的代码,一个精致的利润表数据获取程序就完成了:

def craw_list():
    stock_list = []
    for i in range(1, 26):
        url = "https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeDataSimple?page="+str(i)+"&num=80&sort=symbol&asc=1&node=zhishu_000001&_s_r_a=page"
        response = requests.get(url).text
        symbol = re.findall('"symbol":"(.*?)","name"',response,re.S)
        stock_list.extend(symbol)
    return stock_list


def craw_mod(code, year):
    url = "http://money.finance.sina.com.cn/corp/go.php/vFD_ProfitStatement/stockid/"+code+"/ctrl/2022/displaytype/4.phtml"
    df = pd.read_html(url, attrs = {"id": "ProfitStatementNewTable0"}, header=[1], index_col=0)[0]
    df.dropna(axis=1, how="all", inplace=True)

    for i in range(1, year):
        url = "http://money.finance.sina.com.cn/corp/go.php/vFD_ProfitStatement/stockid/"+code+"/ctrl/"+str(2022-i)+"/displaytype/4.phtml"
        df_1 = pd.read_html(url, attrs = {"id": "ProfitStatementNewTable0"}, header=[1], index_col=0)[0]
        df_1.dropna(axis=1, how="all", inplace=True)
        df = pd.concat([df, df_1], axis=1) 
        df.dropna(how="all")
        
    df.to_csv(code + ".csv") # 存储路径
    

def main():
    stock_list = craw_list()
    for code in stock_list:
        craw_mod(code[2:], 3) # code前两个字符为"sh",要去掉
        print("爬取进度{}%\r".format('%.2f'% (100*(stock_list.index(code) + 1)/len(stock_list))), end = "")


if __name__=="__main__":
    import datetime
    start = datetime.datetime.now()
    main()
    end = datetime.datetime.now()
    print("程序耗时:", end - start)

        当然,用多线程或者多进程辅助加速也是可以的,这里就不进行展示了。

        在刚刚的网址中找到资产负债表、现金流量表的网址链接就可以进一步把其它两张表也爬下来,都是一样的操作,换换网址而已,笔者也不进行更多展示了。

        最后都保存到了本地:

Python中爬取新浪财经数据通常涉及网络爬虫技术,例如使用`requests`库获取网页内容,然后解析HTML或JSON数据,最后将结果存储到Excel中。这里我们可以使用`beautifulsoup4`处理HTML,`pandas`处理数据,并利用`openpyxl`或`xlsxwriter`来创建Excel文件。 以下是一个简单的步骤说明: 1. **安装必要的库**: 首先需要安装 `requests`, `beautifulsoup4`, `lxml` (BeautifulSoup的一个依赖库), `pandas` 和 Excel操作库,如 `openpyxl` 或 `xlsxwriter`。可以使用下面的命令安装: ```bash pip install requests beautifulsoup4 lxml pandas openpyxl xlsxwriter ``` 2. **获取网页内容**: 使用`requests.get()`函数获取目标网页的HTML内容: ```python import requests url = 'http://stock.finance.sina.com.cn/fund/f10/F10Data_SSE.php?code=股票代码' response = requests.get(url) html_content = response.text ``` 3. **解析HTML**: 使用BeautifulSoup解析HTML,找到包含财务报表信息的部分: ```python from bs4 import BeautifulSoup soup = BeautifulSoup(html_content, 'lxml') table_data = soup.find('table') # 找到表格元素 ``` 4. **提取数据**: 解析表格数据,这可能涉及到查找特定标签、属性或CSS选择器来获取你需要的财务指标。假设财务数据在`tr`标签内: ```python data_rows = table_data.find_all('tr') financial_data = [] for row in data_rows: cells = row.find_all('td') row_data = [cell.text.strip() for cell in cells] financial_data.append(row_data) ``` 5. **保存到Excel**: 使用`pandas`将数据转换成DataFrame,然后用`openpyxl`或`xlsxwriter`将其写入Excel文件: ```python import pandas as pd df = pd.DataFrame(financial_data, columns=['列名1', '列名2', ...]) # 根据实际数据填充列名 writer = pd.ExcelWriter('财务报表.xlsx', engine='openpyxl') # 或者 'xlsxwriter' df.to_excel(writer, sheet_name='Sheet1', index=False) # 如果有多个表,可以用sheet_name参数指定 writer.save() ``` 注意:实际操作时,你需要根据新浪财经网站的具体结构调整上述代码。同时,频繁抓取网络数据可能会触发网站的反爬策略,所以在编写爬虫时要注意遵守网站的robots.txt规则,并尽量降低请求频率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Simon Cao

创作不易,您的鼓励将是我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值