1. 程式人生 > 實用技巧 >利用python分析pdf資料,分析上市公司財報

利用python分析pdf資料,分析上市公司財報

import re
import os.path
import matplotlib
import matplotlib.pyplot as plt
from pdfminer.pdfparser import PDFParser, PDFDocument
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LTTextBoxHorizontal, LAParams
from pdfminer.pdfinterp import PDFTextExtractionNotAllowed
from IPython.display import display, HTML
from pandas import DataFrame
# from adjustText import adjust_text


# 解析PDF文字,並儲存到TXT檔案中
def parse(pdf_path):
    TEXT = ''
    fp = open(pdf_path, 'rb')
    # 用檔案物件建立一個PDF文件分析器
    parser = PDFParser(fp)
    # 建立一個PDF文件
    doc = PDFDocument()
    # 連線分析器,與文件物件
    parser.set_document(doc)
    doc.set_parser(parser)

    # 提供初始化密碼,如果沒有密碼,就建立一個空的字串
    doc.initialize()

    # 檢測文件是否提供txt轉換,不提供就忽略
    if not doc.is_extractable:
        raise PDFTextExtractionNotAllowed
    else:
        # 建立PDF,資源管理器,來共享資源
        rsrcmgr = PDFResourceManager()
        # 建立一個PDF裝置物件
        laparams = LAParams()
        device = PDFPageAggregator(rsrcmgr, laparams=laparams)
        # 建立一個PDF解釋其物件
        interpreter = PDFPageInterpreter(rsrcmgr, device)

        # 迴圈遍歷列表,每次處理一個page內容
        # doc.get_pages() 獲取page列表
        startIndex = 0
        isEnd = False

        for page in doc.get_pages():
            interpreter.process_page(page)
            # 接受該頁面的LTPage物件
            layout = device.get_result()
            # 這裡layout是一個LTPage物件 裡面存放著 這個page解析出的各種物件
            # 一般包括LTTextBox, LTFigure, LTImage, LTTextBoxHorizontal 等等
            # 想要獲取文字就獲得物件的text屬性,

            for x in layout:
                if(isinstance(x, LTTextBoxHorizontal)):
                    text = x.get_text()
                    if(text.find('公司簡介和主要財務指標')) > 0:
                        startIndex += 1
                    if(startIndex == 2):
                        TEXT += text

                    if(text.find('主要會計資料和財務指標')) > 0:
                        isEnd = True
            if(isEnd):
                break

    return TEXT


dir_path = os.path.abspath('.') + '\\pdf_files'
files = os.listdir(dir_path)
# print(files)

pdfList = []
for file in files:
    pdf_path = dir_path + '\\' + file
    pdfList.append(parse(pdf_path))

comInfoList = []

for pdf in pdfList:
    comInfo = {}
    r = r'(?<=股票簡稱)\s*[^\n]+'
    comInfo['股票簡稱'] = re.findall(r, pdf)[0].strip() if re.search(r, pdf) else ''

    r = r'(?<=股票程式碼)\s*[^\n]+'
    comInfo['股票程式碼'] = re.findall(r, pdf)[0].strip() if re.search(r, pdf) else ''

    r = r'(?<=公司的法定代表人)\s*[^\n]+'
    comInfo['公司的法定代表人'] = re.findall(r, pdf)[0].strip() if re.search(r, pdf) else ''

    r = r'(?<=辦公地址)\s*[^\n]+'
    comInfo['辦公地址'] = re.findall(r, pdf)[0].strip() if re.search(r, pdf) else ''

    r = r'(?<=公司國際網際網路網址)\s*[^\n]+'
    comInfo['公司網址'] = re.findall(r, pdf)[0].strip() if re.search(r, pdf) else ''

    r = r'(?<=電子信箱)\s*[^\n]+'
    comInfo['電子信箱'] = re.findall(r, pdf)[0].strip() if re.search(r, pdf) else ''

    r = r'(?<=營業收入(元))\s*(([^\n]+\n){4})'

    m = re.findall(r, pdf)[0]
    s = ''.join(m).replace(' ', '').split('\n')

    comInfo['2019年營業收入元'] = s[0]
    comInfo['2018年營業收入元'] = s[1]
    comInfo['2017年營業收入元'] = s[3]

    comInfoList.append(comInfo)

# print(comInfoList)
data = {'股票簡稱': [], '股票程式碼': [], '公司的法定代表人': [], '辦公地址': [], '公司網址': [], '電子信箱': []}
data2 = {'股票簡稱': [], '股票程式碼': [], '2019': [], '2018': [], '2017': []}

for comInfo in comInfoList:
    data['股票簡稱'].append(comInfo['股票簡稱'])
    data['股票程式碼'].append(comInfo['股票程式碼'])
    data['公司的法定代表人'].append(comInfo['公司的法定代表人'])
    data['辦公地址'].append(comInfo['辦公地址'])
    data['公司網址'].append(comInfo['公司網址'])
    data['電子信箱'].append(comInfo['電子信箱'])

    data2['股票簡稱'].append(comInfo['股票簡稱'])
    data2['股票程式碼'].append(comInfo['股票程式碼'])
    data2['2019'].append(comInfo['2019年營業收入元'])
    data2['2018'].append(comInfo['2018年營業收入元'])
    data2['2017'].append(comInfo['2017年營業收入元'])

print('1. 提取:股票簡稱、股票程式碼、公司的法定代表人、辦公地址、公司網址、電子信箱')
df = DataFrame(data)
display(HTML(df.to_html()))

print('2. 提取:主要會計資料和財務指標——第01-10位:最近三年營業收入(元)')
df2 = DataFrame(data2)
display(HTML(df2.to_html()))

print('3. 所有同學,畫一張或幾張圖,呈現一些規律')
matplotlib.rcParams['font.sans-serif'] = ['SimHei']  # 用黑體顯示中文

x = ['2017', '2018', '2019']

# texts = []
for comInfo in comInfoList:
    y = [round(float(comInfo['2017年營業收入元'].replace(',', ''))/1000000, 2), round(float(comInfo['2018年營業收入元'].replace(',', ''))/1000000, 2), round(float(comInfo['2019年營業收入元'].replace(',', ''))/1000000, 2)]
    plt.plot(x, y, label=comInfo['股票簡稱'])
    for xx, yy in zip(x, y):
        plt.text(xx, yy + 1, str(yy), ha='center', va='bottom', fontsize=10)
        # texts.append(str(yy))

# new_texts = [plt.text(x_, y_, text, fontsize=10) for x_, y_, text in zip(x, y, texts)]
# adjust_text(new_texts, only_move={'text': 'x'}, arrowprops=dict(arrowstyle='-', color='grey'), save_steps=True)

plt.xlabel("年份")
plt.ylabel("營業收入(百萬元)")
plt.title("2017-2019各公司營業收入趨勢圖")
plt.legend(loc="upper left")

plt.show()

x = data['股票簡稱']
ys = []
for comInfo in comInfoList:
    y = []
    y.append(round(float(comInfo['2017年營業收入元'].replace(',', ''))/1000000, 2))
    y.append(round(float(comInfo['2018年營業收入元'].replace(',', ''))/1000000, 2))
    y.append(round(float(comInfo['2019年營業收入元'].replace(',', ''))/1000000, 2))
    ys.append(y)

chart = DataFrame(
     data=ys,
     index=x, columns=[2017, 2018, 2019])

chart.plot(kind='bar')

plt.title("各公司營業收入2017-2019年度對比圖")
plt.ylabel("營業收入(百萬元)")
plt.legend()
plt.xticks(rotation=45)

plt.show()

print('4. 基於所畫圖,做一些文字解讀')