• 辨别标题党--提取关键词与比较相似度


    最近好几天都没有更新博客,因为网络设置崩了,然后各种扎心,最后还重装电脑,而且还有一些软件需要重新安装或者配置,所以烦了好久,搞好电脑之后,老师又布置了一个任务,个人觉得很有趣--判别学校新闻是否是标题党

    虽然我不觉得老师的方法能够很好地判别标题党行为,但是也只能开干了!

    第一步:通过爬虫获取学校新闻,这一部分已经在之前的文章中写过,所以不在重复了,有点不同的是,因为从文本中提取内容列会出错,有少数文章的内容没有被全部提取,所以我在源代码的基础上改变了一下,生成了一个只存放内容的文件content.csv

    第二步:(1)对文档内容进行分词,并且按照文档数分别存放在不同的文档,例如3454篇新闻就用3454份文档来存放分词后的内容,但是是可以直接用一个文档来存放的,每篇文章只在文档中占一行就行,分词用结巴,不要用全模式,否则后面选择的关键词会有很多相同,另外下载百度停用词表,在停用词表中的词语就不要写入文件中,因为不能成为关键词,如是、的、好

    (2)使用TF-IDF算法进行关键词提取,首先套一个循环,循环3454个文档,然后按行读取,之后各种烧脑。举个例子:在文档A中,有100个分词后的词语,通过集合去掉重复的之后还剩下80个,把这80个加到字典中,并且要计算这80个词语在文档A中各自出现的次数;然后轮到文档B,首先判断文档B中的分词词语有哪些在字典中,在字典中的话就不加进字典,但是值VALUES加1,否则加入字典。这个太难说清楚了,还是自己去看看详细介绍吧!

    (3)根据TF-IDF算法得到每篇新闻权值前三的词语,并且写入文件中

    第三步:(1)训练相似度模型:这是个很陌生的知识,但是用了工具就很简单了,原理就是存储许多词语,把他们分为向量,就像网络一样连在一起,把距离的远近作为词语之间的相似度,缺点就在于无法识别不在模型中的词语相似度。可以去看看这两个链接,非常详细:https://blog.csdn.net/kaoyala/article/details/79090156;https://github.com/jsksxs360/Word2Vec

    (2)把模型训练好了之后就简单了,把标题从新闻中提取出来,然后进行全模式分词,对于第一个关键词,与分词后的标题逐个计算相似度,取最大相似度,然后再到第二个关键词,最后把结果写入文件中

    下面附上源码:

    import jieba
    import math
    import re
    
    def word():
        #第一步:文档预处理:读取文档 -> 删除不需要的字符(如回车符
    、制表符	、空格等)
        # -> 转换成unicode格式 -> 对文档分词 -> 转换成utf-8格式写入txt文档
    
        #读取文档
        #由于使用TF-IDF方法提取关键词,而且需要分析题目相似度,所以每篇文章生成一个文档!
        with open('content.csv', 'r', newline='', encoding='utf-8')as col:
            j = 1
            for i in col.readlines():
                content=jieba.cut(i,cut_all=False)    #结巴分词精确模式
                result=" ".join(content)     #把generator转换为字符串类型
                result=re.compile('[u4e00-u9fa5]+').findall(result)
                # 转换为列表并且去掉了那些数字3,4英文之类的
                list1=[]    #存储去掉空格之后的列表
    
                #导入停用词表,并进行简单清洗
                list111 = []  #存储停用词表
                with open('baidustop.txt', 'r', encoding='utf-8')as f:
                    for i in f.readlines():
                        i = i.strip()  #去掉换行符
                        list111.append(i)
    
                for i in result:
                    if len(i)<=1 :    #如果是空格或者单个字就去掉不要
                        continue
                    elif i in list111:  #如果在停用词表里面就不要
                        continue
                    else:
                        list1.append(i)
    
                # 把分词结果写入TXT文档中
                with open('txt/TF-IDF'+str(j)+'.txt','a',encoding='utf-8')as file:
                    for word in list1:
                        file.write(word+'
    ')
                j+=1   #为了文档名字
    
    def language():
        #第二步:使用TF-IDF算法进行关键词提取
        dict2={}   #存放语料库,统计一个单词在多少个文件中存在
        for i in range(1,3455):
            with open('txt/TF-IDF' + str(i) + '.txt', 'r', encoding='utf-8')as file:
                list2=[]
                for wd in file.readlines():   #按行读取
                    wd=wd.replace('
    ','')   #去掉换行符
                    list2.append(wd)
    
                #制作语料库字典,为了求解IDF
                set1=set(list2)    #转换为集合!
                for word in set1:
                    dict2[word]=dict2.get(word,0)+1   #一个文档中每个单词最多只能增加1 !
        with open('language.txt','a',encoding='utf-8')as f:
            for j,k in zip(dict2.keys(),dict2.values()):
                f.write(j+':')
                f.write(str(k))
                f.write('
    ')
    
    def TfIdf():
        dict3={}    #存放语料库中的键值对,生成该字典是为了进行索引
        for line in open('language.txt','r+',encoding='utf-8'):
            (key, value) = line.strip('
    ').split(':')  #换行符是用strip去除的,然后通过区分冒号来区分键值
            dict3[key] = str(value)   #把对应的键值对存放进dict3字典中
        # 根据dict3求解IDF
        for q in dict3.keys():
            dict3[q] = math.log(3455 / (int(dict3[q]) + 1), 10)  # 10是底
    
        for j in range(1,3455):   #所有文档各自遍历一遍
            count = {}    #存放每次文档的单词和次数
            sumdict={}    #用来存放TF-IDF算法后的结果
            with open('txt/TF-IDF' + str(j) + '.txt', 'r', encoding='utf-8')as file:
                for wd in file.readlines():   #按行读取
                    # 求解单词频率,为了TF
                    wd=wd.replace('
    ','')   #去掉换行符
                    count[wd]=count.get(wd,0)+1  #统计在本文档中该单词出现的次数
                for k in count.keys():
                    sumdict[k] = count[k] / sum(count.values())  # TF表示词条在文档中出现的频率
                    sumdict[k]=sumdict[k]*dict3[k]     #此处用sumdict存放TF-IDF值
    
                data=[]  #存储三个最大值
                with open('TF-IDF.txt', 'a', encoding='utf-8')as f:
                    for i in range(3):
                        data.append(max(sumdict,key=lambda x:sumdict[x]))   #根据字典的值查找最大值
                        f.write(max(sumdict,key=sumdict.get)) #写入文件中
                        f.write(' ')  #用逗号来分割三个关键字
                        sumdict.pop(max(sumdict,key=sumdict.get))  #删除最大值
                    f.write('
    ')
    
    if __name__=='__main__':
        word()
        language()
        TfIdf()
    

      

    from gensim.corpora import WikiCorpus
    import jieba
    import codecs
    from gensim.models import Word2Vec
    from gensim.models.word2vec import LineSentence
    import multiprocessing
    '''
    读取中文wiki语料库,并解析提取xml中的内容
    '''
    #将下载的语料转为文本txt格式
    def dataprocess():
        space = " "
        i = 0
        output = open('E:wikichinawiki-articles.txt', 'w', encoding='utf-8')
        wiki = WikiCorpus('E:wikizhwiki-latest-pages-articles.xml.bz2', lemmatize=False, dictionary={})
        for text in wiki.get_texts():
            output.write(space.join(text) + "
    ") #分割一个词之后换行
            i = i + 1
            if (i % 10000 == 0):   #每一万文章就提示一下
                print('Saved ' + str(i) + ' articles')
        output.close()
        print('Finished Saved ' + str(i) + ' articles')
    
    
    '''
    加载停用词表
    '''
    def createstoplist(stoppath):
        print('load stopwords...')
        stoplist = [line.strip() for line in codecs.open(stoppath, 'r', encoding='utf-8').readlines()]
        #fromkeys用于创建一个新字典,以序列seq中元素做字典的键,value为字典所有键对应的初始值
        stopwords = {}.fromkeys(stoplist)  #值默认为None
        return stopwords
    
    '''
    过滤英文
    '''
    def isAlpha(word):
        try:  #isalpha() 方法检测字符串是否只由字母组成。
            return word.encode('ascii').isalpha()
        except UnicodeEncodeError:
            return False
    
    def trans_seg():
        stopwords = createstoplist(r'E:wikiaidustop.txt')
        i = 0
        with codecs.open('E:wikisegchinawiki-segment40.txt', 'w', 'utf-8') as wopen:
            print('开始...')
            with codecs.open('E:wikizhUTF8chinawiki-articles-jian.txt', 'r', 'utf-8') as ropen:
                for line in ropen.readlines():
                    line = line.strip()  #去掉空格
                    i += 1
                    print('line ' + str(i)) #第几行
                    text = ''
                    for char in line.split():  #对每行进行列表分割
                        if isAlpha(char):  #如果是英文就不要
                            continue
                        text += char  #空格加词语
                    # print(text)
                    words = jieba.cut(text)   #默认模式分词
                    seg = ''
                    for word in words:
                        if word not in stopwords:  #如果在停用词表就不用这个词
                            if len(word) > 1 and isAlpha(word) == False:  # 去掉长度小于1的词和英文
                                if word != '	':  #空格
                                    seg += word + ' '
                    wopen.write(seg + '
    ')
        print('结束!')
    
    '''
    利用gensim中的word2vec训练词向量
    '''
    def word2vec():
        print('Start...')
        rawdata='E:wikisegchinawiki-segment40.txt'
        modelpath='E:wikimodelchinawikimodel.model'
        #vectorpath='E:word2vecvector'
        model=Word2Vec(LineSentence(rawdata),size=400,window=5,min_count=5,workers=multiprocessing.cpu_count())#参数说明,gensim函数库的Word2Vec的参数说明
        model.save(modelpath)
        #model.wv.save_word2vec_format(vectorpath,binary=False)
        print("Finished!")
    
    if __name__=='__main__':
        # dataprocess()
        # trans_seg()
        # word2vec()
        model= Word2Vec.load('E:wikimodelchinawikimodel.model')
        # print(model.most_similar('开心',topn=5))
        try:
            pro=model.similarity('开心', '不存在')
        except:
            pro=0
        print(pro)
    

      

    '''
    计算关键词与题目相似度的流程:加载题目文件与关键词文件--》把题目进行分词--》把分词后的结果保存
    --》把关键词与分词题目词语逐一比较相似度取最大值--》每篇文章得到三个相似度(三个关键词)
    前期准备:jieba分词、wiki中文语料、word2vec模型训练、词向量比较相似度
    标题文档:fosu1中提取,关键词文档:TF-IDF.txt中提取,皆是3454行
    '''
    import csv
    import jieba
    from gensim.models import Word2Vec
    import re
    
    #加载词语模型,用来输出词语相似度
    model= Word2Vec.load('E:wikimodelchinawikimodel.model')
    
    list1=[]   #存储分词后的标题
    list2=[]   #存储关键词
    list3=[]   #存储相似度
    #用with同时打开两个文件
    with open('fosu1.csv','r',newline='',encoding='utf-8')as file1,open('TF-IDF.txt','r',encoding='utf-8')as file2:
        read1 = csv.reader(file1)  # 读取文件
        title = [row[0] for row in read1]  # 获取标题
        for i in title:
            i = jieba.cut(i, cut_all=False)  #全模式识别名字的效果很差
            #虽然使用精确模式有所改变,但是很多名字都不在模型中,所以没法识别,返回错误
            tit = ",".join(i)
            tit=re.compile('[u4e00-u9fa5]+').findall(tit) #只取中文
            list1.append(tit)
        for j in file2.readlines():
            j=j.strip()
            j=j.split(' ')
            list2.append(j)   #关键词
    
        file3=open('similarity.txt','a',encoding='utf-8')
        n=0  #第几个标题
        for p,q in zip(list1,list2):
            word=" ".join(q)
            file3.write(title[n] + ':')
            file3.write(word+'|')
            for w in range(3):
                pro=[]  #暂时存储一个关键词与其他标题分词的相似度
                for i in p:
                    try:    #关键词与他们逐一比较相似度
                        pro.append(model.similarity(i,q[w]))
                    except:   #有些词语不在模型词典中,会报错
                        if i==q[w]:  #如果词语不在模型中,但是标题中有相同的词语,那么就把相似度设为1.0
                            pro.append(1.0)
                        else:   #否则为0.0
                            pro.append(0.0)
                pro=float('%.2f'%max(pro))  #取相似度最大的为关键词与标题的相似度
                file3.write(str(pro)+' ')
            file3.write('
    ')
            n+=1  #标题+1
    

      

  • 相关阅读:
    几种php加速器比较
    细说firewalld和iptables
    Linux上iptables防火墙的基本应用教程
    mysql 字符串按照数字类型排序
    《设计模式之禅》之六大设计原则下篇
    《设计模式之禅》之六大设计原则中篇
    《设计模式之禅》之六大设计原则上篇
    git bash 乱码问题之解决方案
    nexus没有授权导致的错误
    Java之微信公众号开发
  • 原文地址:https://www.cnblogs.com/fodalaoyao/p/10549263.html
Copyright © 2020-2023  润新知