如何批量获取年报中数据?

最近老师布置任务要获得四百家公司年报中管理费用明细中的业务招待费和其他费用这两项数据,有没有用r或者python可以实现的方法编程批量获取啊T_T
关注者
298
被浏览
184,675

10 个回答

其实上市公司的年报都是免费的,也有很多网站进行了整理,尤其是对于报表,可以批量获取。

一、完整版年报获取方式

通常上市公司会在每年的4月份左右发布上年年报,在该公司的网站上会有下载链接,这是最权威的年报获取手段。

比如安琪酵母:


打开其官方网站,能够看到“投资者关系”一栏,里面就是放的各种公告,包括历年财报。




这里其实是一个PDF的下载链接,使用下载工具下载即可。


如果大量分析年报的话,这样的下载方式略显繁琐。

绝大多数证券网站都做了搜集整理,可以方便的查找下载,比如新浪股票、网易财经、腾讯证券。

我习惯使用腾讯证券,地址在此:gu.qq.com/sh600291/gp/j

敲入股票代码或者简写,就可以下载PDF格式的年报。

二、数字版报表下载方式

通过上文的方式下载的年报,动辄一二百页,对于深度分析某个公司基本面是有帮助的,但很多时候我们只是想了解一下连续几年来的某个项目变动情况,F10里不全,PDF一个个看起来会累瞎眼,那怎么办呢?

有两种方式,一种是高昂的国泰安数据库、Wind客户端等专业软件,内置了年报资料,另一种是一些免费的网站,提供了Excel格式的下载链接。

比如网易财经。

quotes.money.163.com/se600001.html (股票代码为600001的资产负债表)

http://quotes.money.163.com/service/lrb_600001.html (股票代码为600001的利润表)

http://quotes.money.163.com/service/xjllb_600001.html (股票代码为600001的现金流量表)

下载的都是格式为csv的Excel表格,为该公司上市以来所有报表。替换掉代码即可下载你想要的公司的报表。


报表格式如下:


可见利用这些数据进行历年分析是非常简单的。

三、一点点编程代码,批量下载和处理

对于财经数据分析,Python提供了非常友好的处理模式,不过因为我当时在学Ruby,就写了一段Ruby代码下载。

作为初学者,很多代码优化学得不好,在编程高手们面前,这段代码有点献丑了。不过幸亏我脸皮厚,既然许多朋友咨询,我就恬不知耻的放上来了。


# -*- coding: UTF-8 -*-
require 'rubygems'
require 'hpricot'
require 'open-uri'
################################本程序实现财务指定股票上市以来全部财务报表的下载
x = 0

#获取股票列表文件stocklist.txt的总行数
def wc(filename)
$nline = $nword = $nchar = 0 #$符号表示全局变量,普通变量不在def外起作用
File.open(filename) do |io|
io.each_line do |line|
words = line.split(/\s+/).reject{|w| w.empty? }
#本例中使用了split方法分割单词,当行首有空白字符时,split方法的执行结果中会产生空白字符串,因此我们
#会删除该空白字符串。
$nline += 1
$nword += words.length
$nchar += line.length
end
end
#puts "文件的行数为:#{$nline}\n文件的单词数为:#{$nword}\n文件的字符数为:#{$nchar}"
puts "股票池股票数:#{$nword}\n"

end
wc("d:/rb/stock/downreports/stocklist.txt")
#puts $nword

#循环开始

while x <= $nword - 1

#puts "轮询中:"

stock_lines = File.readlines("d:/rb/stock/downreports/stocklist.txt");


s_code = stock_lines[x]
scode = s_code.chomp # chomp用来删除文本里带过来的换行符


puts "====================="
puts "正在下载#{scode}的资产负债表,共计#{$nword}只,当前第#{x}只。"

#确定csv文件命名规则
file1_path = "d:\\stock\\zcfzb\\"
file1_name = scode + "zcfzb.csv"
file1_name_path = file1_path + file1_name

#将网易财经接口的数据保存为csv文件
File.open(file1_name_path, 'wb') {|f| f.write(open('quotes.money.163.com/se' + "#{scode}"+'.html') {|f1| f1.read})}

#防止接口调用过频被踢,暂停3秒
sleep(3)

puts "资产负债表下载完毕"

puts "====================="
puts "正在下载#{scode}的利润表"

#确定csv文件命名规则
file2_path = "d:\\stock\\lrb\\"
file2_name = scode + "lrb.csv"
file2_name_path = file2_path + file2_name

#将网易财经接口的数据保存为csv文件
File.open(file2_name_path, 'wb') {|f| f.write(open('quotes.money.163.com/se' + "#{scode}"+'.html') {|f1| f1.read})}

#防止接口调用过频被踢,暂停3秒
sleep(3)

puts "利润表下载完毕"

puts "====================="
puts "正在下载#{scode}的现金流量表"

#确定csv文件命名规则
file3_path = "d:\\stock\\xjllb\\"
file3_name = scode + "xjllb.csv"
file3_name_path = file3_path + file3_name

#将网易财经接口的数据保存为csv文件
File.open(file3_name_path, 'wb') {|f| f.write(open('quotes.money.163.com/se' + "#{scode}"+'.html') {|f1| f1.read})}

#防止接口调用过频被踢,暂停3秒
sleep(3)


puts "现金流量表下载完毕"

puts "====================="
puts "正在下载#{scode}的主要财务指标表"

#确定csv文件命名规则
file4_path = "d:\\stock\\zycwzb\\"
file4_name = scode + "zycwzb.csv"
file4_name_path = file4_path + file4_name

#将网易财经接口的数据保存为csv文件
File.open(file4_name_path, 'wb') {|f| f.write(open('quotes.money.163.com/se' + "#{scode}"+'.html') {|f1| f1.read})}

#防止接口调用过频被踢,暂停3秒
sleep(3)

puts "主要财务指标表下载完毕"
x = x + 1
end

本段代码的核心就是这一行了:

f.write(open('quotes.money.163.com/se' + "#{scode}"+'.html') {|f1| f1.read})}

学过一丁点代码的,应该一看就明白了。此处虽然用的Ruby,你换Python也很容易。

下载完毕后,还是很壮观的:


有了这些基础数据,你就可以随意分析任意上市公司的历年财报了。

和国泰安数据库、Wind数据相比,起码省了几万块,还不赶快去加个鸡腿?

题主问题不清晰,简单的回答一下思路,最关键的点在于:程序只能按照你的思路做机械的批量化的操作,如果整个过程中有只有人能够识别操作的行为(比如年报地址分散得找,年报格式不统一得去识别等),那你就只能手工去做了。如果其中有重复的模式,那可以考虑编程解决。

  1. 年报已经有了文件,还是得去找?
  • 如果没有,得去下载的话,有没有有规律的可以机械化处理的方式(比如某个网站你提供名称就能下载到)?没有的话请放弃。
  • 年报格式是否统一?比如你要的格式是否以固定的格式出现在某个位置?
  • 去编程提取信息的操作难度和手工去找的工作量对比如何?该程序的可复用性如何?如果这个功能就用这一次,而且编出来比手动操作还麻烦,那当然不用费这个心了。
  • 如果你能够描述出来怎样用固定的步骤解决这个问题,那你可以考虑找个懂编程的人来解决。如果自己都说不清怎么操作,那就别浪费时间了,自己慢慢干吧。