郑雯菲的实验报告

目录

.代码及结果展示

    预先准备 爬取网页 下载年报 解析年报 绘制图片

.结果分析

.遇到的问题



Ⅰ.代码及结果展示(回到目录)


预先准备(回到目录)


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跳过报错,使得最后可以找到需要的格式