百摩网
当前位置: 首页 生活百科

python抓取财务数据(Python抓取上市公司财务数据)

时间:2023-08-03 作者: 小编 阅读量: 5 栏目名: 生活百科

Python抓取上市公司财务数据本文开始正式介绍python抓取的代码编写,我将由浅入深地来介绍上市公司财务数据的抓取实现上市公司列表的抓取相对会简单一些,本文会先对上市公司财务数据的相关页面进行分析,然后再详细讲解上市公司列表的抓。

本文开始正式介绍python抓取的代码编写,我将由浅入深地来介绍上市公司财务数据的抓取实现。上市公司列表的抓取相对会简单一些,本文会先对上市公司财务数据的相关页面进行分析,然后再详细讲解上市公司列表的抓取实现,若想直接看列表抓取的,可以直接跳到“第一点”的“第六步”开始阅读。对于有上市公司财务数据抓取需求的朋友,或者刚入门学习python抓取的同学均能提供参考价值。

先回顾一下本主题“Python抓取上市公司财务数据”的内容体系,分成9节来为‬大家讲解,从0到1来详细拆解程序开发流程和编码实现,这套体系内容适合给Python零基础的小白学者学习,同时也对熟悉python但对数据采集不熟练的量化专家提供一套Python抓取的最佳实践。其包含的主要章节如下:

1. Centos7搭建代码库和Python运行环境

2. Win10搭建Python开发环境

3. Python爬虫应用运行(Docker)镜像准备

4. 编码实现上市公司列表抓取

5. 编码实现上市公司简介和行业板块抓取

6. 编码实现上市公司企业财务摘要抓取

7. 编码实现上市公司历年财务数据抓取

8. 编码实现上市公司财务数据抓取结果入库(Mysql)

9. Python代码提交及部署运行

本文讲解的是其中的第4章节,主要包括:

1)上市公司财务数据页面的定位分析;

2)上市公司列表页的网络数据结构分析

3)编写列表抓取程序

4)列表抓取程序的运行

一、上市公司财务数据页面的定位分析

第一步:上市公司数据页面定位

打开新浪财经网站https://finance.sina.com.cn/,并在搜索框中搜索我们需要抓取的公司代码,以新华医疗(600587)为例,如下图:

点击自动提示的搜索结果,我们就能进入对应上市公司的行情详情页https://finance.sina.com.cn/realstock/company/sh600587/nc.shtml,该页面左侧模块我们就能找到我们需要的数据页面链接,如下图:

第二步:公司简介页面结构分析

打开公司简介页,地址如下:

http://vip.stock.finance.sina.com.cn/corp/go.php/vCI_CorpInfo/stockid/600587.phtml

通过url格式我们可以发现可以改变股票代码就能定位到不同上市公司的简介页,因此通配url如下(%s代表股票代码的字符串占位):

http://vip.stock.finance.sina.com.cn/corp/go.php/vCI_CorpInfo/stockid/%s.phtml

另外,我们可以看到公司简介信息以单表格的形式展现,如下:

该表格的格式分为两列和四列两种,后续可根据奇偶列进行数据键值对关联处理。

第三步:所属行业页面结构分析

打开公司的所属行业页面,url地址如下:

https://vip.stock.finance.sina.com.cn/corp/go.php/vCI_CorpOtherInfo/stockid/600587/menu_num/2.phtml

通过url格式我们可以发现可以改变股票代码就能定位到不同上市公司的所属行业页面,因此通配url如下(%s代表股票代码的字符串占位):

https://vip.stock.finance.sina.com.cn/corp/go.php/vCI_CorpOtherInfo/stockid/%s/menu_num/2.phtml

我们可以看到公司的行业数据为表格中的一个字段值,如下:

该数据的提取可以直接指定xpath路径提取文本即可。

第四步:财务摘要页面结构分析

打开公司财务摘要页面,地址如下:

http://vip.stock.finance.sina.com.cn/corp/go.php/vFD_FinanceSummary/stockid/600587/displaytype/4.phtml

通过url格式我们可以发现可以改变股票代码就能定位到不同上市公司的财务摘要页面,因此通配url如下(%s代表股票代码的字符串占位):

http://vip.stock.finance.sina.com.cn/corp/go.php/vFD_FinanceSummary/stockid/%s/displaytype/4.phtml

另外,我们可以看到公司财务摘要数据以多表格的形式展现,如下:

该表格为固定两列,首行字体加粗代表日期,数据值存在有的带链接,有的不带。后续可直接提取两列的文本分别作为数据键和值,直接关联即可。

第五步:各类财务指标的历年数据结构分析

打开公司财务指标、资产负债表、利润表、现金流量表页面,地址分别如下:

http://vip.stock.finance.sina.com.cn/corp/go.php/vFD_FinancialGuideLine/stockid/600587/displaytype/4.phtml

http://vip.stock.finance.sina.com.cn/corp/go.php/vFD_BalanceSheet/stockid/600587/ctrl/part/displaytype/4.phtml

http://vip.stock.finance.sina.com.cn/corp/go.php/vFD_ProfitStatement/stockid/600587/ctrl/part/displaytype/4.phtml

http://vip.stock.finance.sina.com.cn/corp/go.php/vFD_CashFlow/stockid/600587/ctrl/part/displaytype/4.phtml

由于我们需要获取历年数据,我们需要进一步分析指标数据页面结构。从页面结构上来看,历年数据都在页面中有链接,如下图:

我们点击2021年的数据打开对应2021年的财务指标数据页,其URL分别如下:

https://money.finance.sina.com.cn/corp/go.php/vFD_FinancialGuideLine/stockid/600587/ctrl/2021/displaytype/4.phtml

http://money.finance.sina.com.cn/corp/go.php/vFD_BalanceSheet/stockid/600587/ctrl/2021/displaytype/4.phtml

http://money.finance.sina.com.cn/corp/go.php/vFD_ProfitStatement/stockid/600587/ctrl/2021/displaytype/4.phtml

http://money.finance.sina.com.cn/corp/go.php/vFD_CashFlow/stockid/600587/ctrl/2021/displaytype/4.phtml

通过url格式我们可以发现可以改变股票代码和年份就能定位到不同上市公司的对应年份的财务指标数据页面,因此通配url如下(%s代表股票代码字符串占位,%d代表对应年份的数值占位):

https://money.finance.sina.com.cn/corp/go.php/vFD_FinancialGuideLine/stockid/%s/ctrl/%d/displaytype/4.phtml

http://money.finance.sina.com.cn/corp/go.php/vFD_BalanceSheet/stockid/%s/ctrl/%d/displaytype/4.phtml

http://money.finance.sina.com.cn/corp/go.php/vFD_ProfitStatement/stockid/%s/ctrl/%d/displaytype/4.phtml

http://money.finance.sina.com.cn/corp/go.php/vFD_CashFlow/stockid/%s/ctrl/%d/displaytype/4.phtml

另外,我们看到各类财务指标数据均以多列表格的形式展现,如下图:

并且表格均以报告日期为第一行,第一列均为数据指标名称,后续列则都为指标的值。另外,大部分指标数据都有一二级标题名称,也存在有的指标只有一级标题名称,如下图:

后续可通过多级字典的格式来存储数据,第1级为日期、第2级为一级标题、第3级为二级标题(若有),最后的那一级为指标的值。

待抓取的上市公司财务数据分析完毕后。我们开始分析上市公司的列表数据。

第六步:定位上市公司列表

通过查找新浪财经网站,我们可以找到行情中心页面有根据行业分类来查询不同分类下的上市公司列表,如下图:

我们可以选择沪市A股、深市A股、北交所三个主要市场的上市企业列表,打开其中一个列表(沪市A股)页面,列表为分页展示,如下图:

二、上市公司列表页的网络数据结构分析

第一步:打开页面的浏览器检查工具

我们通过右键-点击“检查”(或快捷键F12),如下图:

第二步:筛选XHR类型的网络请求列表

切换到“网络”TAB的“XHR”项,如下图:

第三步:监测翻页操作的新增网络请求

我们点击下一页,并观察网络列表的新增请求,如下图:

我们查看请求详情,发现是通过GET方法请求的分页数据,如下图:

第四步:分析列表请求的url地址

列表的请求的url为:

https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page=2&num=40&sort=symbol&asc=1&node=sh_a&symbol=&_s_r_a=page

我们可以通过多次翻页查看请求得出,该url的page参数为页码。并通过查看其他分类的请求可知,node参数为分类标识,其中沪市A股为sh_a,深市A故为sz_a,北交所为hs_bjs。

第五步:分析列表请求的响应数据

从其响应的数据我们知道响应数据的格式为json数组,将json数据格式化后,我们能看出code为股票代码,name为股票名称(经过了unioncode编码),如下图所示:

三、编写列表抓取程序

第一步:打开scrapy_list.py模块文件

在项目scrapy-finance文件夹中,选择scrapy_list文件并选择右键-Edit with IDLE-Edit with IDLE 3.0(64-bit),如下图:

点击打开后,就可以开始编写代码,如下图:

第二步:编写页面抓取方法

根据列表页的url参数,创建抓取方法scrapy_page,参数包括页码、分类标识,并实现页面请求和解析逻辑,代码如下:

from urllib import requestimport sslimport jsonssl._create_default_https_context = ssl._create_unverified_contextdef scrapy_page(self, page_no, market_sign):list_url = "https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page=%d&num=40&sort=symbol&asc=1&node=%s&symbol=&_s_r_a=page"resp = request.urlopen(list_url%(page_no, market_sign))print ("request url:"resp.geturl())rt_code = resp.getcode()if rt_code==200:data_json = json.loads(resp.read().decode())return [{'code': one.get('code'), 'name': one.get('name')} for one in data_json]else:print ("error return code:" rt_code)return []

以上代码说明如下:

1. from urllib import request为从urllib模块中加载request子模块,http请求我们使用request模块的urlopen方法;

2. import ssl和ssl._create_default_https_context = ssl._create_unverified_context是在https安全请求时,设置为做不认证的模式。不做此设置会导致https类型的请求会失败。

3. list_url%(page_no, market_sign)中的%是python中对字符串进行格式化的方式,可拼接一个或多个(多个需用括号括起来)变量,变量将替换掉字符串中的对应占位符,占位符类型包括以下几种:

(1)%d为整数占位,将整型和浮点型转为整型后填充;

(2)%f为浮点数占位,将整型和浮点型转为浮点型后填充,默认保留6位小数;

(3)%s为字符串占位,转化为对象的字符串表述(或者说取对象的__str__方法返回值)后填充;

(4)%x为十六进制占位,将十进制数转化为十六进制后填充;

(5)%o为八进制占位,将十进制数转化为八进制后填充;

4. request.urlopen()方法实现了请求URL地址,其参数可只传URL,也可指定参数的方式来调用,可传的参数有method=请求方法,url=请求URL,body=请求体数据,headers=请求头数据,请求结果将以http.client.HTTPResponse对象的形式返回

5. HTTPResponse类提供了geturl()获取请求的URL、getcode()获取响应码、read()读取响应的内容,getheaders()获取响应头等方法,用来获取响应的相关数据。

格式上需要注意以下两点:

1. import引入依赖和ssl全局设置的代码放在模块代码的顶部;

2. scrapy_page函数的实现放在ScrapyList类中,并注意统一增加一级缩进;

如下图:

第三步:编写调用测试列表请求

在ScrapyList类的run方法中增加scrapy_page的调用以测试列表页的请求和解析,代码如下:

res_list = self.scrapy_page(1, 'sh_a')print ('res len=%d first=%s'%(len(res_list), str(res_list[0])))

如下图:

第四步:保存并运行列表抓取模块

使用Ctrl S快捷键保存后,Ctrl F5运行模块,如下图所示:

至此我们成功抓取到了一页上市企业数据,一页40条,并成功解析出了股票代码和股票名称。

第五步:编写循环抓取上市公司列表

基于刚刚的测试代码,我们增加while循环来实现循环抓取,并且在结果数量不足40条时结束循环。并且在抓取结束后等待1秒钟再继续抓下一页,避免请求太频繁而被限制请求。最后在请求异常时,进行异常捕获,避免因为某次报错而中断抓取循环,同时在出错时等待3秒钟后再重试请求。循环抓取的结果将存储在code_list数组中。代码如下:

code_list = []# sh_a market market_sign = "sh_a"page_no = 1while True:try:res_list = self.scrapy_page(page_no, market_sign)code_list.extend(res_list)if len(res_list) < 40:breakpage_no= 1time.sleep(1)except HTTPError as err:print ('Http Error:', err)time.sleep(3)

另外,模块顶部代码还需:

1. 增加from time来导入时间模块以支持sleep方法;

2. 增加from urllib.error import HTTPError来导入HTTPError类。

如下图:

第六步:编写将列表数据存储到文件

编写存储列表数据到文件的函数save_list_to_file,参数包含list_file(存储文件的路径)、res_list(待存储的json列表),代码如下:

# result write to filedef save_list_to_file(self, list_file, res_list):try:fb = open(list_file, 'w')for item in res_list:fb.write(json.dumps(item) '\n')except IOError as err:print ('IO Error:', err)else:fb.close()

其中:

1. open()方法为读写文件的方法,第二个参数为文件操作模式,可以用w覆盖写入、r读取、a追加,方法的返回值为文件句柄。

2. json.dumps方法为将json对象导出成字符串,以便将字符串存储到文件中。写入的json字符串后缀增加'\n'换行字符,代表一个json存储为一行。

3. 最后我们捕获到IOError异常则打印出来,若正常处理则最后调用close()方法来关闭文件句柄。

我们将save_list_to_file方法的实现放在ScrapyList类中,并在run()方法中调用,并且将存储路径在__init__方法中初始化,如下图所示:

至此,列表抓取代码编写完成,我们可以将#todo注释去掉。

四、列表抓取程序的运行

第一步:创建list_data结果存储文件夹

命名为list_data,回车保存,如下图:

第二步:本地运行scrapy_list.py模块

由于上市公司列表的抓取请求量并不大,我们可以直接运行测试一下列表抓取模块,如下图:

第三步:查看本地列表抓取结果

可以发现总共抓取了53页上市公司列表。我们查看抓取结果文件夹list_data,可知抓取结果成功写入到了code_list.data文件夹。如下图:

第四步:编写增加多个分类的列表抓取

我们复制sz_a的循环抓取代码,修改market_sign变量的初始化值分别为'sz_a'、'hs_bjs',如下图所示:

使用Ctrl S保存文件,至此上市公司的分类列表抓取代码编写完成。

五、结语

本节主要讲解了上市公司数据的页面结构以及上市公司列表数据的页面网络解析和python抓取代码,并在本地运行了单个分类的测试列表抓取,成功抓到到了53页列表数据。最后,我们按照循环的逻辑实现了沪市A股、深市A股以及北交所三个分类的上市公司列表抓取,为后面的公司详情及历年财务数据抓取做好了基础数据的准备。

下一节将介绍“上市公司简介和行业板块的抓取”,将会对python抓取技术做进一步的实操学习,希望通过详细的步骤讲解及逐层深入的分析,能让小白用户也能轻松拿起python来实现自己的抓取程序。并最终能独立完成整个财务数据的抓取,为后续的量化分析提供充足的数据基础。感兴趣的可以关注下我的后续动态,有任何疑问或建议欢迎在评论区留言。

    推荐阅读
  • 什么才是真正的有文化(我们真弄明白了吗)

    任何伪造的文物,都不享有真品特有的历史文化价值。一个文化遗址存留物精致丰富程度,是对当时社群的文明程度高低最好的体现。当下之文化,也必应立足于当代社会而论之,必须要体现较高层次精神创造。但是,无论任何阶层的人进行文化创造,都必须为所属时代高层次的精神创造与升华,都必须应是对整个文明进程具有积极的推动意义。那种粗俗、低劣的东西,绝不应代表今日社会之文化。

  • 关于健康的小短片(包你会笑出声的16秒小)

    [呲牙]我是爱唱歌爱生活的三月春风姐姐,不久前才在今日头条大平台自由创作,除了传播正能量,还希望给路过的你带来开心和快乐![呲牙][给力]虎皮鹦鹉原产于澳大利亚内陆地区,智商相当于三到四岁的孩子,性情活泼可爱,叫声如唱歌一样特别好听,容易训养,讨人喜欢!虎皮鹦鹉是群居性的鸟类,如果养一只,那太寂寞了,会患上抑郁症,容易有自残行为,因此至少养一对比较好,就像人类一样,害怕孤独,希望长久有伴。

  • 国庆青龙古镇要门票吗(青龙古镇景区临时门票价格确定)

    国庆青龙古镇要门票吗本报讯 12月24日,市发改委公布青龙古镇景区临时门票价格及有关事项。青龙古镇景区临时门票实行最高限价管理,价格为30元/人·次。景区可根据季节和市场供求状况,自主制定下浮价格,下浮幅度不限。上述临时门票价格自2022年1月1日起执行,试行期14个月。

  • 为创造人类美好未来不懈努力(携手开创人类更加美好的未来)

    党的二十大代表们表示,中国共产党是为中国人民谋幸福的政党,也是为人类进步事业而奋斗的政党。党的十八大以来,在以同志为核心的党中央坚强领导下,中国坚定不移做世界和平的建设者、全球发展的贡献者、国际秩序的维护者,为促进人类和平与发展作出了重大贡献。共同抗疫情,患难见真情。中国人民愿同世界人民携手开创人类更加美好的未来。

  • 福州未来路停车场收费标准(福州站停车场收费标准)

    目前,福州火车站施工专用电台、抽水泵、防水沙袋等防汛物资已准备到位;15名党员应急抢险队、10名保洁应急人员已全部准备就位,休班职工在家24小时开机待命,随时对因强降雨导致而可能发生的列车停运、晚点等突发情况做出应急处置。要知道,雨天将会严重的加剧了城市交通拥堵,福州车站因堵车而耽误乘坐火车的情况常有发生。

  • 仙气十足的吃鸡名字(温柔的好听的吃鸡名字)

    泽畔东篱空叹花语意,我来为大家科普一下关于仙气十足的吃鸡名字?以下内容希望对你有帮助!仙气十足的吃鸡名字泽畔东篱空叹花语意浅嫣婉语风落尘归去凡尘红梦惜醉颜忆挽离笙歌i无梦相赠空景孤扰人心竹笙锦瑟流年乱了沉浮无梦相赠抹茶夏天笑弄清风

  • 老虎上树咬死豹子(徒手打死一只豹子的商县老太太活了83岁)

    徒手打死一只豹子的商县老太太活了83岁稀罕】1982年,67岁的商县老太打死一只豹子1982年,67岁的商县老太打死一只豹子文/杨恩绪(陕西商州)1982年6月16日,齐德英老太太讲述打死凶豹的过程那时候,我在商县县委任宣传部长在一次县委。

  • 梦见地基(梦见地基准备盖房子)

    3、女人梦见地基,预示近期的感情运势不错,如果是单身女性,将会拥有一位温柔又有能力的好伴侣,已婚的女人将会得到爱人和家人的更多疼爱。

  • 脚踏两只船的男人以后会幸福么(男人脚踏两条船)

    因为在她怀孕没多长时间,她居然发现小陈还有着其他女人,并且也怀孕三个月了,甚至比她的第2个孩子还要更早。其实她腹中的孩子可以打掉不要,但是之前已经有过一个孩子需要养活,这也依然需要一笔钱,因此这笔抚养费她认为应该由小陈承担。对于这一点,两人经过多方争吵说法,也最终无法说服对方,经过他人的调解劝解下,最终决定,小陈必须得对于之前生出来的孩子负责,给予焦女士每个月适当的抚养费。

  • 4月19日沙门镇卫生院第六期九价HPV疫苗摇号

    四、中签的用户需在提示的预约截止日期前登陆浙里办APP预约到院接种时间,逾期未预约的用户,将视为自动放弃,并在6个月内不能参加中签疫苗的活动申请。