精华内容
下载资源
问答
  • 需求很简单,就是从数据库中读取内容,包括资讯,产品,公司简介之类,看看是否存在违禁,有的话就把这条记录的ID存入违禁文档。可以应用于分词库匹配检索,如关键字、敏感词的标识,起到过滤的作用。
  • 目前,主题自动标引形成...如果将近义、同义以及多义规范化地统一处理,将会提高查准率和查全率,而规范处理即为将关键词转换为主题.1、汉语关键词自动转换主题问题的提出为提高检索效率,主题有着重要的地...

    0e7f62f6514008f06cd6c5c006650430.png

    目前,主题自动标引形成的索引均为关键字或关键词的索引.关键词在选择的时候,可以是主题词,也可以是没有经过任何规范化处理过的任意词汇,也就是自由词.用自由词作为关键词进行标引时,用户检索文献的时候就很容易造成误检或者漏检.

    如果将近义词、同义词以及多义词规范化地统一处理,将会提高查准率和查全率,而规范处理即为将关键词转换为主题词.

    1、汉语关键词自动转换主题词问题的提出

    为提高检索效率,主题词有着重要的地位.所以,用主题词作为文献标引,形成检索标识进行检索具有明显优点.

    首先,主题词属于规范化词汇,具有单一性的特点,一个词能够准确地表达一个概念,不随时间变化,不被使用者的主观理解和上下文左右,是十分理想的分析元素.

    其次,主题词所反应的概念并不是孤立的,它可以通过逻辑组合形成索引标识,来表达文献的中心内容这就有效避免了标引词对文献主题表达不清,检索率不高的问题.用主题词作为检索词进行对中文文本数据的分析与研究,能有效避免由于检索词的不规范性所导致检索数据库中主题标识的冗余或缺失.

    主题词是一种专门从自然语言中挑选出来的表达文本内容的词汇,用于文献的标引或检索,再加以规范化,达到了一个词语一个意义的要求的语词.

    例如,“玉米”与“苞米”为同义词,在建立主题索引系统时,如果不进行规范和区分,那么在检索时,就会出现检索不全的情况,为此就必须选择“玉米”这个具有使用频率高而又具有单种含义的规范性词语作为主题词.

    目前关键词-主题词转换实现方式主要包括3种:人工方式、计算机辅助方式和自动转换方式.1)人工方式,主要依赖智力劳动人工完成对应转换的操作,效率较低,但质量较高.2)自动转换方式,即由计算机根据释义词典、同义词表等各种语义工具通过各种相似度算法自动完成,效率较高,但质量参差不齐.3)计算机辅助方式,即由人与计算机共同完成,是当前各种关键词-主题词转换采用的主要编制形式.

    如李纲在《基于词汇链的关键词自动标引方法》中,利用基于知网的词语语义相关度算法对词汇链的构建算法进行了改进,并结合词频和词的位置等统计信息,进行关键词的自动标引.程肖、路蓓等在《热点主题词提取方法研究》中,基于多特征的融合提出热点主题词权重计算方法,构造出热点主题词判断公式HK,实现对热点主题词的提取.将关键词自动转换为主题词是计算机中文信息处理一直关注和力争解决的问题.

    2、汉语关键词自动转换主题词方法的步骤

    在海量的数据库文献中,并不能保证每篇文章的题名都能反映文章的主题,有的甚至再加上关键词也不能准确地表达文章的主旨.笔者是将文章的题名和摘要两者中的关键词抽出并转换为主题词,这样能有效地防止存取的主题词不能完全表达文章主旨问题的产生.

    关键词自动转换主题词的过程可以分为以下几个步骤:第1步,利用已有的词法分析工具对文献进行分词处理和词性标注;第2步,将经过分词处理后的词汇信息根据词语的词性标注进行筛选和词频统计;第3步,将筛选和统计好的词与现有主题词表进行匹配,并重新进行词频统计;第4步,经过人工干预选择出能表达该文献主旨的相关主题词,并进行存储.

    其主要的简单的设计流程如图1所示.

    在此模块中所应用的是中国科学院计算技术研究所开发的分词工具ICTCLAS(institute of computing technology,Chinese lexical analysis system),应用此工具对数据库中的中文文献进行分词处理和词性标注.ICTCLAS(institute of computing technology,Chinese lexical a-nalysis system)是中国科学院计算技术研究所研制出的基于多层隐马模型的汉语词法分析系统,该系统的功能主要有:中文分词,词性标注,未登录词识别.

    分词正确率高达97.58%(最近的973专家组评测结果).

    其最主要特点是把分出的词都进行了词性标注,且标注详细,不仅把词类分得很详细,而且把每一类又分成若干更详细的类别.在文献中,具有实际意义的词就是名词(n),还有与名词组合起来的形容词等等,这些词是描述性的词,可以对主题起到更好地表达,而其他的词比如量词(q)、代词(r)、介词(p)、助词(u)、标点符号(w)等等,则不具有实际意义.

    所以对文献中词语的筛选与统计,其实就是对文献中名词、动词等的筛选与统计,避免数据的繁杂和冗余,降低了工作量,提高主题词提取的准确性.应用电子版中国分类主题词表将分词出的关键词转换为主题词,具体步骤包括文献分词处理、词频统计、关键词转换主题词和主题词存储.由于在前人研究中文献分词处理和词频统计技术已经比较成熟,本文着重讨论关键词转换成主题词的方法和步骤.

    d194110fb41d8a30bc7f60a85a998933.png

    2.1关键词自动转换主题词过程描述

    本方法使用国家图书馆出版社所出版的电子版中国分类主题词表来具体操作,其界面如图2所示.

    68ed62f40d78d1f2429ace4b760f8de5.png

    对于不规范的检索词,比如同义词、多义词等,利用电子版中国分类主题词表能将其规范化.例如学名为玉米的事物,在现实生活和文献中,有好多其他的别称,如:苞谷、苞米、棒子,玉蜀黍等等.在此主题词表的检索框中输入此类词汇的别称时,该词表系统会自动地将规范化的主题词汇输出.将所有的筛选出来的词汇经过规范化处理后,就可以得到所有有关文本的主题词.针对可能存在主题词重复的情况,再将其词频进行统计.经过人工筛选出确实能表达该文献主题的主题词,并进行数据存储.

    2.2汉语主题词存取的处理流程

    首先,数据库中的表包括文献的名称、作者、出版社报刊名称、出版或发表日期以及存取出来的主题词等数据项.

    其次,主题词存取的数据处理流程体现在主题词存取过程中,通过计算机编程实现文献信息的读取,并利用分词工具对文献汉语语句做出分析并进行分词处理,处理过的词语信息经过词频统计,以方便主题词匹配时的重点选择,再人工干预选出能概括该文献主旨的主题词.

    其流程见图3.

    1cee23e60111ea4f72ab5377f8279662.png

    3、关键词自动转换主题词的分词、统计和存储

    本方法的重点就是汉语语句的分词处理和分词后对词语进行的筛选统计,以及主题词的录入.其实现使用了C#作为其主要编程语言,目的是减少其繁琐与易错性.使用Microsoft SQL Server 2000数据库实现标引词的提取和存储.

    3.1分词处理

    在中科院计算所汉语词法分析系统ICTCLAS中,对中文文本数据进行分词处理和分析.如果仅对某些语句进行分词处理,可以将要分析的语句输入到上面的检索框中,再点击“运行”即可得到详尽的分词结果和词语信息.如图4所示.如果对整个文件进行分析处理的话,点击“处理文件…”按钮,会弹出打开文件的对话框,系统会自动将分好的词语保存在相应的目录下,得到的文件留作后面统计处理用.

    3.2统计处理

    将汉语词法分析系统分析的词语信息进行统计,其算法如下:

    1)初始化cizu,cixing,设定标示符flag,以及字符暂存zz,flag等于0时,表示算法在统计过程中,flag不等于0时,表示一个词组识别结束.

    2)读取文件,用字符串(s)记录.

    3)设定循环次数i(i在(0,s.Length-1)区间).当flag等于0时,如果s[i]为空,则继续,i++;若s[i]是'/',则将cizu赋给zz,设置flag等于1,同时置cizu为空,i++;若s[i]是字,则将s[i]赋给cizu,i++.否则,若s[i]为空格,申请fenci类ci,将zz、词性赋值给ci,同时置zz为空,之后在fenci类中查找当前加入的词是否有记录,若有记录,则更新记录,数目加1,若没有记录,则新建.置flag为0,cixing为空,i++.若s[i]不是空格,则将s[i]赋值给cixing,i++.

    3c38404ed613fd4314af595a869c4974.png

    3.3主题词存储

    将文本的基本信息和提取的主题词保存在数据库中,就得到主题词标引的结果.存储过程其相关代码如下:

    24d9ff1cab22d7d86747ea4a6acd23bd.png

    4、结论

    本文取得的结果是通过中国科学院计算技术研究所开发的汉语分词工具和电子版的中国分类主题词表这2个现有工具,利用计算机编程语言实现中文文献的分词、筛选统计,将分出的词语记录并加以统计词频,词频合适的词被视为能代表文本主旨词语,将其与主题词表进行匹配,从而自动转换成主题词进行存储.

    对分词得到的关键词进行主题词匹配所用到的电子版中国分类主题词表,存在加密的情况,所以在探讨阶段还需要人工干预,但是如果真正投入使用,与国家图书馆合作将其接口实现即可.

    参考文献:

    [1] 章洪流,徐伟,吴倩,等.关键词标引常见问题探讨[J].中国专利与发明,2008(8):66-67.

    [2] 顾潇华,姜亦强,崔涛.中文自动标引、全文检索及搜索引擎三者关系的探讨[J].图书馆学研究,2011(17):88-89.

    展开全文
  • 护发行业词典数据 主要包含相关的词典数据,可以进行护发行业数据过滤等操作。 进行护发行业数据的数据预处理等
  • 需求很简单,就是从数据库中读取内容,包括资讯,产品,公司简介之类,看看是否存在违禁,有的话就把这条记录的ID存入违禁文档。可以应用于分词库匹配检索,如关键字、敏感词的标识,起到过滤的作用。 2.设计...

    说明:2.0相对1.0的算法改进

    首先1.0是用父子节点树来保存树的,一个父对应多个子节点,这就不可避免要使用List来保存子节点,由于List的大小有限制,在1.0的时候加载的数据小于10万条,没有出现List溢出问题。
    所以2.0放弃使用父子节点的树,在数据结构上使用了兄弟节点树,也放弃使用List树解决了List溢出问题同时效率与空间的利用提升了一个等级

    1.面向应用
    最近公司新开发的电商平台,要实现一些违禁词过滤。需求很简单,就是从数据库中读取内容,包括资讯,产品,公司简介之类,看看是否存在违禁词,有的话就把这条记录的ID存入违禁词文档。可以应用于分词库匹配检索,如关键字、敏感词的标识,起到过滤的作用。
    2.设计思想
    采用了哈希表与树相结合的思想,哈希表中放的是关键词的首字符相同和以该首字符开始的树根节点。
    这里写图片描述
    3.方案的优缺点
    首先使用了树来保存违禁词,节省了前缀相同汉字的内存空间,以HashMap作为索引提高了匹配的效率。继承了HashMap的快速定位优点,在以树的形式保存关键字,比HashMap节省空间。又因为不同汉字开头的是不同的小树,小树的查询效率比所有的节点挂载在大树上的效率有更大的提高。
    4.模拟效果图
    这里写图片描述

    节点类
    TreeBrother .Class

    package HashTree;
    
    import java.io.Serializable;
    
    public class TreeNode implements Serializable {
        private int isLast;                 //是否是关键字结束节点
        private String nodeName;            //节点名
        private TreeNode parentNode;        //父节点
        private TreeNode brotherNode;       //兄弟节点
        private TreeNode childNode;         //子节点
        public int getIsLast() {return isLast;}
    
        public void setIsLast(int isLast) {this.isLast = isLast;}
    
        public String getNodeName() {return nodeName;}
    
        public void setNodeName(String nodeName) {this.nodeName = nodeName;}
    
        public TreeNode getParentNode() {return parentNode;}
    
        public void setParentNode(TreeNode parentNode) {this.parentNode = parentNode;}
    
        public TreeNode getBrotherNode() {return brotherNode;}
    
        public void setBrotherNode(TreeNode brotherNode) {this.brotherNode = brotherNode;}
    
        public TreeNode getChildNode() {return childNode;}
    
        public void setChildNode(TreeNode childNode) {this.childNode = childNode;}
    }

    树的操作类
    TreeHelper.Class

    package HashTree;
    
    import jxl.Cell;
    import jxl.Sheet;
    import jxl.Workbook;
    
    import java.io.*;
    import java.util.*;
    
    /**
     * Created by Administrator on 2016/3/22.
     *
     * @version $Revision$ $Date$
     *          2016/3/22
     *          14:09
     * @author: Administrator
     * @since 3.0
     */
    public class TreeBrother {
        private  Boolean isExit;            //是否存在违禁词
        private  int maxLength;             //记录树的最大长度
        private  int index;                 //最大匹配位置
        private  Map<String, TreeNode> map;  //树根索引
        private  List<String> indexList;    //记录关键词的位置
        private  List<String> valueList;    //记录关键词
        private  int wordCount;             //违禁词总数
        private  int articleLength;
    
        public static void main(String[] args) throws IOException {
            TreeBrother treeBrother = new TreeBrother();
            //加载树
            Long loadStartTime = new Date().getTime();
            treeBrother.readXlsBuildTree("F:\\words1.xls");
            treeBrother.readXlsBuildTree(1, 1,2,"F:\\words2.xls");
            treeBrother.readXlsBuildTree(1, 1,2,"F:\\words3.xls");
            treeBrother.readFileBuildTree("F:\\lex-main.lex");
            Long loadEndTime = new Date().getTime();
            //读取文章
            String str = treeBrother.readTxt("F:\\hello.txt");
            //查找树
            Long searchStartTime = new Date().getTime();
            treeBrother.findWordLocation(str);
            Long searchEndTime = new Date().getTime();
            //显示树的信息
            treeBrother.showInfo(loadEndTime-loadStartTime,searchEndTime-searchStartTime);
        }
    
        public TreeBrother(){
            initTreeHelper();
        }
    
        /**
         * TreeHelper初始化
         */
        public void initTreeHelper(){
            isExit=false;
            maxLength = 0;
            index=0;
            map = new HashMap<String, TreeNode>();
            wordCount=0;
            indexList = new ArrayList<String>();
            valueList = new ArrayList<String>();
            articleLength =0;
        }
    
        /**
         * 显示树的操作信息
         * @param loadTime      加载时间
         * @param searchTime    查询时间
         */
        public void showInfo(Long loadTime, Long searchTime){
            System.out.println("加载树的时间:"+String.valueOf(loadTime)+"(ms)");
            System.out.println("查询树的时间:"+String.valueOf(searchTime)+"(ms)");
            System.out.println("树的最大长度为:"+maxLength);
            System.out.println("文章字数:"+articleLength);
            System.out.println("禁词条数:"+wordCount);
            System.out.print("关键词序列:");
            for(String st : indexList){
                System.out.print(st);
            }
            System.out.println();
            System.out.print("关键词队列:");
            for(String st : valueList){
                System.out.print(st);
            }
            System.out.println();
        }
    
        /**
         * 找出字符串中匹配关键词的位置
         * @param str   待处理字符串
         */
        public  void findWordLocation(String str){
            int first =0;
            String word = "";
            while(true){
                //从源字符串中取出小于或等于该树最大长度个数的字符串
                if(first + maxLength < str.length()){
                    word = str.substring(first, first + maxLength);
                }else {
                    if(first != str.length()-1) {
                        //直到最后一个退出匹配
                        if (first != str.length() - 2) {
                            word = str.substring(first, str.length());
                        } else {
                            break;
                        }
                    }else {
                        break;
                    }
                }
    
                TreeNode node = map.get(word.substring(0, 1));
                isExit = false;         //重置原始状态
                //树存在则查找
                if (null != node) {
                    findWord(node, word, 0);
                }
                //index > 0 说明树干存在关键词
                if (0 != index) {
                    String out = String.format("(%d,%d)",first,first+index );
                    indexList.add(out);
                    valueList.add(word.substring(first,first+index+1));
                } else {
                    //index = 0 说明树叶存在关键词
                    if(isExit) {
                        String out = String.format("(%d,%d)",first,first+index );
                        indexList.add(out);
                        valueList.add(word.substring(first,first+index+1));
                    }
                }
                first++;            //字符串起始位置后移
                index =0;           //重置全局变量
                isExit =false;      //重置全局变量
            }
        }
    
        /**
         * 字符串挂载到树
         * @param word  源字符串
         */
        public  void dealWord(String word){
            String temp = word.substring(0,1);
            TreeNode node = map.get(temp);
            //树不存在则创建树根,再创建树
            if(null == node){
                TreeNode rootNode = new TreeNode();
                rootNode.setNodeName(temp);
                makeTree(rootNode, word, 0);
                map.put(temp, rootNode);
            }else{
                //树存在,则更新树节点
                makeTree(node,word,0);
            }
        }
    
        /**
         * 寻找子树匹配的关键词的位置
         * @param treeNode  树节点
         * @param word      待处理字符串
         * @param first     字符串的起始位置
         */
        public  void findWord(TreeNode treeNode, String word, int first){
            //取出起始字符串
            String temp = word.substring(first,first+1);
            //是否首字符串跟树根字符串相同
            if(temp.equals(treeNode.getNodeName()) && 0 == first){
    
                //是否起始字符串在字符的最后位置
                if(first != word.length() - 1) {
                    //是否存在子节点
                    if (null != treeNode.getChildNode()) {
                        //树干是否是关键词,不是则寻找下一个
                        if(1 != treeNode.getIsLast() ) {
                            first++;
                            findWord(treeNode, word, first);
                        }else {
                            //是树干节点则说明是关键词
                            index = first;
                            isExit = true;
                            return;
                        }
                    } else {
                        //是叶节点则说明是关键词
                        index = first;
                        isExit = true;
                        return;
                    }
                }
            }
            //是否叶节点
            if(null == treeNode.getChildNode()){
                //源字符串已经扫描完毕
                if(first == word.length()-2){
                    //是叶节点则说明是关键词
                    index = first;
                    isExit=true;
                    return;
                }
            } else {
                //遍历子节点
                TreeNode brotherNode = treeNode.getChildNode();
                while(null != brotherNode) {
                    //存在路径
                    if(temp.equals(brotherNode.getNodeName())) {
                        //是关键词树干节点或叶节点,记录下来
                        if(1 == brotherNode.getIsLast() || null == brotherNode.getChildNode()){
                            index = first;
                        }
                        //源字符串扫描完毕
                        if(first == word.length()-1) {
                            //子节点是树干关键字,记录下来
                            if(1 == brotherNode.getIsLast()) {
                                index = first;
                                isExit = true;
                                return;
                            }else {
                                //子节点是叶节点关键字,记录下来
                                if(null == brotherNode.getChildNode()){
                                    index = first;
                                    isExit = true;
                                    return;
                                }else {
                                    return;
                                }
                            }
                        }
                        //扫描下一个
                        first++;
                        findWord(brotherNode, word, first);
                        break;
                    }
                    brotherNode = brotherNode.getBrotherNode();
                }
            }
        }
    
        /**
         * 树的遍历
         * @param treeNode  根节点
         */
        public   void showTree(TreeNode treeNode){
            System.out.println(treeNode.getNodeName());
            //遍历兄弟节点
            if(null != treeNode.getBrotherNode()) {
                showTree(treeNode.getBrotherNode());
            }
            //遍历子节点
            if (null != treeNode.getChildNode()) {
                    showTree(treeNode.getChildNode());
            }
        }
    
        /**
         * 创建树
         * @param treeNode  节点
         * @param word      待创建字符串
         * @param first     字符串的起始位置
         */
        public  void makeTree(TreeNode treeNode, String word, int first){
            int flag=0;                 //记录是否已存在兄弟节点,不存在flag=0,则创建兄弟节点
            //word字符扫描完毕就结束
            if(first == word.length()){
                return;
            }
            //取字符
            String temp = word.substring(first,first+1);
            //是否匹配当前节点
            if(temp.equals(treeNode.getNodeName())){
                flag =1;
                //字符游标是否到最后
                if(first != word.length()-1){
                    first++;
                    //子节点是否为空,空则创建子节点,非空则递归调用下一个节点
                    if(null != treeNode.getChildNode()) {
                        makeTree(treeNode.getChildNode(), word, first);
                    }else {
                        TreeNode childNode = new TreeNode();
                        childNode.setNodeName(word.substring(first,first+1));
                        childNode.setParentNode(treeNode);
                        treeNode.setChildNode(childNode);
                        makeTree(childNode, word, first);
                    }
                }else {
                    //关键词匹配最后的节点则标志为1
                    if(0 != first){
                        treeNode.setIsLast(1);
                    }
                }
            }
            TreeNode brotherNode = treeNode.getBrotherNode();           //获取兄弟节点
            //遍历兄弟节点
            while(null != brotherNode){
                //找到匹配节点
                if(temp.equals(brotherNode.getNodeName())){
                    flag =1;
                    //是否是最后一个字符
                    if(first != word.length()-1){
                        first++;
                        makeTree(brotherNode, word, first);
                        break;
                    }else {
                        //扫描到最后一个字符,说明该字符串挂载完毕,标志节点为关键节点
                        if(0 != first){
                            brotherNode.setIsLast(1);
                        }
                    }
                }
                brotherNode = brotherNode.getBrotherNode();
            }
            //节点不存在,则创建兄弟节点
            if(0 == flag){
                brotherNode = new TreeNode();
                brotherNode.setNodeName(word.substring(first,first+1));
                brotherNode.setParentNode(treeNode.getParentNode());
                treeNode.setBrotherNode(brotherNode);
                //偏移下一个节点
                if(first != word.length()-1){
                    makeTree(brotherNode, word, first);
                }else {
                    brotherNode.setIsLast(1);
                }
            }
        }
    
        /**
         * 读取XLS文档(按行读取一行记录)
         * @param myPath  文档的路径
         */
        public  void readXlsBuildTree(String myPath) {
            Workbook readwb = null;
            try {
                //构建Workbook对象, 只读Workbook对象
                //直接从本地文件创建Workbook
                InputStream instream = new FileInputStream(myPath);
                readwb = Workbook.getWorkbook(instream);
                //Sheet的下标是从0开始
                //获取第一张Sheet表
                Sheet readsheet = readwb.getSheet(0);
                //获取Sheet表中所包含的总列数
                int rsColumns = readsheet.getColumns();
                //获取Sheet表中所包含的总行数
                int rsRows = readsheet.getRows();
                //获取指定单元格的对象引用
                String theWord =null;
                for (int i = 0; i < rsRows; i++) {
                    for (int j = 0; j < rsColumns; j++) {
                        Cell cell = readsheet.getCell(j, i);
                        theWord =cell.getContents();
                        //如果theWord不为null和空,则加入Bloomfilter中
                        if (theWord != null && !theWord.trim().equals("")) {
                            //记录树的最大长度
                            if(maxLength < theWord.length()){
                                maxLength = theWord.length();
                            }
                            dealWord(theWord);  //挂载节点
                            wordCount++;        //记录禁词条数
                        }
                        //System.out.print(cell.getContents() + " ");
                    }
                    //System.out.println();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                readwb.close();
            }
        }/**
         * 读取Excel文档(按行读取一行记录)
         * @param myPath   文档的路径
         * @param startRow Excel开始读取的行  默认是最大的长度结束
         * @param startCol Excel开始读取的列
         * @param endCol   Excel结束读取的列
         */
        public  void readXlsBuildTree(int startRow, int startCol,int endCol,String myPath) {
            Workbook readwb = null;
            try {
                //构建Workbook对象, 只读Workbook对象
                //直接从本地文件创建Workbook
                InputStream instream = new FileInputStream(myPath);
                readwb = Workbook.getWorkbook(instream);
                //Sheet的下标是从0开始
                //获取第一张Sheet表
                Sheet readsheet = readwb.getSheet(0);
                //获取Sheet表中所包含的总列数
                int rsColumns = endCol;
                //获取Sheet表中所包含的总行数
                int rsRows = readsheet.getRows();
                //获取指定单元格的对象引用
                String theWord =null;
                for (int i = startRow; i < rsRows; i++) {
                    for (int j = startCol; j < rsColumns; j++) {
                        Cell cell = readsheet.getCell(j, i);
                        theWord =cell.getContents();
                        //如果theWord不为null和空,则加入Bloomfilter中
                        if (theWord != null && !theWord.trim().equals("")) {
                            //记录树的最大长度
                            if(maxLength < theWord.length()){
                                maxLength = theWord.length();
                            }
                            dealWord(theWord);  //挂载节点
                            wordCount++;        //记录禁词条数
                        }
                         //System.out.print(cell.getContents() + " ");
                    }
                    //System.out.println();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                readwb.close();
            }
        }
    
        /**
         *读取文件创建树(按行读取一行记录)
         * @param path  路径
         */
        public void readFileBuildTree(String path) throws FileNotFoundException {
            File file = new File(path);
            FileInputStream in = new FileInputStream(file);
            if (null == in) { //如果in为null,则返回
                return;
            }
            InputStreamReader reader = null;
            try {
                //创建输入流
                reader = new InputStreamReader(in, "UTF-8");
                BufferedReader buffReader = new BufferedReader(reader, 512);
                String theWord = null;
                do {
                    theWord = buffReader.readLine();
                    //如果theWord不为null和空,则加入Bloomfilter中
                    if (theWord != null && !theWord.trim().equals("")) {
                        //记录树的最大长度
                        if(maxLength < theWord.length()){
                            maxLength = theWord.length();
                        }
                        dealWord(theWord);  //挂载节点
                        wordCount++;        //记录禁词条数
                    }
                } while (theWord != null);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //关闭流
                try {
                    if (reader != null) {
                        reader.close();
                        reader = null;
                    }
                    if (in != null) {
                        in.close();
                        in = null;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 读取txt
         * @param path  文件路径
         * @return
         * @throws IOException
         */
        public String readTxt(String path) throws IOException {
            File file = new File(path);
            FileInputStream fin = new FileInputStream(file);
            InputStreamReader reader = new InputStreamReader(fin);
            BufferedReader  buffer = new BufferedReader(reader,512);
            String theWord ;
            String str = "肯德基" ;
            do{
                theWord = buffer.readLine();
                str += theWord;
            } while (null != theWord);
            //记录文章长度
            articleLength = str.length();
            return  str;
        }
    
        public Boolean getIsExit() {return isExit;}
    
        public void setIsExit(Boolean isExit) {this.isExit = isExit;}
    
        public int getMaxLength() {return maxLength;}
    
        public void setMaxLength(int maxLength) {this.maxLength = maxLength;}
    
        public int getIndex() {return index;}
    
        public void setIndex(int index) {this.index = index;}
    
        public Map<String, TreeNode> getMap() {return map;}
    
        public void setMap(Map<String, TreeNode> map) {this.map = map;}
    
        public List<String> getIndexList() {return indexList;}
    
        public void setIndexList(List<String> indexList) {this.indexList = indexList;}
    
        public int getWordCount() {return wordCount;}
    
        public void setWordCount(int wordCount) {this.wordCount = wordCount;}
    
        public List<String> getValueList() {return valueList;}
    
        public void setValueList(List<String> valueList) {this.valueList = valueList;}
    }
    
    

    [读取Excel表格的工具包和源码]
    http://download.csdn.net/detail/xianhujianke/9471561

    展开全文
  • SEO的关键词搜索分词工具大集合

    千次阅读 2018-08-04 11:13:29
    里面包含关键词分词,关键词长度分词,关键词排序,关键词去重等多项功能,为SEO做优化等快排 的时候,提供了简单便捷的使用。 该网站还有其他在线工具,希望您喜欢。多多支持更多的创造。...

    关于SEO或者竞价所用到的关键词词组去重筛选排序等多重功能

    https://www.lmcjl.com/index/participle/index?menu_id=10&parent_id=1

    里面包含了关键词分词,关键词长度分词,关键词排序,关键词去重等多项功能,为SEO做优化等快排

    的时候,提供了简单便捷的使用。

    该网站还有其他在线工具,希望您喜欢。多多支持更多的创造。

    展开全文
  • 关键词抽取就是从文本里面把跟这篇文档意义最相关的一些抽取出来。这个可以追溯到文献检索初期,当时还不支持全文搜索的时候,关键词就可以作为搜索这篇论文的词语。因此,目前依然可以在论文中看到关键词这一项。...

    转自:http://www.cnblogs.com/zhbzz2007 欢迎转载,也请保留这段声明。谢谢!

    1 简介

    关键词抽取就是从文本里面把跟这篇文档意义最相关的一些词抽取出来。这个可以追溯到文献检索初期,当时还不支持全文搜索的时候,关键词就可以作为搜索这篇论文的词语。因此,目前依然可以在论文中看到关键词这一项。

    除了这些,关键词还可以在文本聚类、分类、自动摘要等领域中有着重要的作用。比如在聚类时将关键词相似的几篇文档看成一个团簇,可以大大提高聚类算法的收敛速度;从某天所有的新闻中提取出这些新闻的关键词,就可以大致了解那天发生了什么事情;或者将某段时间内几个人的微博拼成一篇长文本,然后抽取关键词就可以知道他们主要在讨论什么话题。

    总之,关键词就是最能够反映出文本主题或者意思的词语。但是网络上写文章的人不会像写论文那样告诉你本文的关键词是什么,这个时候就需要利用计算机自动抽取出关键词,算法的好坏直接决定了后续步骤的效果。

    关键词抽取从方法来说大致有两种:

    • 第一种是关键词分配,就是有一个给定的关键词库,然后新来一篇文档,从词库里面找出几个词语作为这篇文档的关键词;
    • 第二种是关键词抽取,就是新来一篇文档,从文档中抽取一些词语作为这篇文档的关键词;

    目前大多数领域无关的关键词抽取算法(领域无关算法的意思就是无论什么主题或者领域的文本都可以抽取关键词的算法)和它对应的库都是基于后者的。从逻辑上说,后者比前着在实际使用中更有意义。

    从算法的角度来看,关键词抽取算法主要有两类:

    • 有监督学习算法,将关键词抽取过程视为二分类问题,先抽取出候选词,然后对于每个候选词划定标签,要么是关键词,要么不是关键词,然后训练关键词抽取分类器。当新来一篇文档时,抽取出所有的候选词,然后利用训练好的关键词抽取分类器,对各个候选词进行分类,最终将标签为关键词的候选词作为关键词;
    • 无监督学习算法,先抽取出候选词,然后对各个候选词进行打分,然后输出topK个分值最高的候选词作为关键词。根据打分的策略不同,有不同的算法,例如TF-IDF,TextRank等算法;

    jieba分词系统中实现了两种关键词抽取算法,分别是基于TF-IDF关键词抽取算法和基于TextRank关键词抽取算法,两类算法均是无监督学习的算法,下面将会通过实例讲解介绍如何使用jieba分词的关键词抽取接口以及通过源码讲解其实现的原理。

    2 示例

    下面将会依次介绍利用jieba分词系统中的TF-IDF及TextRank接口抽取关键词的过程。

    2.1 基于TF-IDF算法进行关键词抽取

    基于TF-IDF算法进行关键词抽取的示例代码如下所示,

    from jieba import analyse
    # 引入TF-IDF关键词抽取接口
    tfidf = analyse.extract_tags
    
    # 原始文本
    text = "线程是程序执行时的最小单位,它是进程的一个执行流,\
            是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,\
            线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。\
            线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。\
            同样多线程也可以实现并发操作,每个请求分配一个线程来处理。"
    
    # 基于TF-IDF算法进行关键词抽取
    keywords = tfidf(text)
    print "keywords by tfidf:"
    # 输出抽取出的关键词
    for keyword in keywords:
        print keyword + "/",

    控制台输出,

    keywords by tfidf:
    线程/ CPU/ 进程/ 调度/ 多线程/ 程序执行/ 每个/ 执行/ 堆栈/ 局部变量/ 单位/ 并发/ 分派/ 一个/ 共享/ 请求/ 最小/ 可以/ 允许/ 分配/ 

    2.2 基于TextRank算法进行关键词抽取

    基于TextRank算法进行关键词抽取的示例代码如下所示,

    from jieba import analyse
    # 引入TextRank关键词抽取接口
    textrank = analyse.textrank
    
    # 原始文本
    text = "线程是程序执行时的最小单位,它是进程的一个执行流,\
            是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,\
            线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。\
            线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。\
            同样多线程也可以实现并发操作,每个请求分配一个线程来处理。"
    
    print "\nkeywords by textrank:"
    # 基于TextRank算法进行关键词抽取
    keywords = textrank(text)
    # 输出抽取出的关键词
    for keyword in keywords:
        print keyword + "/",

    控制台输出,

    keywords by textrank:
    线程/ 进程/ 调度/ 单位/ 操作/ 请求/ 分配/ 允许/ 基本/ 共享/ 并发/ 堆栈/ 独立/ 执行/ 分派/ 组成/ 资源/ 实现/ 运行/ 处理/

    3 理论分析

    下面将会依次分析TF-IDF算法及TextRank算法的原理。

    3.1 TF-IDF算法分析

    在信息检索理论中,TF-IDF是Term Frequency - Inverse Document Frequency的简写。TF-IDF是一种数值统计,用于反映一个词对于语料中某篇文档的重要性。在信息检索和文本挖掘领域,它经常用于因子加权。

    TF-IDF的主要思想就是:如果某个词在一篇文档中出现的频率高,也即TF高;并且在语料库中其他文档中很少出现,即DF的低,也即IDF高,则认为这个词具有很好的类别区分能力。

    TF-IDF在实际中主要是将二者相乘,也即TF * IDF,TF为词频(Term Frequency),表示词t在文档d中出现的频率;IDF为反文档频率(Inverse Document Frequency),表示语料库中包含词t的文档的数目的倒数。

    TF公式:

    TF计算公式为,

    TF=count(t)count(di) TF=count(t)count(di)

    式中,count(t)表示文档di中包含词t的个数;

    count(di)表示文档di的词的总数;

    IDF公式:

    IDF计算公式为,

    IDF=num(corpus)num(t)+1 IDF=num(corpus)num(t)+1

    式中,num(corpus)表示语料库corpus中文档的总数;

    num(t)表示语料库corpus中包含t的文档的数目;

    应用到关键词抽取:

    1. 预处理,首先进行分词和词性标注,将满足指定词性的词作为候选词;
    2. 分别计算每个词的TF-IDF值;
    3. 根据每个词的TF-IDF值降序排列,并输出指定个数的词汇作为可能的关键词;

    3.2 TextRank算法分析

    类似于PageRank的思想,将文本中的语法单元视作图中的节点,如果两个语法单元存在一定语法关系(例如共现),则这两个语法单元在图中就会有一条边相互连接,通过一定的迭代次数,最终不同的节点会有不同的权重,权重高的语法单元可以作为关键词。

    节点的权重不仅依赖于它的入度结点,还依赖于这些入度结点的权重,入度结点越多,入度结点的权重越大,说明这个结点的权重越高;

    TextRank迭代计算公式为,

    WS(Vi)=(1d)+dVjIn(Vi)wjiVkOut(Vj)wjkWS(Vj) WS(Vi)=(1−d)+d∗∑Vj∈In(Vi)wji∑Vk∈Out(Vj)wjk∗WS(Vj)

    节点i的权重取决于节点i的邻居节点中i-j这条边的权重 / j的所有出度的边的权重 * 节点j的权重,将这些邻居节点计算的权重相加,再乘上一定的阻尼系数,就是节点i的权重;

    阻尼系数 d 一般取0.85;

    算法通用流程:

    1. 标识文本单元,并将其作为顶点加入到图中;
    2. 标识文本单元之间的关系,使用这些关系作为图中顶点之间的边,边可以是有向或者无向,加权或者无权;
    3. 基于上述公式,迭代直至收敛;
    4. 按照顶点的分数降序排列;
    • 1.本模型使用co-occurrence关系,如果两个顶点相应的语义单元共同出现在一个窗口中(窗口大小从2-10不等),那么就连接这两个顶点;

    • 2.添加顶点到图中时,需要考虑语法过滤,例如只保留特定词性(如形容词和名词)的词;

    应用到关键短语抽取:

    1. 预处理,首先进行分词和词性标注,将单个word作为结点添加到图中;
    2. 设置语法过滤器,将通过语法过滤器的词汇添加到图中;出现在一个窗口中的词汇之间相互形成一条边;
    3. 基于上述公式,迭代直至收敛;一般迭代20-30次,迭代阈值设置为0.0001;
    4. 根据顶点的分数降序排列,并输出指定个数的词汇作为可能的关键词;
    5. 后处理,如果两个词汇在文本中前后连接,那么就将这两个词汇连接在一起,作为关键短语;

    4 源码分析

    jieba分词的关键词抽取功能,是在jieba/analyse目录下实现的。

    其中,__init__.py主要用于封装jieba分词的关键词抽取接口;

    tfidf.py实现了基于TF-IDF算法抽取关键词;

    textrank.py实现了基于TextRank算法抽取关键词;

    4.1 TF-IDF算法抽取关键词源码分析

    基于TF-IDF算法抽取关键词的主调函数是TFIDF.extract_tags函数,主要是在jieba/analyse/tfidf.py中实现。

    其中TFIDF是为TF-IDF算法抽取关键词所定义的类。类在初始化时,默认加载了分词函数tokenizer = jieba.dt、词性标注函数postokenizer = jieba.posseg.dt、停用词stop_words = self.STOP_WORDS.copy()、idf词典idf_loader = IDFLoader(idf_path or DEFAULT_IDF)等,并获取idf词典及idf中值(如果某个词没有出现在idf词典中,则将idf中值作为这个词的idf值)。

    def __init__(self, idf_path=None):
        # 加载
        self.tokenizer = jieba.dt
        self.postokenizer = jieba.posseg.dt
        self.stop_words = self.STOP_WORDS.copy()
        self.idf_loader = IDFLoader(idf_path or DEFAULT_IDF)
        self.idf_freq, self.median_idf = self.idf_loader.get_idf()

    然后开始通过TF-IDF算法进行关键词抽取。

    首先根据是否传入了词性限制集合,来决定是调用词性标注接口还是调用分词接口。例如,词性限制集合为["ns", "n", "vn", "v", "nr"],表示只能从词性为地名、名词、动名词、动词、人名这些词性的词中抽取关键词。

    1) 如果传入了词性限制集合,首先调用词性标注接口,对输入句子进行词性标注,得到分词及对应的词性;依次遍历分词结果,如果该词的词性不在词性限制集合中,则跳过;如果词的长度小于2,或者词为停用词,则跳过;最后将满足条件的词添加到词频词典中,出现的次数加1;然后遍历词频词典,根据idf词典得到每个词的idf值,并除以词频词典中的次数总和,得到每个词的tf * idf值;如果设置了权重标志位,则根据tf-idf值对词频词典中的词进行降序排序,然后输出topK个词作为关键词;

    2) 如果没有传入词性限制集合,首先调用分词接口,对输入句子进行分词,得到分词;依次遍历分词结果,如果词的长度小于2,或者词为停用词,则跳过;最后将满足条件的词添加到词频词典中,出现的次数加1;然后遍历词频词典,根据idf词典得到每个词的idf值,并除以词频词典中的次数总和,得到每个词的tf * idf值;如果设置了权重标志位,则根据tf-idf值对词频词典中的词进行降序排序,然后输出topK个词作为关键词;

    def extract_tags(self, sentence, topK=20, withWeight=False, allowPOS=(), withFlag=False):
        # 传入了词性限制集合
        if allowPOS:
            allowPOS = frozenset(allowPOS)
            # 调用词性标注接口
            words = self.postokenizer.cut(sentence)
        # 没有传入词性限制集合
        else:
            # 调用分词接口
            words = self.tokenizer.cut(sentence)
        freq = {}
        for w in words:
            if allowPOS:
                if w.flag not in allowPOS:
                    continue
                elif not withFlag:
                    w = w.word
            wc = w.word if allowPOS and withFlag else w
            # 判断词的长度是否小于2,或者词是否为停用词
            if len(wc.strip()) < 2 or wc.lower() in self.stop_words:
                continue
            # 将其添加到词频词典中,次数加1
            freq[w] = freq.get(w, 0.0) + 1.0
        # 统计词频词典中的总次数
        total = sum(freq.values())
        for k in freq:
            kw = k.word if allowPOS and withFlag else k
            # 计算每个词的tf-idf值
            freq[k] *= self.idf_freq.get(kw, self.median_idf) / total
        
        # 根据tf-idf值进行排序
        if withWeight:
            tags = sorted(freq.items(), key=itemgetter(1), reverse=True)
        else:
            tags = sorted(freq, key=freq.__getitem__, reverse=True)
        # 输出topK个词作为关键词
        if topK:
            return tags[:topK]
        else:
            return tags

    4.2 TextRank算法抽取关键词源码分析

    基于TextRank算法抽取关键词的主调函数是TextRank.textrank函数,主要是在jieba/analyse/textrank.py中实现。

    其中,TextRank是为TextRank算法抽取关键词所定义的类。类在初始化时,默认加载了分词函数和词性标注函数tokenizer = postokenizer = jieba.posseg.dt、停用词表stop_words = self.STOP_WORDS.copy()、词性过滤集合pos_filt = frozenset(('ns', 'n', 'vn', 'v')),窗口span = 5,(("ns", "n", "vn", "v"))表示词性为地名、名词、动名词、动词。

    首先定义一个无向有权图,然后对句子进行分词;依次遍历分词结果,如果某个词i满足过滤条件(词性在词性过滤集合中,并且词的长度大于等于2,并且词不是停用词),然后将这个词之后窗口范围内的词j(这些词也需要满足过滤条件),将它们两两(词i和词j)作为key,出现的次数作为value,添加到共现词典中;

    然后,依次遍历共现词典,将词典中的每个元素,key = (词i,词j),value = 词i和词j出现的次数,其中词i,词j作为一条边起始点和终止点,共现的次数作为边的权重,添加到之前定义的无向有权图中。

    然后对这个无向有权图进行迭代运算textrank算法,最终经过若干次迭代后,算法收敛,每个词都对应一个指标值;

    如果设置了权重标志位,则根据指标值值对无向有权图中的词进行降序排序,最后输出topK个词作为关键词;

    def textrank(self, sentence, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v'), withFlag=False):
    
        self.pos_filt = frozenset(allowPOS)
        # 定义无向有权图
        g = UndirectWeightedGraph()
        # 定义共现词典
        cm = defaultdict(int)
        # 分词
        words = tuple(self.tokenizer.cut(sentence))
        # 依次遍历每个词
        for i, wp in enumerate(words):
            # 词i 满足过滤条件
            if self.pairfilter(wp):
                # 依次遍历词i 之后窗口范围内的词
                for j in xrange(i + 1, i + self.span):
                    # 词j 不能超出整个句子
                    if j >= len(words):
                        break
                    # 词j不满足过滤条件,则跳过
                    if not self.pairfilter(words[j]):
                        continue
                    # 将词i和词j作为key,出现的次数作为value,添加到共现词典中
                    if allowPOS and withFlag:
                        cm[(wp, words[j])] += 1
                    else:
                        cm[(wp.word, words[j].word)] += 1
        # 依次遍历共现词典的每个元素,将词i,词j作为一条边起始点和终止点,共现的次数作为边的权重
        for terms, w in cm.items():
            g.addEdge(terms[0], terms[1], w)
        
        # 运行textrank算法
        nodes_rank = g.rank()
        
        # 根据指标值进行排序
        if withWeight:
            tags = sorted(nodes_rank.items(), key=itemgetter(1), reverse=True)
        else:
            tags = sorted(nodes_rank, key=nodes_rank.__getitem__, reverse=True)
    
        # 输出topK个词作为关键词
        if topK:
            return tags[:topK]
        else:
            return tags

    其中,无向有权图的的定义及实现是在UndirectWeightedGraph类中实现的。根据UndirectWeightedGraph类的初始化函数__init__,我们可以发现,所谓的无向有权图就是一个词典,词典的key是后续要添加的词,词典的value,则是一个由(起始点,终止点,边的权重)构成的三元组所组成的列表,表示以这个词作为起始点的所有的边。

    无向有权图添加边的操作是在addEdge函数中完成的,因为是无向图,所以我们需要依次将start作为起始点,end作为终止点,然后再将start作为终止点,end作为起始点,这两条边的权重是相同的。

    def addEdge(self, start, end, weight):
        # use a tuple (start, end, weight) instead of a Edge object
        self.graph[start].append((start, end, weight))
        self.graph[end].append((end, start, weight))

    执行textrank算法迭代是在rank函数中完成的。

    首先对每个结点赋予相同的权重,以及计算出该结点的所有出度的次数之和;

    然后迭代若干次,以确保得到稳定的结果;

    在每一次迭代中,依次遍历每个结点;对于结点n,首先根据无向有权图得到结点n的所有
    入度结点(对于无向有权图,入度结点与出度结点是相同的,都是与结点n相连的结点),在前面我们已经计算出这个入度结点的所有出度的次数,而它对于结点n的权值的贡献等于它本身的权值 乘以 它与结点n的共现次数 / 这个结点的所有出度的次数 ,将各个入度结点得到的权值相加,再乘以一定的阻尼系数,即可得到结点n的权值;

    迭代完成后,对权值进行归一化,并返回各个结点及其对应的权值。

    def rank(self):
        ws = defaultdict(float)
        outSum = defaultdict(float)
    
        wsdef = 1.0 / (len(self.graph) or 1.0)
        # 初始化各个结点的权值
        # 统计各个结点的出度的次数之和
        for n, out in self.graph.items():
            ws[n] = wsdef
            outSum[n] = sum((e[2] for e in out), 0.0)
    
        # this line for build stable iteration
        sorted_keys = sorted(self.graph.keys())
        # 遍历若干次
        for x in xrange(10):  # 10 iters
            # 遍历各个结点
            for n in sorted_keys:
                s = 0
                # 遍历结点的入度结点
                for e in self.graph[n]:
                    # 将这些入度结点贡献后的权值相加
                    # 贡献率 = 入度结点与结点n的共现次数 / 入度结点的所有出度的次数
                    s += e[2] / outSum[e[1]] * ws[e[1]]
                # 更新结点n的权值
                ws[n] = (1 - self.d) + self.d * s
    
        (min_rank, max_rank) = (sys.float_info[0], sys.float_info[3])
    
        # 获取权值的最大值和最小值
        for w in itervalues(ws):
            if w < min_rank:
                min_rank = w
            if w > max_rank:
                max_rank = w
    
        # 对权值进行归一化
        for n, w in ws.items():
            # to unify the weights, don't *100.
            ws[n] = (w - min_rank / 10.0) / (max_rank - min_rank / 10.0)
    
        return ws

    4.3 使用自定义停用词集合

    jieba分词中基于TF-IDF算法抽取关键词以及基于TextRank算法抽取关键词均需要利用停用词对候选词进行过滤。实现TF-IDF算法抽取关键词的类TFIDF和实现TextRank算法抽取关键词的类TextRank都是类KeywordExtractor的子类。而在类KeywordExtractor,实现了一个方法,可以根据用户指定的路径,加载用户提供的停用词集合。

    类KeywordExtractor是在jieba/analyse/tfidf.py中实现。

    类KeywordExtractor首先提供了一个默认的名为STOP_WORDS的停用词集合。

    然后,类KeywordExtractor实现了一个方法set_stop_words,可以根据用户指定的路径,加载用户提供的停用词集合。

    可以将extra_dict/stop_words.txt拷贝出来,并在文件末尾两行分别加入“一个”和
    “每个”这两个词,作为用户提供的停用词文件,使用用户提供的停用词集合进行关键词抽取的实例代码如下,

    from jieba import analyse
    # 引入TF-IDF关键词抽取接口
    tfidf = analyse.extract_tags
    # 使用自定义停用词集合
    analyse.set_stop_words("stop_words.txt")
    
    # 原始文本
    text = "线程是程序执行时的最小单位,它是进程的一个执行流,\
            是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,\
            线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。\
            线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。\
            同样多线程也可以实现并发操作,每个请求分配一个线程来处理。"
    
    # 基于TF-IDF算法进行关键词抽取
    keywords = tfidf(text)
    print "keywords by tfidf:"
    # 输出抽取出的关键词
    for keyword in keywords:
        print keyword + "/",

    关键词结果为,

    keywords by tfidf:
    线程/ CPU/ 进程/ 调度/ 多线程/ 程序执行/ 执行/ 堆栈/ 局部变量/ 单位/ 并发/ 分派/ 共享/ 请求/ 最小/ 可以/ 允许/ 分配/ 多个/ 运行/

    对比章节2.1中的关键词抽取结果,可以发现“一个”和“每个”这两个词没有抽取出来。

    keywords by tfidf:
    线程/ CPU/ 进程/ 调度/ 多线程/ 程序执行/ 每个/ 执行/ 堆栈/ 局部变量/ 单位/ 并发/ 分派/ 一个/ 共享/ 请求/ 最小/ 可以/ 允许/ 分配/ 

    实现原理 ,这里仍然以基于TF-IDF算法抽取关键词为例。

    前面已经介绍了,jieba/analyse/__init__.py主要用于封装jieba分词的关键词抽取接口,在__init__.py首先将类TFIDF实例化为对象default_tfidf,而类TFIDF在初始化时会设置停用词表,我们知道类TFIDF是类KeywordExtractor的子类,而类KeywordExtractor中提供了一个名为STOP_WORDS的停用词集合,因此类TFIDF在初始化时先将类KeywordExtractor中的STOP_WORDS拷贝过来,作为自己的停用词集合stop_words。

    # 实例化TFIDF类
    default_tfidf = TFIDF()
    # 实例化TextRank类
    default_textrank = TextRank()
    
    extract_tags = tfidf = default_tfidf.extract_tags
    set_idf_path = default_tfidf.set_idf_path
    textrank = default_textrank.extract_tags
    
    # 用户设置停用词集合接口
    def set_stop_words(stop_words_path):
        # 更新对象default_tfidf中的停用词集合
        default_tfidf.set_stop_words(stop_words_path)
        # 更新对象default_textrank中的停用词集合
        default_textrank.set_stop_words(stop_words_path)

    如果用户需要使用自己提供的停用词集合,则需要调用analyse.set_stop_words(stop_words_path)这个函数,set_stop_words函数是在类KeywordExtractor实现的。set_stop_words函数执行时,会更新对象default_tfidf中的停用词集合stop_words,当set_stop_words函数执行完毕时,stop_words也就是更新后的停用词集合。我们可以做个实验,验证在调用analyse.set_stop_words(stop_words_path)函数前后,停用词集合是否发生改变。

    from jieba import analyse
    import copy
    
    # 将STOP_WORDS集合深度拷贝出来
    stopwords0 = copy.deepcopy(analyse.default_tfidf.STOP_WORDS)
    # 设置用户自定停用词集合之前,将停用词集合深度拷贝出来  
    stopwords1 = copy.deepcopy(analyse.default_tfidf.stop_words)
    
    print stopwords0 == stopwords1
    print stopwords1 - stopwords0
    
    # 设置用户自定停用词集合
    analyse.set_stop_words("stop_words.txt")
    # 设置用户自定停用词集合之后,将停用词集合深度拷贝出来
    stopwords2 =  copy.deepcopy(analyse.default_tfidf.stop_words)
    
    print stopwords1 == stopwords2
    print stopwords2 - stopwords1

    结果如下所示,

    True
    set([])
    False
    set([u'\u6bcf\u4e2a', u'\u8207', u'\u4e86', u'\u4e00\u500b', u'\u800c', u'\u4ed6\u5011', u'\u6216', u'\u7684', u'\u4e00\u4e2a', u'\u662f', u'\u5c31', u'\u4f60\u5011', u'\u5979\u5011', u'\u6c92\u6709', u'\u57fa\u672c', u'\u59b3\u5011', u'\u53ca', u'\u548c', u'\u8457', u'\u6211\u5011', u'\u662f\u5426', u'\u90fd'])

    说明:

    • 没有加载用户提供的停用词集合之前,停用词集合就是类KeywordExtractor中的STOP_WORDS拷贝过来的;
    • 加载用户提供的停用词集合之后,停用词集合在原有的基础上进行了扩;

    证明了我们的想法。

    5 Reference

    关键词抽取简介

    TF-IDF与余弦相似性的应用(一):自动提取关键词

    TextRank: Bringing Order into Texts

    展开全文
  • 包含百度360PC移动指数、SEM、检索量等VIP数据。做图片网站值得参考。5118图片长尾,50W图片关键词,VIP全部数据
  • 所谓长尾理论,是指当商品储存、流通...长尾关键词是更具体,更长的搜索短语(通常是三个或更多单词),可以清楚地传达搜索者的意图。由于其特殊性,与关键字相比,此类关键字的搜索量较低,但带来了更多的可转换流量。
  • 资源包括最近一段时间亚马逊最火爆的前200名产品关键词,最近好卖的产品是什么关键词
  • 因为长尾关键词的搜索量比较小所以竞争程度相对没有那么激烈,而且长尾理论上有无限个,而这些长尾都有可能给我们的博客网站带来不错的流量,所以作为站长的我们还是有必要了解长尾关键词是什么意思以及如何获取...
  • 以前看新闻大家都是从报纸,电视,新闻网,看资讯一般是从论坛上看,找答案一般是在搜索引擎上。那么现在看新闻、资讯、找问题答案或解决方法的,从今日头条里也占了一大部分了吧。...所以就延伸到今日头条关键词下拉
  • 不懂得实践的学生,就是纸上谈兵。...首先明确,这里说的关键词,是包括我们经常说的长尾的,长尾的挖掘方法,我在自己的个人网站上,已经分享过一篇文章了,有空大家可以去看看,文章标题:...
  • 针对不同的流量来源选择优化的方案,包括关键词的选择、挖掘和排布。  要做SEO优化,首先需要了解网站获取流量的来源。目前网站流量来源主要分为四大块:直接访问、推荐访问、SEO、 APP。在第三块流量来源SEO上...
  •  (4)allowPOS :是否仅包括指定词性的  TextRank基本思想:  (1)分词  (2)找之间共现关系,构建图  (3)计算图中节点的PageRank """ 4、词性标注 import jieba.posseg as pseg words = pseg.cut...
  • 1、此工具目前可以挖掘淘宝下拉框关键词包括你搜一个关键词扩展出来的属性也会包括在内。 2、同时取下拉框关键词搜索后你是不是想找的,只要你下拉框有他都会把挖掘出来的在查询一遍你是不是想找,然后...
  • 之前写了关于精确提取关键词的文章,当时针对的是...同时代码里包含了同义功能 废话不多说,直接撸代码 定义同义分词类如下 package com.daelly.sample.lucene.analyzer.synonyms; import java.io.File; impo
  • 话说上篇文章提到开车之前的准备工作,强调要...直通车提供的关键词,主要来源于宝贝标题中包含,关于标题的优化技巧,大家可以看之前贾真写的两篇文章《淘宝搜索标题优化》(鬼脚七微信中021号文章,回复021可以...
  • 关键词提取

    2018-03-14 15:41:00
    当新来一篇文章时,抽取所有的候选,然后利用训练好的分类器抽取候选,对各个候选进行分类,最终将标签为关键词的候选作为关键词; 2. 无监督学习算法 先抽取候选,然后对各个候选进行打分,...
  • 提取关键词

    2018-07-16 17:23:11
    关键词是一篇文档中表达的主要话题,处理文档或句子时,提取关键词...使用TF-IDF提取关键词的方法十分好理解,TF衡量了一个在文档中出现的频率,一个文档中多次出现的总是有一定的特殊意义,但是并不是所有多次...
  • js 正则 检测包含关键词的句子

    千次阅读 2018-04-23 10:53:12
    可以通过.search(/(关键词1|关键词2|关键词3...)/g),但不能用这种.search(/['关键词1','关键词2','关键词3'...]/g),因为后面这种方式是判断单个字符的,如果用作判断包含多个字符的关键词,则会出问题,可以尝试:...
  • 亚马逊广告是我们卖家日常运营中最常用的推广方式之一,亚马逊卖家众多,广告...有很多卖家概括了一个逻辑,大做广泛匹配、长尾做词组匹配或精准匹配,这是没问题的。  假设你为你的产品设置的竞价关键词是W...
  • 日常SEO优化中,我们每天需要编写大量文章,内容中会多次出现重复性关键词,这是一件蛮正常的事情,很多人用关键词重复来增加关键词的密度,这也是可以理解的,但为什么有人强调,核心关键词最好在文章标题中只出现...
  • 欢迎大家转载本篇文章,但是请附带下面内容放在您转载文章的地方: 【csdn:沧桑亲自测试过】 【沧桑QQ:1316590732】 ... 如果文章的内容对您有所帮助,也非常感谢您的打赏。...长尾关键词的区别是什么? ...
  • 事实上,这两个定义表达了相同的含义,假设你在使用百度,你想通过一个关键词获得信息,那么你输入的所有都可以称为关键词。 图片 关键字可以分为那几个类型? 属性关键字 促销关键字 品牌关键字 评鉴关键字 属性...
  • 如果网页中包含某些关键词(关键列表在keyword.txt文件里,逗号分隔)则弹出提示框显示“该网页禁止访问”,以拦截当前的访问。
  • 目录: 第一篇:综述 第二篇:数据集、实现代码介绍 第三篇:特征设计 第四篇:候选生成(上) ...大多数候选生成方法都是使用启发式规则从文本中直接生成候选,注意到关键词内部不会包含其他关键词,从...
  • 本文大纲如下:拓展和筛选网站主词挖掘搜索引擎推荐关键词业务相关的挖掘同行关键词的挖掘关键词组合拓展1、拓展和筛选网站主关键词网站能支持的主推关键词的数量有限,所以我们精心挑选。step1:根据对一个行业的...
  • 网站关键词布局怎么理解关键词对于一个网站很重要 首页常用来优化网站的热门主 关键词 栏目页用来优化主关键词的拓展 该怎么分析关键词布局呢请看下文详细介绍 网站的结构通常包括首页栏目页和内容页搜索引擎在...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 62,320
精华内容 24,928
关键字:

关键词包括哪些词