金融数据挖掘(一):A股上市公司2022年年报

A股上市公司年报,是我们分析上市公司财务状况和经营状况,并进行股票估值和行情预测的重要依据。那么,我们应该如何爬取这些上市公司的财报数据,并用于数据分析和可视化呢?今天我们以东方财富网为例,来介绍一下基本的步骤。

一、操作环境

1. 浏览器:Safari浏览器(版本:17.31)

2. Python版本:Python3.12

3. 开发环境:Pycharm 2023.3(Community Edition)

4. 操作系统:MacOS 14.3(Sonoma)

二、网页解析

1. 点击如下网址,进入数据页面

2022年年报业绩大全 _ 数据中心 _ 东方财富网

2. 页面空白处“点击右键”——“检查元素”,进入开发者工具。

    选择”网络“标签页,然后刷新网页,获取所有网页加载项。

 3. 对列表中的所有加载项依次进行预览,寻找数据源地址。

     以本次操作为例,数据源的网址为(数据源网址是动态生成的):

https://datacenter-web.eastmoney.com/api/data/v1/get?callback=jQuery112307880322881038256_1709033016691&sortColumns=UPDATE_DATE%2CSECURITY_CODE&sortTypes=-1%2C-1&pageSize=50&pageNumber=1&reportName=RPT_LICO_FN_CPD&columns=ALL&filter=(REPORTDATE%3D%272022-12-31%27)

4. 分析数据源网址,找出真正的数据源接口

   一般网址的基本结构为:

协议://域名(IP:端口)/资源路径?查询条件(结构:key1=value1&key2=value2)

   据此分析上面的数据源网址,可以发现,真正的数据接口,其实是:

   https://datacenter-web.eastmoney.com/api/data/v1/get

  但是,要想获取到指定数据,“查询条件”部分也是必不可少的。这个我们后面再讲。

5. 分析数据源网址的代码结构,确定爬取方案

   通过“预览”,我们可以发现,数据源网址对应的,其实是一个JSON格式的数据。但这并不是标准的JSON格式数据,还多了一个“jQuery112307880322881038256_1709033016691()”。这个多出来的部分是回调函数,对应数据源网址中的"callback"部分,我们可直接在网址中删除。

 三、编写代码

1. 导入工具包

# coding:utf-8
import requests
import pandas as pd
import json

2. 创建DataFrame表格。注意:变量名要与数据对应

list=pd.DataFrame(columns=['股票代码','股票名称','所在行业','股市类型','交易市场','每股收益','每股净收益','营业总收入','营业收入同比增长','净利润','净利润同比增长','每股净资产','净资产收益率','每股经营现金流量','销售毛利率','利润分配','股息率'])

3. 建立循环,以爬取所有页面的数据。循环范围根据数据的页面数量决定。

4. 使用requests爬取数据

(1)确定爬取数据的url网址,如下:

url='https://datacenter-web.eastmoney.com/api/data/v1/get?sortColumns=UPDATE_DATE%2CSECURITY_CODE&sortTypes=-1%2C-1&pageSize=50&pageNumber='+str(i)+'&reportName=RPT_LICO_FN_CPD&columns=ALL&filter=(REPORTDATE%3D%272022-12-31%27)'

其中”?"之后的”查询条件“部分,分别设为:

sortColumns=UPDATE_DATE%2CSECURITY_CODE    #排序变量#

sortTypes=-1%2C-1    #排序格式#

pageSize=50            #每页的数据量,此处默认为50#  

pageNumber=str(i)    # "i"对应循环数,循环爬取各页数据#

reportName=RPT_LICO_FN_CPD     #报告名#

columns=ALL      #查询所有变量#

filter=(REPORTDATE%3D%272021-12-31%27)     #筛选报告时间,此处默认2022-12-31#

(2)创建表头headers,如下:

header={'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.3.1 Safari/605.1.15',
            'Cookie': 'st_asi=delete; st_inirUrl=https%3A%2F%2Fbaidu.com%2F; st_psi=20240227192236777-113300301066-4864084221; st_pvi=11934193275781; st_sn=13; st_sp=2024-02-26%2015%3A19%3A30; JSESSIONID=37A0895F7D4E1F2005EF79C5B041FC90; st_si=63431626210633; HAList=ty-1-000001-%u4E0A%u8BC1%u6307%u6570; qgqp_b_id=b06ad5d3eaab94f81f12355ecebb1842'}

cookie可以随意复制一个,不影响最终结果。

(3)爬取网页

money=requests.get(url=url,headers=header)
money.encoding='utf8'

5. 解析爬取的JSON数据

data=json.loads(money.text)
chart=data["result"]['data']

6. 将爬取到的数据依次写入DataFrame表格中

k=0
for j in range(50):
   try:
        chartj=chart[j]
        print(chartj)
        code=chartj['SECURITY_CODE']
        abbr=chartj['SECURITY_NAME_ABBR']
        market=chartj['TRADE_MARKET']
        type=chartj['SECURITY_TYPE']
        eps=chartj['BASIC_EPS']
        epsde=chartj['DEDUCT_BASIC_EPS']
        income=chartj['TOTAL_OPERATE_INCOME']
        try:
            incomegrtht=float(chartj['YSTZ'])/100
        except:
            incomegrtht = chartj['YSTZ']
        profit=chartj['PARENT_NETPROFIT']
        try:
            profitgrtht=float(chartj['SJLTZ'])/100
        except:
            profitgrtht = chartj['SJLTZ']
        bps=chartj['BPS']
        try:
            roe=float(chartj['WEIGHTAVG_ROE'])/100
        except:
            roe=chartj['WEIGHTAVG_ROE']
        mgjy=chartj['MGJYXJJE']
        try:
            xsml=float(chartj['XSMLL'])/100
        except:
            xsml=chartj['XSMLL']
        lrfp=chartj['ASSIGNDSCRPT']
        hy=chartj['PUBLISHNAME']
        try:
            gxl=float(chartj['ZXGXL'])/100
        except:
            gxl=chartj['ZXGXL']
        list.loc[k]=[code,abbr,hy,type,market,eps,epsde,income,incomegrtht,profit,profitgrtht,bps,roe,mgjy,xsml,lrfp,gxl]
        k=k+1
   except:
        continue

其中,k=0需要在整个爬虫代码最前端进行声明。

同时,导入变量数据时,要与开头设定的DataFrame表格的变量顺序一致。

7. 把DataFrame表格保存为excel文件

list.to_excel('list.xlsx',index=False)

四、运行代码

运行代码后,在项目所在目录中会生成表格“list.xlsx”。

代码运行时,一般可见如下警告。它并不会影响最终结果,因此可以不予理会:

FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.

 打开该文件,可以看到爬取的数据如下:

最后,附上完整代码

# coding:utf-8
import requests
import pandas as pd
import json
k=0
list=pd.DataFrame(columns=['股票代码','股票名称','所在行业','股市类型','交易市场','每股收益','每股净收益','营业总收入','营业收入同比增长','净利润','净利润同比增长','每股净资产','净资产收益率','每股经营现金流量','销售毛利率','利润分配','股息率'])
for i in range(1,237):
    url='https://datacenter-web.eastmoney.com/api/data/v1/get?sortColumns=UPDATE_DATE%2CSECURITY_CODE&sortTypes=-1%2C-1&pageSize=50&pageNumber='+str(i)+'&reportName=RPT_LICO_FN_CPD&columns=ALL&filter=(REPORTDATE%3D%272022-12-31%27)'
    header={'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.3.1 Safari/605.1.15',
            'Cookie': 'st_asi=delete; st_inirUrl=https%3A%2F%2Fbaidu.com%2F; st_psi=20240227192236777-113300301066-4864084221; st_pvi=11934193275781; st_sn=13; st_sp=2024-02-26%2015%3A19%3A30; JSESSIONID=37A0895F7D4E1F2005EF79C5B041FC90; st_si=63431626210633; HAList=ty-1-000001-%u4E0A%u8BC1%u6307%u6570; qgqp_b_id=b06ad5d3eaab94f81f12355ecebb1842'}
    money=requests.get(url=url,headers=header)
    money.encoding='utf8'
    data=json.loads(money.text)
    chart=data["result"]['data']
    for j in range(50):
     try:
        chartj=chart[j]
        print(chartj)
        code=chartj['SECURITY_CODE']
        abbr=chartj['SECURITY_NAME_ABBR']
        market=chartj['TRADE_MARKET']
        type=chartj['SECURITY_TYPE']
        eps=chartj['BASIC_EPS']
        epsde=chartj['DEDUCT_BASIC_EPS']
        income=chartj['TOTAL_OPERATE_INCOME']
        try:
            incomegrtht=float(chartj['YSTZ'])/100
        except:
            incomegrtht = chartj['YSTZ']
        profit=chartj['PARENT_NETPROFIT']
        try:
            profitgrtht=float(chartj['SJLTZ'])/100
        except:
            profitgrtht = chartj['SJLTZ']
        bps=chartj['BPS']
        try:
            roe=float(chartj['WEIGHTAVG_ROE'])/100
        except:
            roe=chartj['WEIGHTAVG_ROE']
        mgjy=chartj['MGJYXJJE']
        try:
            xsml=float(chartj['XSMLL'])/100
        except:
            xsml=chartj['XSMLL']
        lrfp=chartj['ASSIGNDSCRPT']
        hy=chartj['PUBLISHNAME']
        try:
            gxl=float(chartj['ZXGXL'])/100
        except:
            gxl=chartj['ZXGXL']
        list.loc[k]=[code,abbr,hy,type,market,eps,epsde,income,incomegrtht,profit,profitgrtht,bps,roe,mgjy,xsml,lrfp,gxl]
        k=k+1
     except:
        continue
list.to_excel('list.xlsx',index=False)

  • 27
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要爬取A股上市公司2022年报,需要先找到能够获取这些报告的数据源。一种比较常见的方式是从上交所和深交所的官方网站获取这些报告。 以下是爬取的大致步骤: 1. 确定要爬取的公司列表,可以从上交所和深交所的官方网站获取。 2. 构建爬取链接,链接的格式为:http://www.sse.com.cn/disclosure/listedinfo/announcement/index_1.htm 或 http://disclosure.szse.cn/m/search0425.jsp。 3. 解析页面内容,获取年报的下载链接。 4. 下载年报并保存到本地。 下面是一个简单的示例代码,供参考: ```python import requests from bs4 import BeautifulSoup # 构建爬取链接 sse_url = 'http://www.sse.com.cn/disclosure/listedinfo/announcement/index_1.htm' szse_url = 'http://disclosure.szse.cn/m/search0425.jsp' # 爬取上交所的公司年报 sse_resp = requests.get(sse_url) sse_soup = BeautifulSoup(sse_resp.text, 'html.parser') sse_table = sse_soup.find('div', {'class': 'sse_list_1'}).find_all('li') for row in sse_table: if '年报' in row.text: report_url = row.find('a')['href'] # 下载年报并保存到本地 report_resp = requests.get(report_url) with open('report.pdf', 'wb') as f: f.write(report_resp.content) # 爬取深交所的公司年报 szse_resp = requests.post(szse_url, data={'searchWZ': '年报', 'sort': 'time', 'pageSize': '30', 'pageNum': '1'}) szse_soup = BeautifulSoup(szse_resp.text, 'html.parser') szse_table = szse_soup.find('table', {'class': 'cls-data-table'}).find_all('tr') for row in szse_table: if '年报' in row.text: report_url = 'http://disclosure.szse.cn' + row.find_all('td')[1].find('a')['href'] # 下载年报并保存到本地 report_resp = requests.get(report_url) with open('report.pdf', 'wb') as f: f.write(report_resp.content) ``` 需要注意的是,这只是一个简单的示例代码,实际爬取的时候还需要处理一些细节,比如反爬虫机制、异常处理等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值