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基础的时候一些难以理解和运用的知识现在可以融会贯通了,比如之前对定义函数然后返回所需要的值以及传入参数很困惑, 现在发现定义一个函数并调用是非常轻松的,关键在于函数内部的编程逻辑。此外,做的过程中遇到的很多报错情况我都可以更快的解决,然后不停地修改代码,直至程序正常运行。 虽然整个项目花费了很多时间,但是我觉得这对于我们真正理解和运用编程来解决问题意义重大,之后遇到更复杂的项目也更愿意去探索。
最后非常感谢老师给了我们这样一份期末作业,更感谢老师在课堂上耐心的讲解和知识的拓展,带领我们探索了很多实用的方法和工具,感谢老师!!!