问题:
某天朋友咨询我一个问题,她手上有一些政府文件,需要找出这些文件里出现频率最高的关键词,取TOP50,做成词云图展示(类似于下图,频率越高越醒目)。
思路:
1、提取出每个文件的内容
2、找出每个有意义的词,并统计出每个词出现的次数
3、取次数最高的50个词,做成词云图
1和3还好说,总有办法可以做到。WORD文档可直接复制出来,PDF文档也有办法把文字提取出来,有了关键词和对应的次数,直接可以用可视化工具(比如FineBI)做出词云图。关键是第2步如何实现。
联想到Oracle全文索引的原理:Oracle词法分析器(lexer)将所有的表意单元(term)找出来,记录在一组以dr开头的表里,同时记录该表意单元出现的位置、次数、hash值等……而且专门有一个汉语分析器,可以分析出汉语的表意单元(比如“我们都是中国人”,它可以分析出“中国人”是一个表意单元,“是中”则不是)。那么,如果我们能查到dr开头的这组表,第2步就解决了。
试验:
Step1:构建环境
-- 建全文索引的详细语法可以网上搜索
-- 1、建表,插入文字
CREATE TABLE T_KEY_WORD
(
STR VARCHAR2(1000)
);
INSERT INTO T_KEY_WORD VALUES('中国人民站起来了,环保,绿色健康的食品。');
INSERT INTO T_KEY_WORD VALUES('中国、美国、日本,是世界上经济比较发达的国家。');
INSERT INTO T_KEY_WORD VALUES('环保是当今世界的主题之一。');
INSERT INTO T_KEY_WORD VALUES('2023年经济不太景气。');
COMMIT ;
-- 2、用其他工号赋予权限
GRANT CTXAPP TO REGULATORY_1;
GRANT EXECUTE ON CTX_DDL TO REGULATORY_1;
-- 3、建分析器
Begin
-- ctx_ddl.drop_preference('club_lexer') ;
-- ctx_ddl.drop_preference('mywordlist') ;
ctx_ddl.create_preference('club_lexer','CHINESE_LEXER') ;
ctx_ddl.create_preference('mywordlist','BASIC_WORDLIST') ;
ctx_ddl.set_attribute('mywordlist','PREFIX_INDEX','TRUE') ;
ctx_ddl.set_attribute('mywordlist','PREFIX_MIN_LENGTH',1) ;
ctx_ddl.set_attribute('mywordlist','PREFIX_MAX_LENGTH',5) ;
ctx_ddl.set_attribute('mywordlist','SUBSTRING_INDEX','YES') ;
end;
/
Step2:建全文索引
-- 建索引
create index IDX2_T_KEY_WORD on T_KEY_WORD(STR)
indextype is ctxsys.context
parameters (
'DATASTORE CTXSYS.DIRECT_DATASTORE FILTER CTXSYS.NULL_FILTER LEXER club_lexer WORDLIST mywordlist'
);
Step3:查看dr开头的表
SELECT * FROM DR$IDX_T_KEY_WORD2$I ;
Step4:按出现次数降序排序,并剔除掉无意义的词,取TOP50
-- 一些无意义的次,比如的、是、了等等,需手工剔除
SELECT * FROM DR$IDX2_T_KEY_WORD$I WHERE TOKEN_TYPE='0' ORDER BY TOKEN_COUNT DESC;
注意:
TOKEN_COUNT,是指该词出现的记录数(行数:一个文档对应一行记录),如果某行记录里出现了N次,只会+1。所以此方法的关键词出现的次数,一个文档最多统计一次。如果想在同一个文档里,出现N次,次数就+N,需要再处理一下(比如遍历这些词,依次替换掉关键词为空,字段前后长度差/关键词的长度,就是一行记录里关键词出现的次数)。