郑雯菲的实验报告
目录
Ⅰ.代码及结果展示
预先准备
爬取网页
下载年报
解析年报
绘制图片
Ⅱ.结果分析
Ⅲ.遇到的问题
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import pandas as pd
import re
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
import time
import os
import requests
import fitz
def get_link(txt):
p_txt = '(.*?)'
p = re.compile(p_txt, re.DOTALL)
matchObj = p.search(txt)
attachpath = matchObj.group(1).strip()
href = matchObj.group(2).strip()
title = matchObj.group(3).strip()
return([attachpath, href, title])
data='000153 丰原药业 000403 派林生物 000423 东阿阿胶 000513 丽珠集团 000518 四环生物 000534 万泽股份 000538 云南白药 000566 海南海药 000590 启迪药业 000597 东北制药'
a=data.split(' ')
l1=[]
for i in range(10):
l1.append([a[2*i],a[2*i+1]])
df=pd.DataFrame(l1,columns=['上市公司代码','上市公司简称'])
chrome_driver = r"C:\chrome\chromedriver"
browser = webdriver.Chrome(executable_path=chrome_driver)
browser.get('https://www.szse.cn/disclosure/listed/fixed/index.html')
End = time.strftime('%Y-%m-%d', time.localtime())
START = browser.find_element(By.CLASS_NAME,'input-left')
END = browser.find_element(By.CLASS_NAME,'input-right')
START.send_keys('2013-01-01')
END.send_keys(End + Keys.RETURN)
browser.find_element(By.LINK_TEXT,'请选择公告类别').click()
browser.find_element(By.LINK_TEXT,'年度报告').click()
time.sleep(0.5)
#让点击后可以恢复,消除坐标累计影响
ActionChains(browser).move_by_offset(200, 100).click().perform()
ActionChains(browser).move_by_offset(-200, -100).perform()
for index,row in df.iterrows():
code = row[0]
name = row[1]
Searchbox = browser.find_element(By.ID, 'input_code')
Searchbox.send_keys(code)
time.sleep(0.2)
Searchbox.send_keys(Keys.RETURN)
time.sleep(0.5)
html = browser.find_element(By.ID, 'disclosure-table')
innerHTML = html.get_attribute('innerHTML')
with open(name+'.html','w',encoding='utf-8') as f:
f.write(innerHTML)
browser.find_elements(By.CLASS_NAME,'icon-remove')[-1].click()
结果
i = 0
for index,row in df.iterrows():
i+=1
name = row[1]
with open(name+'.html', encoding='utf-8') as f:
html = f.read()
prefix = 'https://disc.szse.cn/download'
prefix_href = 'https://www.szse.cn/'
# 获得证券的代码和公告时间
p_a = re.compile('(.*?)', re.DOTALL)
p_span = re.compile('(.*?)', re.DOTALL)
get_code = lambda txt: p_a.search(txt).group(1).strip()
get_time = lambda txt: p_span.search(txt).group(1).strip()
p = re.compile('(.*?)
', re.DOTALL)
trs = p.findall(html)
p2 = re.compile('(.*?)', re.DOTALL)
tds = [p2.findall(tr) for tr in trs[1:]]
df1 = pd.DataFrame({'证券代码': [td[0] for td in tds],
'简称': [td[1] for td in tds],
'公告标题': [td[2] for td in tds],
'公告时间': [td[3] for td in tds]})
codes = [get_code(td) for td in df1['证券代码']]
short_names = [get_code(td) for td in df1['简称']]
ahts = [get_link(td) for td in df1['公告标题']]
times = [get_time(td) for td in df1['公告时间']]
df1 = pd.DataFrame({'证券代码': codes,
'简称': short_names,
'公告标题': [aht[2] for aht in ahts],
'attachpath': [prefix + aht[0] for aht in ahts],
'href': [prefix_href + aht[1] for aht in ahts],
'公告时间': times
})
d=[]
for index, row in df1.iterrows():
ggbt = row[2]
a = re.search("摘要|取消|英文", ggbt)
if a != None:
d.append(index)
df11 = df1.drop(d).reset_index(drop = True)
df11.to_csv(name+'.csv',encoding='utf-8-sig')
os.makedirs(name,exist_ok=True)
os.chdir(name)
d1 = {}
for index, row in df11.iterrows():
d1[row[2]] = row[3]
for key, value in d1.items():
f = requests.get(value)
with open (key+".pdf", "wb") as code:
code.write(f.content)
os.chdir('../')
结果
l2=[]#储存公司名称
for i in l1:
l2.append(i[1])
#筛选所需文件,并记下文件路径
l3=[]
for i in range(2013,2023):
l3.append('%s年年度报告.pdf'%(i))
l3.append('%s年年度报告(更新后).pdf'%(i))
#由于归属于上市公司股东的净利润(元)在年报中可能是有两行,且换行符位置没有确定,故创造个列表包含所有的检索项目
l2=['丰原药业', '派林生物', '东阿阿胶', '四环生物', '万泽股份', '云南白药', '海南海药', '启迪药业', '东北制药']#丽珠集团表述不同,之后单独检索
s1='归属于上市公司股东的净利润(元)'
l5=[]
for i in range(1,14):
l5.append('(?<=\n)'+s1[:i]+'\n'+s1[i:]+'\s?\n?\s*([-\d+,.]*)\s?\n?([\d+]*)')
for a in l2:
print(a)
file=os.listdir('./%s'%(a))
l4=[]
for i in file:
if i in l3:
l4.append('./%s/'%(a)+i)
df = pd.read_csv(a+'.csv',converters={'证券代码':str})
df = df.sort_index(ascending=False)
final = pd.DataFrame(index=range(2013,2023),columns=['营业收入(元)','归属于上市公司股东的净利润(元)'])
final.index.name='年份'
code = str(df.iloc[0,1])
name = df.iloc[-1,2]
for i in l4:
doc=fitz.open(i)
text=''
for j in range(15):
page = doc[j]
text += page.get_text()
p_year=re.compile('.*?(\d{4}) .*?年度报告.*?')
year = int(p_year.findall(text)[0])
p_rev = re.compile('(?<=\n)营业总?收入(?\w?)?\s?\n?([\d+,.]*)\s\n?')
p_eps = re.compile('(?<=\n)归属于上市公司股东的净利润(元)\s?\n?\s*([-\d+,.]*)\s?\n?([\d+]*)')
for c in l5:
try:
eps=p_eps.search(text).group(1)
except AttributeError:
p_eps = re.compile(c)
continue
else:
break
p_site = re.compile('(?<=\n)\w*办公地址:?\s?\n?(.*?)\s?(?=\n)',re.DOTALL)
p_web =re.compile('(?<=\n)公司\w*网址:?\s?\n?([a-zA-Z./:]*)\s?(?=\n)',re.DOTALL)
revenue=float(p_rev.search(text).group(1).replace(',',''))
eps=p_eps.search(text).group(1)
if '.' == eps[-1]:#有的公司数据换行了,合并一下
eps=eps+p_eps.search(text).group(2)
final.loc[year,'营业收入(元)']=revenue
final.loc[year,'归属于上市公司股东的净利润(元)']=eps
print(year,eps)
final.to_csv('%s信息.csv' %(a),encoding='utf-8-sig') #将各公司数据存储到本地测csv文件
site=p_site.search(text).group(1)
web=p_web.search(text).group(1)
with open('%s信息.csv'%(a),'a',encoding='utf-8-sig') as f: #把股票简称,代码,办公地址和网址写入文件末尾
content='股票简称,%s\n股票代码,%s\n办公地址,%s\n公司网址,%s'%(name,code,site,web)
f.write(content)
#丽珠集团
s2='归属于本公司股东的净利润'
l6=[]
for i in range(1,14):
l6.append('(?<=\n)'+s2[:i]+'\n'+s2[i:]+'\s?\n\s*([-\d+,.]*)\s?\n?')
l6.append('(?<=\n)归属于本公司股东的净利润\s?\n\s*([-\d+,.]*)\s?\n?')
for a in ['丽珠集团']:
print(a)
file=os.listdir('./%s'%(a))
l4=[]
for i in file:
if i in l3:
l4.append('./%s/'%(a)+i)
df = pd.read_csv(a+'.csv',converters={'证券代码':str})
df = df.sort_index(ascending=False)
final = pd.DataFrame(index=range(2013,2023),columns=['营业收入(元)','归属于上市公司股东的净利润(元)'])
final.index.name='年份'
code = str(df.iloc[0,1])
name = df.iloc[-1,2]
num=2013
for i in l4:
doc=fitz.open(i)
text=''
for j in range(15):
page = doc[j]
text += page.get_text()
p_year=re.compile('.*?(\d{4}) .*?年度报告.*?')
year = int(p_year.findall(text)[0])
p_rev = re.compile('(?<=\n)营业总?收入(?\w?)?\s?\n?([\d+,.]*)\s\n?')
p_eps = re.compile('(?<=\n)归属于上市公司股东的净利润(元)\s?\n?\s*([-\d+,.]*)\s?\n?')
for c in l6:
try:
eps=p_eps.search(text).group(1)
except AttributeError:
p_eps = re.compile(c)
continue
else:
break
p_site = re.compile('(?<=\n)\w*办公地址:?\s?\n?(.*?)\s?(?=\n)',re.DOTALL)
p_web =re.compile('(?<=\n)公司\w*网址:?\s?\n?([a-zA-Z./:]*)\s?(?=\n)',re.DOTALL)
revenue=float(p_rev.search(text).group(1).replace(',',''))
eps=p_eps.search(text).group(1)
if year >2015:#从2016年开始,丽珠集团单位为人民币千元,为了统一,这里进行转换
eps=float(eps.replace(',',''))*1000
revenue*=1000
final.loc[year,'营业收入(元)']=revenue
final.loc[year,'归属于上市公司股东的净利润(元)']=eps
print(year,eps)
final.to_csv('%s信息.csv' %(a),encoding='utf-8-sig')
site=p_site.search(text).group(1)
web=p_web.search(text).group(1)
with open('%s信息.csv'%(a),'a',encoding='utf-8-sig') as f:
content='股票简称,%s\n股票代码,%s\n办公地址,%s\n公司网址,%s'%(name,code,site,web)
f.write(content)
结果
l2=[]#储存公司名称
for i in l1:
l2.append(i[1])
l7=[]#合并文件信息
for i in l2:
data=pd.read_csv(i+'信息.csv')
l7.append(data)
for i in range(len(l7)):
l7[i]=l7[i].set_index('年份')
ly=[]#营业收入
lg=[]#归属于上市公司股东的净利润
for i in range(10):
ly.append(pd.DataFrame(l7[i].iloc[:11,0]))
lg.append(pd.DataFrame(l7[i].iloc[:11,1]))
fname = "C:\Windows\Fonts\SIMLI.TTF"
zhfont1 = fm.FontProperties(fname=fname)
plt.rcParams['figure.dpi'] = 300
plt.figure(figsize=(5,10))
x = np.arange(2013,2023)
yl=[]
ynl=[]
for k in range(10):
yt=[]
a=ly[k].index
y=ly[k]['2013':'2022'].iloc[:,0]
for i in y:
t=float(i)/1000000000
yt.append(t)
y=np.array(yt)
yn=ly[k]['股票简称':'股票简称'].iloc[:,0]
yl.append(y)
ynl.append(yn[0])
plt.xlim(2012,2023,1)
plt.xticks(range(2013,2023),fontsize=8)
plt.plot(x, yl[0], color='#1E90FF', marker='^',markersize=10, linestyle='-', label=ynl[0],linewidth = 2.5,alpha=0.8)
plt.plot(x, yl[1], color='#2E8B57', marker='^', markersize=10,linestyle='-', label=ynl[1],linewidth = 2.5,alpha=0.8)
plt.plot(x, yl[2], color='#FF8C00', marker='^', markersize=10,linestyle='-', label=ynl[2],linewidth = 2.5,alpha=0.8)
plt.plot(x, yl[3], color='#4682B4', marker=9, markersize=9,linestyle='-', label=ynl[3],linewidth = 2,alpha=0.8)
plt.plot(x, yl[4], color='#FF6A6A', marker=9,markersize=9, linestyle='-', label=ynl[4],linewidth = 2,alpha=0.8)
plt.plot(x, yl[5], color='#9BCD9B', marker=9, markersize=9,linestyle='-', label=ynl[5],linewidth =2,alpha=0.8)
plt.plot(x, yl[6], color='#6495ED', marker='D', markersize=7,linestyle='-', label=ynl[6],linewidth =1.5,alpha=0.8)
plt.plot(x, yl[7], color='#FFB90F', marker='s', markersize=7,linestyle='-', label=ynl[7],linewidth =1.5,alpha=0.8)
plt.plot(x, yl[8], color='#8B3A3A', marker='D',markersize=7, linestyle='-', label=ynl[8],linewidth =1.5,alpha=0.8)
plt.plot(x, yl[9], color='#00CED1', marker='s', markersize=7,linestyle='-', label=ynl[9],linewidth =1.5,alpha=0.8)
plt.legend(loc = "upper left",prop={'family':'simsun'})
plt.grid(True)
title="营业收入随时间变化趋势图"
plt.title(title, fontproperties=zhfont1,fontsize=18)
plt.ylabel("营业收入(十亿元)", fontproperties=zhfont1,fontsize=14) # 设置Y轴标签
plt.xlabel("年份",loc='left', fontproperties=zhfont1,fontsize=14) # 设置X轴标签
plt.savefig("营业收入随时间变化趋势图")
fname = "C:\Windows\Fonts\SIMLI.TTF"
zhfont1 = fm.FontProperties(fname=fname)
plt.rcParams['figure.dpi'] = 300
plt.figure(figsize=(5,10))
x = np.arange(2013,2023)
yl=[]
ynl=[]
for k in range(10):
yt=[]
a=lg[k].index
y=lg[k]['2013':'2022'].iloc[:,0]
for i in y:
t=float(i.replace(',',''))/1000000000
yt.append(t)
y=np.array(yt)
yn=ly[k]['股票简称':'股票简称'].iloc[:,0]
yl.append(y)
ynl.append(yn[0])
plt.xlim(2012,2023,1)
plt.xticks(range(2013,2023),fontsize=8)
plt.plot(x, yl[0], color='#1E90FF', marker='^',markersize=10, linestyle='-', label=ynl[0],linewidth = 2.5,alpha=0.8)
plt.plot(x, yl[1], color='#2E8B57', marker='^', markersize=10,linestyle='-', label=ynl[1],linewidth = 2.5,alpha=0.8)
plt.plot(x, yl[2], color='#FF8C00', marker='^', markersize=10,linestyle='-', label=ynl[2],linewidth = 2.5,alpha=0.8)
plt.plot(x, yl[3], color='#4682B4', marker=9, markersize=9,linestyle='-', label=ynl[3],linewidth = 2,alpha=0.8)
plt.plot(x, yl[4], color='#FF6A6A', marker=9,markersize=9, linestyle='-', label=ynl[4],linewidth = 2,alpha=0.8)
plt.plot(x, yl[5], color='#9BCD9B', marker=9, markersize=9,linestyle='-', label=ynl[5],linewidth =2,alpha=0.8)
plt.plot(x, yl[6], color='#6495ED', marker='D', markersize=7,linestyle='-', label=ynl[6],linewidth =1.5,alpha=0.8)
plt.plot(x, yl[7], color='#FFB90F', marker='s', markersize=7,linestyle='-', label=ynl[7],linewidth =1.5,alpha=0.8)
plt.plot(x, yl[8], color='#8B3A3A', marker='D',markersize=7, linestyle='-', label=ynl[8],linewidth =1.5,alpha=0.8)
plt.plot(x, yl[9], color='#00CED1', marker='s', markersize=7,linestyle='-', label=ynl[9],linewidth =1.5,alpha=0.8)
plt.legend(loc = "upper left",prop={'family':'simsun'})
plt.grid(True)
title="归属于上市公司股东的净利润随时间变化趋势图"
plt.title(title, fontproperties=zhfont1,fontsize=16)
plt.ylabel("归属于上市公司股东的净利润(十亿元)", fontproperties=zhfont1,fontsize=14) # 设置Y轴标签
plt.xlabel("年份",loc='left', fontproperties=zhfont1,fontsize=14) # 设置X轴标签
plt.savefig('归属于上市公司股东的净利润随时间变化趋势图')
结果
营业收入分析
可以看到十家企业中营业收入最高的是云南白药,其营业收入每一年都远高于其他企业,而且涨幅很大,营业收入逐年增长。东北制药、丽珠集团的营业收入也是在逐年增长,涨幅较大。东阿阿胶的营业收入在2013~2017整体向上涨,2018~2019大幅度下跌。通过网上检索,东阿阿胶至2006年起不断提价,经销商们发现,东阿阿胶已经不仅仅是一种用于销售的商品,还是一种有一定金融属性的商品,所以许多人开始囤东阿阿胶,逐渐地东阿阿胶更像是成为了一种金融产品。东阿阿胶在市场上的营业收入不断增加,这也导致了大批厂商涌入阿胶市场。随着各种低价阿胶涌入市场,19年经销商开始认清形式,大幅度抛售囤积的存货,东阿阿胶的销售渠道全线溃败,这有就导致了东阿阿胶在2019年营业收入的大幅度下跌。除了以上几家企业,其余企业的营业收入变化较为平稳,不再赘述。
归属于上市公司股东的净利润分析
整体归属于上市公司股东的净利润排行前三的是云南白药、丽珠集团和东阿阿胶。这三家企业的归属于上市公司股东的净利润都是不断上涨,直至某一年大幅度下跌,后期继续上涨。海南海药2013~2018年归属于上市公司股东的净利润变化较为平稳,2018~2021年该数据不断下跌,2022年再次上涨回原来的高度。其余企业2013~2022年,十年以来变化都较为平稳。
归属于上市公司股东的净利润在年报中经常是有两行,而且换行符的位置不确定,这里尝试了用try跳过报错,使得最后可以找到需要的格式