Python提取上市公司年报指定关键字句子并进行语调积极程度分析

我是为了写论文所以学习了以下Python。要实现的目的是:逐一读取文件夹中各个年报pdf中“经营情况讨论与分析”章节。将该章节中包含一些特定关键字的句子全部筛选出来,然后评价筛选出来句子语调积极程度,并将结果输出为Excel,Excel中要包含的内容包括公司名称,年份,语调积极程度评分。代码没有报错可以正常跑,但秒跑完,然后输出的result是一个空的Excel,请问问题出在了哪里呢?因为是目的性很强的去学习Python,所以对很多理论知识都一知半解,还请各位能帮我解决一下这个问题,谢谢!

import os
import re
import pandas as pd
from PyPDF2 import PdfFileReader

# 定义关键字列表
keywords = ['增长', '提高', '增加', '扩大', '优化', '改善', '创新', '领先', '占据市场', '提升', '强化', '突破', '拓展', '加强', '提升']

# 定义函数,用于读取pdf文件中的指定章节
def read_pdf_section(pdf_path):
    with open(pdf_path, 'rb') as f:
        pdf = PdfFileReader(f)
        for page in pdf.pages:
            text = page.extractText()
            # 查找“经营情况讨论与分析”章节
            match = re.search(r'经营情况讨论与分析', text)
            if match:
                # 获取章节所在页码
                page_num = pdf.pages.index(page)
                # 查找章节结束位置
                end_match = re.search(r'[\n\s]*[\d一二三四五六七八九十]+[\n\s]*年度报告', text[match.end():])
                if end_match:
                    end_pos = match.end() + end_match.start()
                else:
                    end_pos = len(text)
                # 返回章节内容
                return text[match.end():end_pos], page_num
    # 如果未找到指定章节,则返回空字符串和-1
    return '', -1

# 定义函数,用于评价句子语调积极程度
def evaluate_tone(sentence):
    score = 0
    for keyword in keywords:
        if keyword in sentence:
            score += 1
    return score

# 定义函数,用于处理单个pdf文件
def process_pdf(pdf_path):
    # 读取pdf文件中的指定章节
    section, page_num = read_pdf_section(pdf_path)
    if page_num == -1:
        return None
    # 将章节内容按句子分割
    sentences = re.split(r'[。!?]', section)
    # 筛选包含关键字的句子
    filtered_sentences = [sentence.strip() for sentence in sentences if any(keyword in sentence for keyword in keywords)]
    # 评价句子语调积极程度
    scores = [evaluate_tone(sentence) for sentence in filtered_sentences]
    # 获取公司名称和年份
    company_name = os.path.basename(os.path.dirname(pdf_path))
    year = re.search(r'(\d{4})年度报告', section).group(1)
    # 构造结果字典
    result = {'公司名称': company_name, '年份': year, '语调积极程度评分': sum(scores) / len(scores)}
    return result

# 定义函数,用于处理整个文件夹
def process_folder(folder_path):
    results = []
    for file_name in os.listdir(folder_path):
        if file_name.endswith('.pdf'):
            file_path = os.path.join(folder_path, file_name)
            result = process_pdf(file_path)
            if result:
                results.append(result)
    # 将结果转换为DataFrame并输出为Excel文件
    df = pd.DataFrame(results)
    df.to_excel('result.xlsx', index=False)

# 调用函数,处理指定文件夹
process_folder('D:\上市公司年报')

你好,你的代码比较多,我只是大概看了下。
问题出在pd.DataFrame(results)这句代码里的results的数据类型不对。
这边你的results是一个list,而每个list的元素是一个dict。这不是pd.DataFrame()能够接受的数据类型。

pd.DataFrame()接受4种数据类型,ndarray, Series, DataFrame, dict。
而你的results是一个list,不在四种可接受的四种数据类型之列, 你需要对results做一个类型转变。

data = {
    '公司名称': [], 
    '年份': [], 
    '语调积极程度评分': []
}
for result in results:
    data['公司名称'].append(result['公司名称'])
    data['年份'].append(result['年份'])
    data['语调积极程度评分'].append(result['公司名称'])
不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7767368
  • 除此之外, 这篇博客: 决策树(基于增益率)之python实现中的 如图,为使用到的公式,信息熵表明样本的混乱程度,增益表示熵减少了,即样本开始分类,增益率是为了平衡增益准则对可取值较多的属性的偏好,同时增益率带来了对可取值偏小的属性的偏好,实际中,先用增益进行筛选,选取大于增益平均值的,然后再选取其中增益率最高的。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    以下代码纯粹手写,未参考其他人代码,如果问题,请不吝赐教。

    1,计算信息熵的函数

    import numpy as np
    # 计算信息熵
    # data:like np.array
    # data.shape=(num_data,data_features+1) 即属性与label放一起了
    def entropy(data,num_class):
        class_set=list(set(data[:,-1]))
        result=0
        length=len(data)
    #     这里修改一下,不使用num_class
        for i in range(len(class_set)):
            l=len(data[data[:,-1]==class_set[i]])
            p=l/length
    #         防止某类未出现,概率为0
            if p>0:
                result-=p*np.log2(p)
        return result
    Python学习qq群:10667510,送全套爬虫学习资料与教程~

    2,计算增益及属性a的固有值(IV)

    # 计算不同属性的信息增益
    # detail_features:特征构成的list,每个特征的可取值构成list元素,即也是list
    def calculate_gain(data,detail_features,num_class):
      '''返回各属性对应的信息增益及平均值'''
        result=[]
        ent_data=entropy(data,num_class)
        for i in range(len(detail_features)):
            res=ent_data
            for j in range(len(detail_features[i])):
    #             有问题?
                part_data=data[data[:,i]==detail_features[i][j]]
                length=len(part_data)
                res-=length*entropy(part_data,num_class)/len(data)
            result.append(res)
        return result,np.array(result).mean()
    # 计算某个属性的固有值
    def IVa(data,attr_index):
        attr_values=list(set(data[:,attr_index]))
        v=len(attr_values)
        res=0
        for i in range(v):
            part_data=data[data[:,attr_index]==attr_values[i]]
            p=len(part_data)/len(data)
            res-=p*np.log2(p)
        return res    
    Python学习qq群:10667510,送全套爬虫学习资料与教程~

    3,构建节点类,以便构建树

    class Node:
        def __init__(self,key,childs):
            self.childs=[]
            self.key=key
        def add_node(self,node):
            self.childs.append(node)
    

    4,构建树

    # 判断数据是否在所有属性的取值都一样,以致无法划分
    def same_data(data,attrs):
        for i in range(len(attrs)):
            if len(set(data[:,i]))>1:
                return False
        return True
    
    # attrs:属性的具体形式
    def create_tree(data,attrs,num_class,root):
    #     注意这里3个退出条件
        #     1,如果数据为空,不能划分,此时这个叶节点不知标记为哪个分类了
        if len(data)==0:
            return
    #   2,如果属性集为空,或所有样本在所有属性的取值相同,无法划分,返回样本最多的类别
        if len(attrs)==0 or same_data(data,attrs):
            class_set=list(set(data[:,-1]))
            max_len=0
            index=0
            for i in range(len(class_set)):
                if len(data[data[:,-1]==class_set[i]])>max_len:
                    max_len=len(data[data[:,-1]==class_set[i]])
                    index=i
            root.key=root.key+class_set[index]
            return 
    #     3,如果当前节点包含同一类的样本,无需划分
        if len(set(data[:,-1]))==1:
            root.key=root.key+data[0,-1]
            return
        ent=entropy(data,num_class)
        gain_result,mean=calculate_gain(data,attrs,num_class)
        max=0
        max_index=-1
    #     求增益率最大
        for i in range(len(gain_result)):
            if gain_result[i]>=mean:
                iva=IVa(data,i)
                if gain_result[i]/iva>max:
                    max=gain_result[i]/iva
                    max_index=i
        for j in range(len(attrs[max_index])):
            part_data=data[data[:,max_index]==attrs[max_index][j]]
    #         删除该列特征
            part_data=np.delete(part_data,max_index,axis=1)
    #         添加节点
            root.add_node(Node(key=attrs[max_index][j],childs=[]))
    #         删除某一类已判断属性
            new_attrs=attrs[0:max_index]
            new_attrs.extend(attrs[max_index+1:])
            create_tree(part_data,new_attrs,num_class,root.childs[j])     
    Python学习qq群:10667510,送全套爬虫学习资料与教程~

    5,使用西瓜数据集2.0测试,数据这里就手写了,比较少

    def createDataSet():
        """
        创建测试的数据集
        :return:
        """
        dataSet = [
            # 1
            ['青绿', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', '好瓜'],
            # 2
            ['乌黑', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', '好瓜'],
            # 3
            ['乌黑', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', '好瓜'],
            # 4
            ['青绿', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', '好瓜'],
            # 5
            ['浅白', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', '好瓜'],
            # 6
            ['青绿', '稍蜷', '浊响', '清晰', '稍凹', '软粘', '好瓜'],
            # 7
            ['乌黑', '稍蜷', '浊响', '稍糊', '稍凹', '软粘', '好瓜'],
            # 8
            ['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '硬滑', '好瓜'],
    
            # ----------------------------------------------------
            # 9
            ['乌黑', '稍蜷', '沉闷', '稍糊', '稍凹', '硬滑', '坏瓜'],
            # 10
            ['青绿', '硬挺', '清脆', '清晰', '平坦', '软粘', '坏瓜'],
            # 11
            ['浅白', '硬挺', '清脆', '模糊', '平坦', '硬滑', '坏瓜'],
            # 12
            ['浅白', '蜷缩', '浊响', '模糊', '平坦', '软粘', '坏瓜'],
            # 13
            ['青绿', '稍蜷', '浊响', '稍糊', '凹陷', '硬滑', '坏瓜'],
            # 14
            ['浅白', '稍蜷', '沉闷', '稍糊', '凹陷', '硬滑', '坏瓜'],
            # 15
            ['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '软粘', '坏瓜'],
            # 16
            ['浅白', '蜷缩', '浊响', '模糊', '平坦', '硬滑', '坏瓜'],
            # 17
            ['青绿', '蜷缩', '沉闷', '稍糊', '稍凹', '硬滑', '坏瓜']
        ]
    
        # 特征值列表
        labels = ['色泽', '根蒂', '敲击', '纹理', '脐部', '触感']
    
        # 特征对应的所有可能的情况
      
    
      labels_full = []
    
        for i in range(len(labels)):
            items=[item[i] for item in dataSet]
            uniqueLabel = set(items)
            labels_full.append(list(uniqueLabel))
        return np.array(dataSet), labels, labels_full
    Python学习qq群:10667510,送全套爬虫学习资料与教程~

    6,开始构建树

    dataset,labels,labels_full=createDataSet()
    
    root=Node('',[])
    create_tree(dataset, labels_full, 2, root)
    Python学习qq群:10667510,送全套爬虫学习资料与教程~

    7,打印树结构

    def print_root(n,root):print(n,root.key)
        for node in root.childs:
            print_root(n+1,node)
    print_root(0,root)      
    Python学习qq群:10667510,送全套爬虫学习资料与教程~

    打印结果为:数字表示层次

    0 
    1 模糊坏瓜
    1 稍糊
    2 硬滑坏瓜
    2 软粘好瓜
    1 清晰
    2 硬滑好瓜
    2 软粘
    3 青绿
    4 稍蜷好瓜
    4 蜷缩
    4 硬挺坏瓜
    3 乌黑坏瓜
    3 浅白
    

    8,绘制树形结构,这里我就手动绘制了。图中有2个叶节点为空白,即模型不知道该推测其为好瓜还是坏瓜。这里我暂时没有好的思路解决,只能随机处理?


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^