鱼C论坛

 找回密码
 立即注册
查看: 677|回复: 8

求助大佬帮忙看一下代码

[复制链接]
发表于 2020-3-6 12:08:33 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
用python改了一个文本分析的程序,基本思路就是循环读取文章中的句子,分词、去停用词、计算词在情感词典里的得分最后输出。文章大概有9000多行,有两篇文章,但是程序跑了一个小时也没输出结果,也没报错,我的电脑内存8g的,我想知道是计算量太大了,还是代码有问题,求大神相助
# -*- coding:utf8 -*-

from collections import defaultdict
import os
import re
import jieba
import codecs
import sys
import chardet
import matplotlib.pyplot as plt



# php install jieba





#使用jieba 函数  对 sentence 文本进行分词

def sent2word(sentence):


#调用jieba进行分词
    segList = jieba.cut(sentence)

#分词后的结果存为segResult 为list类型
    segResult = []
    for w in segList:
        segResult.append(w)

#调用 readLines2 读取停用词
    stopwords = readLines2('stop_words.txt')

#如果是停用词 就不保存到newSent
    newSent = []
    for word in segResult:
        if word+'\n' in stopwords:
            continue
        else:
            newSent.append(word)
#返回newSent
    return newSent


#直接对 sentence 进行分词  不使用停用词 并返回(主要是根据word需要这个操作)
def returnsegResult(sentence):

    segResult = []
    segList = jieba.cut(sentence)

    for w in segList:
        segResult.append(w)
    return segResult


#获取 filepath 目录下的所有文件目录并返回
def eachFile(filepath):
    pathDir =  os.listdir(filepath)
    child=[]
    for allDir in pathDir:
        child.append(os.path.join('%s/%s' % (filepath, allDir)))
    return child


#读取 filename路径 的每一行数据 并返回
def readLines2(filename):
    fopen = open(filename,encoding='gbk', errors='ignore' )
    data=[]
    for x in fopen.readlines():
        if x.strip() != '':
                data.append(x.strip())
    fopen.close()
    return data

#主要为情感定位  见程序文件相关代码 这里是为了速度 提取了部分代码 本来应该在classifyWords 里边  貌似对速度影响不大
def words():
    #情感词
    senList = readLines2('BosonNLP_sentiment_score.txt')
    senDict = defaultdict()
    for s in senList:
        senDict[s.split(' ')[0]] = s.split(' ')[1]
    #否定词
    notList = readLines2('notDict.txt')
    #程度副词
    degreeList = readLines2('degreeDict.txt')
    degreeDict = defaultdict()
    for d in degreeList:
        degreeDict[d.split(' ')[0]] = d.split(' ')[1]

    return senDict,notList,degreeDict




# 见文本文档  根据情感定位  获得句子相关得分
def classifyWords(wordDict,senDict,notList,degreeDict):

    senWord = defaultdict()
    notWord = defaultdict()
    degreeWord = defaultdict()
    #遍历一行的字符串经过分词后转成的字典的每一个键,就是每一个词
    for word in list(wordDict.keys()):
        #判断这些词是否有在情感词典的键中且不在否定词列表中且不在程度副词字典的键中
        if word in list(senDict.keys()) and word not in notList and word not in list(degreeDict.keys()):
            #把符合条件的词在语句字典中对应的序号作为情感词新字典的键,对应的值是那个词在情感字典中的得分
            senWord[wordDict[word]] = senDict[word]
        #判断这些词是否有在否定词列表中且不在程度副词字典的键中
        elif word in notList and word not in list(degreeDict.keys()):
            #把符合条件的词在语句字典中对应的序号作为否定词新字典的键,对应的值是-1
            notWord[wordDict[word]] = -1
        #判断这些词是否有在程度副词字典的键中
        elif word in list(degreeDict.keys()):
            #把符合条件的词在语句字典中对应的序号作为程度副词新字典的键,对应的值是那个词在程度副词字典中的得分
            degreeWord[wordDict[word]] = degreeDict[word]
    #返回三个新字典,各自的键都是语句字典中的词在语句字典中对应的序号,值是词相对应的得分
    return senWord, notWord, degreeWord


#计算一句话的句子得分 
def scoreSent(senWord, notWord, degreeWord, segResult):
    W = 1
    score = 0
    #下面三个列表用来存所有在情感字典、否定词列表、程度副词字典中存在的语句字典的词在那三个中的位置
    senLoc = list(senWord.keys())
    notLoc = list(notWord.keys())
    degreeLoc = list(degreeWord.keys())
    senloc = -1
    #notloc = -1
    #degreeloc = -1
    # 遍历句中所有单词,i为单词绝对位置(绝对位置的意思就是句子分词后不去停用词,各词在句子中的位置)
    for i in range(0, len(segResult)):
        # 如果该词为情感词
        if i in senLoc:
            # loc为情感词位置列表的序号
            senloc += 1
            # 直接添加该情感词分数
            score += W * float(senWord[i])
            # print "score = %f" % score
            # senloc这个变量的作用是在下面的if判断中判断是不是最后一个词(准确性待定)
            if senloc < len(senLoc) - 1:
                # 判断该情感词与下一情感词之间是否有否定词或程度副词
                # j为绝对位置
                for j in range(senLoc[senloc], senLoc[senloc + 1]):
                    # 如果有否定词
                    if j in notLoc:
                        W *= -1
                    # 如果有程度副词
                    elif j in degreeLoc:
                        W *= float(degreeWord[j])
        # i定位至下一个情感词
        if senloc < len(senLoc) - 1:
            i = senLoc[senloc + 1]
    return score


#列表 转 字典
def listToDist(wordlist):
    data={}
    for x in range(0, len(wordlist)):
        data[wordlist[x]]=x
    return data



#主题从这里开始 上边全是方法


#获取 test/neg 下所有文件 路径——返回一个列表,元素是路径字符串
filepwd=eachFile("test/neg")



#
score_articlelist=[]
score_allarticle=[]
datafen=[]


#获取 本地的情感词 否定词 程度副词——返回的是一个列表,元素一是情感字典,键是词,值是分数;元素二是否定词列表,里面各元素就是否定词;元素三是程度副词字典,键是词,值是对应得分
words_vaule=words()

#循环 读取 filepwd  (也就是test/neg目录下所有文件全部跑一下)
for x in filepwd:
    #读目录下文件的内容——得到一个列表,元素是每一行的字符串
    data=readLines2(x)
    #循环 读取 data 对data的每一行内容进行分词和去停用词——每一行输入到sent2word()都得到一个分词后的列表,datafen就是一个列表套列表
    for i in range(len(data)):
        datafen.append(sent2word(data[i]))
        #循环读取 datafen的每一个元素,就是每一行分词后的结果,进行下一步处理
        for j in range(len(datafen)):
            #列表转字典——键是每个词,值是序号,姑且叫它语句字典
            datafen_dist=listToDist(datafen[j])
            #通过classifyWords函数——输入的words_value的三个元素就是情感字典、否定词列表、程度副词字典,得到三个新字典,各自的键都是语句字典中的词在语句字典中对应的序号,值是词相对应的得分
            #data_1是一个元组,三个元素就是三个字典
            data_1=classifyWords(datafen_dist,words_vaule[0],words_vaule[1],words_vaule[2])
            # 通过scoreSent 计算 最后句子得分——输入三个字典和一句话分词后的列表
            data_2=scoreSent(data_1[0],data_1[1],data_1[2],returnsegResult(data[i]))#!!!!!!!!!!循环里复合循环待验证
            # 将得分保存在score_var 以列表的形式,这是针对一篇文章的得分列表,每一个元素对应的是每句话的得分
            score_articlelist.append(data_2)
    #遍历得分列表,计算每一句话的得分的平均值,作为一篇文章的总得分
    for k in range(len(score_articlelist)):
        score_sum_article += score_articlelist[i]
        score_article = score_sum_article/len(score_articlelist)
    score_allarticle.append(score_article)
#打印句子得分
for g in range(len(score_allarticle)):
    print(score_allarticle[g])
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-3-6 14:48:25 | 显示全部楼层
先跑一章短一点的,代码太长不好看哪里错了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-6 15:04:59 | 显示全部楼层
LYF511 发表于 2020-3-6 14:48
先跑一章短一点的,代码太长不好看哪里错了

我加了if __name__=="__main__()":后跑完没有结果,就是直接 >>>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-6 15:06:59 | 显示全部楼层
加在哪的?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-6 15:08:11 From FishC Mobile | 显示全部楼层
Dave111 发表于 2020-3-6 15:04
我加了if __name__=="__main__()":后跑完没有结果,就是直接 >>>

你在idle里运行的吗
直接>>>狠简单啦,就是所有print都没有被执行
如果是涉及循环列表的,就是列表为空
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-6 15:13:49 | 显示全部楼层
wp231957 发表于 2020-3-6 15:08
你在idle里运行的吗
直接>>>狠简单啦,就是所有print都没有被执行
如果是涉及循环列表的,就是列表为空

对,在idle中执行的,好的,那我看看问题在哪
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-6 15:15:43 From FishC Mobile | 显示全部楼层
Dave111 发表于 2020-3-6 15:13
对,在idle中执行的,好的,那我看看问题在哪

在循环之前print一下列表或列表长度
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-6 15:19:59 | 显示全部楼层
wp231957 发表于 2020-3-6 15:15
在循环之前print一下列表或列表长度

好的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-6 16:08:47 | 显示全部楼层

加在各函数下面
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-21 11:22

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表