傅元娴的综合实验

Ⅰ.根据学生姓名自动挑选出所分配行业于的公司

导入本部分所需模块


  import pdfplumber
  import pandas as pd
  import re

  import os
  os.chdir("./Final Project")

代码

  

    #把PDF解析成列表
    def Pdf_extract_table(filename):
        pdf = pdfplumber.open(filename)
        page_count = len(pdf.pages)
        data = []
        for i in range(page_count):
            data += pdf.pages[i].extract_table()
        pdf.close()
        return data

    #将上述列表转化成完整的数据框
    def Get_alllist(data):
        # sz = ['200', '300', '301', '00', '080']  # 深市股票代码A股是以000开头;深市B股代码是以200开头;中小板股票以002开头;
        # # 深市创业板的股票是以300、301开头(比如第一只创业板股票特锐德)。
        # # 另外新股申购代码以00开头、配股代码以080开头。
        # data2 = [x for x in data for string in sz if x[3].startswith(string) == True]
        df = pd.DataFrame(data, columns=data[0]).iloc[:, 1:] #去掉第一列
        df = df.ffill() #将所属行业类型向后填充
        return df

    #从用户端获取姓名
    def InputStu():
        Names = str(input('请输入姓名:'))
        return Names

    #打开行业分配表,根据获取的姓名自动匹配行业
    #def Match(Names):
        #industrylist = pd.read_csv('001班行业安排表.csv', converters={'行业': str})[['行业', '完成人']]
        #Industry = industrylist[(industrylist[2]==Names)].index.tolist()
        #return Industry

    #获取姓名编号
    def Match(Names, assignment):
        match = pd.DataFrame()
        match = pd.concat([match,assignment.loc[assignment['完成人'] == Names]])
        IndNumber = match['行业'].tolist()
        return IndNumber

    #用获取的姓名编号匹配所需要下载年报的公司名称list
    def Get_companylist(industrynum, company):
        df_final = pd.DataFrame()
        df_final = company.loc[company['行业大类代码'] == "01"]
        return df_final



    table = Pdf_extract_table("industry.pdf") #把PDF解析成列表
    company = Get_alllist(table) #将上述列表转化成完整的数据框
    Names = InputStu() #从用户端获取姓名
    assign = pd.read_csv('001班行业安排表.csv', converters={'行业': str})[['行业', '完成人']]
    industrynum = Match(Names,assign)
    companylist = Get_companylist(industrynum, company)
  
  

结果

运行结果截图 获取结果截图

Ⅱ.下载年报

导入本部分所需模块

    
      import json
      import os
      from time import sleep
      from urllib import parse
      import requests
    
    

获取上交所公司数据

    
      def get_adress(company_list):
          url = "http://www.cninfo.com.cn/new/information/topSearch/detailOfQuery"
          data = {
              'keyWord': company_list,
              'maxSecNum': 10,
              'maxListNum': 5,
          }
          hd = {
              'Host': 'www.cninfo.com.cn',
              'Origin': 'http://www.cninfo.com.cn',
              'Pragma': 'no-cache',
              'Accept-Encoding': 'gzip,deflate',
              'Connection': 'keep-alive',
              'Content-Length': '70',
              'User-Agent': 'Mozilla/5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 75.0.3770.100Safari / 537.36',
              'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
              'Accept': 'application/json,text/plain,*/*',
              'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
          }
          r = requests.post(url, headers=hd, data=data)
          print(r.text)
          r = r.content
          m = str(r, encoding="utf-8")
          pk = json.loads(m)
          orgId = pk["keyBoardList"][0]["orgId"]  # 获取参数
          plate = pk["keyBoardList"][0]["plate"]
          code = pk["keyBoardList"][0]["code"]
          print(orgId, plate, code)
          return orgId, plate, code


      def download_PDF(url, file_name):  # 下载pdf
          url = url
          r = requests.get(url)
          f = open(company + "/" + file_name + ".pdf", "wb")
          f.write(r.content)


      def get_PDF(orgId, plate, code):
          url = "http://www.cninfo.com.cn/new/hisAnnouncement/query"
          data = {
              'stock': '{},{}'.format(code, orgId),
              'tabName': 'fulltext',
              'pageSize': 30,
              'pageNum': 1,
              'column': plate,
              'category': 'category_ndbg_szsh;',
              'plate': '',
              'seDate': '',
              'searchkey': '',
              'secid': '',
              'sortName': '',
              'sortType': '',
              'isHLtitle': 'true',
          }

          hd = {
              'Host': 'www.cninfo.com.cn',
              'Origin': 'http://www.cninfo.com.cn',
              'Pragma': 'no-cache',
              'Accept-Encoding': 'gzip,deflate',
              'Connection': 'keep-alive',
              # 'Content-Length': '216',
              'User-Agent': 'User-Agent:Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27',
              'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
              'Accept': 'application/json,text/plain,*/*',
              'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
              'X-Requested-With': 'XMLHttpRequest',
              # 'Cookie': cookies
          }
          data = parse.urlencode(data)
          print(data)
          r = requests.post(url, headers=hd, data=data)
          print(r.text)
          r = str(r.content, encoding="utf-8")
          r = json.loads(r)
          reports_list = r['announcements']
          for report in reports_list:
              if '摘要' in report['announcementTitle'] or "20" not in report['announcementTitle']:
                  continue
              if 'H' in report['announcementTitle']:
                  continue
              else:  # http://static.cninfo.com.cn/finalpage/2019-03-29/1205958883.PDF
                  pdf_url = "http://static.cninfo.com.cn/" + report['adjunctUrl']
                  file_name = report['announcementTitle']
                  print("正在下载:" + pdf_url, "存放在当前目录:/" + company + "/" + file_name)
                  download_PDF(pdf_url, file_name)
                  sleep(2)

      company_list = companylist.loc[ : ,"上市公司简称"]
      for i in range(len(company_list)):# 文件名、目录名或卷标语法不正确。: '*ST香梨',于是把*ST前面的"*"去掉
          company_list.iloc[i] = company_list.iloc[i].replace('*', '')

      if __name__ == '__main__':
          for company in company_list[:]:
              os.mkdir(company)
              orgId, plate, code = get_adress(company)
              get_PDF(orgId, plate, code)
              print("下载下一家")
          print("全部下载完毕!")
    
    

结果

运行结果截图 获取结果截图

Ⅲ解析年报,获取数据

导入本部分所需模块

      
        import pandas as pd
        import fitz
        import re

      
    

代码

      
        t = 0
        for company in company_list:
            t += 1
            df = pd.read_csv(company + '.csv')  # 读取存有公告名称的csv文件用来循环访问pdf年报
            df = df.sort_index(ascending=False)
            final = pd.DataFrame(index=range(2011, 2022), columns=['营业收入(元)', '基本每股收益(元/股)'])  # 创建一个空的dataframe用于后面保存数据
            final.index.name = '年份'
            code = str(df.iloc[0, 1])
            name = df.iloc[-1, 2].replace(' ', '')

            for i in range(len(df)):  # 循环访问每年的年报
                title = df.iloc[i, 3]
                doc = fitz.open('./%s/%s.pdf' % (company, title))
                text = ''
                for j in range(15):  # 读取每份年报前15页的数据(一般财务指标读15页就够了,全部读取的话会比较耗时间)
                    page = doc[j]
                    text += page.get_text()
                p_year = re.compile('.*?(\d{4}) .*?年度报告.*?')  # 捕获目前在匹配的年报年份
                year = int(p_year.findall(text)[0])
                # 设置需要匹配的四种数据的pattern
                p_rev = re.compile('(?<=\n)营业总?收入(?\w?)?\s?\n?([\d+,.]*)\s\n?')
                p_eps = re.compile('(?<=\n)基本每股收益(元/?/?\n?股)\s?\n?([-\d+,.]*)\s?\n?')
                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(',', ''))  # 将匹配到的营业收入的千分位去掉并转为浮点数

                if year > 2011:
                    pre_rev = final.loc[year - 1, '营业收入(元)']
                    if pre_rev / revenue > 2:
                        print('%s%s营业收入下跌超过百分之50,可能出现问题,请手动查看' % (company, title))

                eps = p_eps.search(text).group(1)
                final.loc[year, '营业收入(元)'] = revenue  # 把营业收入和每股收益写进最开始创建的dataframe
                final.loc[year, '基本每股收益(元/股)'] = eps

            final.to_csv('【%s】.csv' % company, encoding='utf-8-sig')  # 将各公司数据存储到本地测csv文件

            site = p_site.search(text).group(1)  # 匹配办公地址和网址(由于取最近一年的,所以只要匹配一次不用循环匹配)
            web = p_web.search(text).group(1)

            with open('【%s】.csv' % company, 'a', encoding='utf-8-sig') as f:  # 把股票简称,代码,办公地址和网址写入文件末尾
                content = '股票简称,%s\n股票代码,%s\n办公地址,%s\n公司网址,%s' % (name, code, site, web)
                f.write(content)
            print(name + '数据已保存完毕' + '(', t, '/', len(company), ')')

      
    

结果

结果截图 结果截图

导入数据

    
      import pandas as pd
      for company in company_list:
          data=pd.read_csv('./提取的数据/{}.csv'.format(company),sep=',')
          print(data)

      #data=pd.read_csv('./提取的数据/农发种业.csv',encoding='ISO-8859-1', sep=',')##此代码不行,读取的中文是乱码
      #于是加上了以下代码
      #-*- coding : utf-8-*-
      # coding:unicode_escape
      import pandas as pd
      import numpy as np
      import matplotlib.pyplot as plt
      io = r'C:\Users\Hou\Downloads\query-hive-191685.csv'
      idk=r'C:\Users\Hou\Downloads\query-hive-191744.csv'
      #data=pd.read_csv(io,encoding='unicode_escape')

      data_list = []
      for company in company_list:
          data = pd.read_csv('./提取的数据/{}.csv'.format(company),encoding='gbk')
          data_list.append(data)

      #获得文件中的公司信息去掉的数据框

      def remove_text(data_list):
          new_data_list = [[data[0:10]] for data in data_list]
          return new_data_list
      new_data_list=remove_text(data_list)

      #筛选出营业收入排名前十的公司
      new_data_list=np.array(new_data_list)
      def income(new_data_list):
          income_df = pd.DataFrame(columns=['十年总营业收入(元)']) #创建一个总营业收入的数据框
          for i in range(len(company_list)):
              income_df.iloc[new_data_list[i]['股票简称','营业收入(元)'],'十年营业总收入(元)'] = new_data_list[i][0:9,1].sum()
              return income_df
      income_df = income(new_data_list)
    
  

绘制图像

  
    import matplotlib.pyplot as plt
    for company in company_list:
      company_data = pd.read_csv("./用来绘制曲线的/{}.csv".format(company), encoding='gbk')
      y_1 = company_data.iloc[:,1].apply(pd.to_numeric, errors='coerce')
      y_2 = company_data["基本每股收益(元/股)"].apply(pd.to_numeric, errors='coerce')
      # y_1 = pd.to_numeric(company_data.iloc[:,1] ,errors='coerce')
      # y_1 = []
      x = range(2012, 2022)

      plt.title('{}近10年基本每股收益(元/股)变动情况'.format(company))  # 折线图标题
      plt.title('{}近10年营业收入(元)变动情况'.format(company))  # 折线图标题
      plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示汉字
      plt.xlabel('时间')  # x轴标题
      #plt.ylabel('差值')  # y轴标题
      plt.plot(x, y_1, marker='o', markersize=3)  # 绘制折线图,添加数据点,设置点的大小E
      #plt.plot(x, y_2, marker='o', markersize=3)


      for a, b in zip(x, y_1):
          plt.text(a, b, b, ha='center', va='bottom', fontsize=10)  # 设置数据标签位置及大小
      #for a, b in zip(x, y_2):
          #plt.text(a, b, b, ha='center', va='bottom', fontsize=10)


      plt.legend('方案一')  # 设置折线名称

      plt.show()  # 显示折线图

    
  

结果

结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图
  
    """
    绘制每一年的对比图:income
    """
    #绘制多个条形图
    from matplotlib import pyplot as plt
    from matplotlib import font_manager

    #导入字体
    my_font = font_manager.FontProperties(fname=r'shuxing.TTF')
    income_ten = pd.read_csv("./用来绘制曲线的/income ten.csv", encoding='gbk')
    a = [2012,2013,2014,2015,2016]
    b_1 = income_ten.iloc[1,1:6].apply(pd.to_numeric, errors='coerce') #一列的数据
    b_2 = income_ten.iloc[2,1:6].apply(pd.to_numeric, errors='coerce') #二列的数据
    b_3 = income_ten.iloc[3,1:6].apply(pd.to_numeric, errors='coerce') #三列的数据
    b_4 = income_ten.iloc[4,1:6].apply(pd.to_numeric, errors='coerce') #四列的数据
    b_5 = income_ten.iloc[5,1:6].apply(pd.to_numeric, errors='coerce') #五列的数据

    #定义变量
    bar_width = 0.2

    bar_1 = list(range(len(a)))
    bar_2 = [i+bar_width for i in bar_1]
    bar_3 = [i+bar_width for i in bar_2]
    bar_4 = [i+bar_width for i in bar_3]
    bar_5 = [i+bar_width for i in bar_4]
    #设置图片尺寸与清晰度
    plt.figure(figsize=(30, 8), dpi=80)

    #导入数据,绘制条形图
    plt.bar(range(len(a)), b_1, width=bar_width, label='ST香梨')
    plt.bar(bar_2, b_2, width=bar_width, label='北大荒')
    plt.bar(bar_3, b_3, width=bar_width, label='登海种业')
    plt.bar(bar_4, b_4, width=bar_width, label='敦煌种业')
    plt.bar(bar_5, b_5, width=bar_width, label='海南橡胶')
    #添加标题
    plt.title('每一年的营业收入对比图', size=20)
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示汉字
    #添加xy轴
    plt.xlabel('时间')
    plt.ylabel('营业收入(元)')
    #x轴刻度
    plt.xticks(bar_2, a,size=15)
    plt.legend()

    #展示效果图
    plt.show()
  

结果

结果截图

    income_ten = pd.read_csv("./用来绘制曲线的/income ten.csv", encoding='gbk')
    a = [2017,2018,2019,2020,2021]
    b_1 = income_ten.iloc[1,6:11].apply(pd.to_numeric, errors='coerce') #六列的数据
    b_2 = income_ten.iloc[2,6:11].apply(pd.to_numeric, errors='coerce') #七列的数据
    b_3 = income_ten.iloc[3,6:11].apply(pd.to_numeric, errors='coerce') #八列的数据
    b_4 = income_ten.iloc[4,6:11].apply(pd.to_numeric, errors='coerce') #九列的数据
    b_5 = income_ten.iloc[5,6:11].apply(pd.to_numeric, errors='coerce') #十列的数据

    #定义变量
    bar_width = 0.2

    bar_1 = list(range(len(a)))
    bar_2 = [i+bar_width for i in bar_1]
    bar_3 = [i+bar_width for i in bar_2]
    bar_4 = [i+bar_width for i in bar_3]
    bar_5 = [i+bar_width for i in bar_4]
    #设置图片尺寸与清晰度
    plt.figure(figsize=(30, 8), dpi=80)

    #导入数据,绘制条形图
    plt.bar(range(len(a)), b_1, width=bar_width, label='隆平高科')
    plt.bar(bar_2, b_2, width=bar_width, label='农发种业')
    plt.bar(bar_3, b_3, width=bar_width, label='神农科技')
    plt.bar(bar_4, b_4, width=bar_width, label='万向德农')
    plt.bar(bar_5, b_5, width=bar_width, label='新农开发')
    #添加标题
    plt.title('每一年的营业收入对比图', size=20)
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示汉字
    #添加xy轴
    plt.xlabel('时间')
    plt.ylabel('营业收入(元)')
    #x轴刻度
    plt.xticks(bar_2, a,size=15)
    plt.legend()

    #展示效果图
    plt.show()
  

结果

结果截图

    """
    绘制每一年的对比图:income per share
    """
    #绘制多个条形图
    from matplotlib import pyplot as plt
    from matplotlib import font_manager

    #导入字体

    income_ten = pd.read_csv("./用来绘制曲线的/income per share ten.csv", encoding='gbk')
    a = [2012,2013,2014,2015,2016]
    b_1 = income_ten.iloc[1,1:6].apply(pd.to_numeric, errors='coerce') #一列的数据
    b_2 = income_ten.iloc[2,1:6].apply(pd.to_numeric, errors='coerce') #二列的数据
    b_3 = income_ten.iloc[3,1:6].apply(pd.to_numeric, errors='coerce') #三列的数据
    b_4 = income_ten.iloc[4,1:6].apply(pd.to_numeric, errors='coerce') #四列的数据
    b_5 = income_ten.iloc[5,1:6].apply(pd.to_numeric, errors='coerce') #五列的数据

    #定义变量
    bar_width = 0.2

    bar_1 = list(range(len(a)))
    bar_2 = [i+bar_width for i in bar_1]
    bar_3 = [i+bar_width for i in bar_2]
    bar_4 = [i+bar_width for i in bar_3]
    bar_5 = [i+bar_width for i in bar_4]
    #设置图片尺寸与清晰度
    plt.figure(figsize=(30, 8), dpi=80)

    #导入数据,绘制条形图
    plt.bar(range(len(a)), b_1, width=bar_width, label='ST香梨')
    plt.bar(bar_2, b_2, width=bar_width, label='北大荒')
    plt.bar(bar_3, b_3, width=bar_width, label='登海种业')
    plt.bar(bar_4, b_4, width=bar_width, label='敦煌种业')
    plt.bar(bar_5, b_5, width=bar_width, label='海南橡胶')
    #添加标题
    plt.title('每一年的基本每股收益收入对比图', size=20)
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示汉字
    #添加xy轴
    plt.xlabel('时间')
    plt.ylabel('基本每股收益(元/股)')
    #x轴刻度
    plt.xticks(bar_2, a,size=15)
    plt.legend()

    #展示效果图
    plt.show()
  

结果

结果截图

    income_ten = pd.read_csv("./用来绘制曲线的/income per share ten.csv", encoding='gbk')
    a = [2017,2018,2019,2020,2021]
    b_1 = income_ten.iloc[1,6:11].apply(pd.to_numeric, errors='coerce') #一列的数据
    b_2 = income_ten.iloc[2,6:11].apply(pd.to_numeric, errors='coerce') #二列的数据
    b_3 = income_ten.iloc[3,6:11].apply(pd.to_numeric, errors='coerce') #三列的数据
    b_4 = income_ten.iloc[4,6:11].apply(pd.to_numeric, errors='coerce') #四列的数据
    b_5 = income_ten.iloc[5,6:11].apply(pd.to_numeric, errors='coerce') #五列的数据

    #定义变量
    bar_width = 0.2

    bar_1 = list(range(len(a)))
    bar_2 = [i+bar_width for i in bar_1]
    bar_3 = [i+bar_width for i in bar_2]
    bar_4 = [i+bar_width for i in bar_3]
    bar_5 = [i+bar_width for i in bar_4]
    #设置图片尺寸与清晰度
    plt.figure(figsize=(30, 8), dpi=80)

    #导入数据,绘制条形图
    plt.bar(range(len(a)), b_1, width=bar_width, label='隆平高科')
    plt.bar(bar_2, b_2, width=bar_width, label='农发种业')
    plt.bar(bar_3, b_3, width=bar_width, label='神农科技')
    plt.bar(bar_4, b_4, width=bar_width, label='万向德农')
    plt.bar(bar_5, b_5, width=bar_width, label='新农开发')
    #添加标题
    plt.title('每一年的基本每股收益对比图', size=20)
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示汉字
    #添加xy轴
    plt.xlabel('时间')
    plt.ylabel('基本每股收益(元/股)')
    #x轴刻度
    plt.xticks(bar_2, a,size=15)
    plt.legend()

    #展示效果图
    plt.show()

  

结果

结果截图

Ⅴ.结果解读

营业收入: *ST香梨、海南橡胶、隆平高科营业收入总体上涨,其余公司波动较大,且主要呈现下降的趋势。

每股收益: 每股收益的增减和净利润上升或下降息息相关,在营业收入下降的情况下,北大荒、敦煌种业、新农开发这几家公司仍然保持着每股收益增长。 其中,神农科技和登海种业的净利润处于亏损状态,每股收益为负。

从对比图的结果来看,敦煌种业、*ST香梨、万向德农营业收入表现亮眼,*ST香梨从2014年每股收益由负变正;农发种业前五年收益良好,后五年收益减少,增长放缓;新农开发近年来经营业绩也不容乐观。

结果总结:行业龙图效应不显著,大部分都是处于中上游水平。但是根据国家发展规划,农业需要加大科技研发投入,未来在农业科技领域创新性强、可行性高的公司更具有增长潜力。

本次实验的心得

过程艰难,但收获巨大。做完这个项目之后,我发现之前自学python基础的时候一些难以理解和运用的知识现在可以融会贯通了,比如之前对定义函数然后返回所需要的值以及传入参数很困惑, 现在发现定义一个函数并调用是非常轻松的,关键在于函数内部的编程逻辑。此外,做的过程中遇到的很多报错情况我都可以更快的解决,然后不停地修改代码,直至程序正常运行。 虽然整个项目花费了很多时间,但是我觉得这对于我们真正理解和运用编程来解决问题意义重大,之后遇到更复杂的项目也更愿意去探索。

最后非常感谢老师给了我们这样一份期末作业,更感谢老师在课堂上耐心的讲解和知识的拓展,带领我们探索了很多实用的方法和工具,感谢老师!!!