公司有个需求,就是需要提供给echart词云图的数据,放在以前我们的数据来源都是从产品那直接要,产品也是跑的别的接口,那怎么行呢,当然有自己的一套可以随便搞了,那么操作来了
Java
package cn.iocoder.yudao.module.nlp.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* @author: hyj
* @createDate: 2023/04/26
* @description: 词频提取 json(给词云图用)
*/
@Component
public class WordFrequencyUtil {
private static final WordFrequencyUtil staticInstance = new WordFrequencyUtil();
@Value("${python.path}")
private String path;
// private String path = "E:/LanZhou/manage_api/nlp/nlp-biz/src/main/resources/static/python/";
/**
* @param content: 文本
* @return: 词云图json对象的string
*/
public static String extraction(String content) {
String result;
try {
result = RunPyUtils.runCmd3(staticInstance.path + "wordFrequency.py", content, staticInstance.path);
} catch (Exception e) {
result = "error";
}
return result;
}
/**
* 测试的时候把什么注解path换一下
*/
public static void main(String[] args) {
String content = "这几天,法国、西方乃至中国的部分媒体,围绕着中国驻法国大使卢沙野在法国LCI电视台专题节目中所阐述的一些观点展开了激烈辩论。支持者为卢大使鼓掌,认为我们应该勇于在国际舞台上应对挑战发声,但也有一些观点认为外媒向来对中国不怀好意,我们在和他们打交道时不能顺着人家的“坑”跳。\n" +
"因为我在法国担任常驻记者的时候,就经常应邀参加法国电视台、电台的辩论节目,因此对孤身一人、舌战群魔的艰难处境深有体会。我非常深切地感受到,尽管我们明知道其中会有很多陷阱、阴谋、困难,但我们也一定要敢于、勇于、善于参与这类活动;因为只有跻身其中、仗义直言,才有可能有朝一日打破这类陷阱,将我们的话语权真正地夺回来,把我们的声音真正地传播出去,传向全世界。\n" +
"所以,我对卢沙野大使勇于应邀前往法国电视台发声、在明显充满敌意的环境中敢于发声,执百分之百支持的态度!我要高呼:Bravo!Monsieurl'Ambassadeur!(棒极了!大使先生!)\n" +
"西方媒体与我们中国媒体在这类电视辩论节目中,从目的、形式到效果,可以说都是南辕北辙、截然相反的。我曾担任过中国中央电视台法语频道专题节目《On ne vous dit pas tout》的主持人;也在福建省电视台东南卫视《中国正在说》专题节目中担任主持人。\n" +
"我在法国时,也应邀参加过法国主流电视台“LCI”“France5”、国家电视台“法兰西电视二台”,24小时连续新闻台“BFM TV”“CNEWS”、以及法国对外电视台“France 24”等各大电视台的辩论节目。我甚至成为法国国家“世界5台(TV5 Monde)”的常邀嘉宾,非常有规律地参加其电视辩论节目。因此我对双方新闻节目、特别是电视辩论节目的制作过程、方式方法,以及从手段到目的等各个环节都非常了解。\n" +
"仅就新闻和辩论节目的目的而言,中法媒体就是不一样的。\n" +
"我在中央电视台法语频道担任主持人时,我的节目经常邀请法国人来参加辩论。我们的新闻出发点是非常明确的,那就是阐述事实、表明观点、消除误会、增进彼此的了解和理解。\n" +
"以我采访阿尔斯通前高管、《美国陷阱》一书的作者皮耶鲁齐(Frédéric Pierucci)为例。我们采访他的目的,一是要他本人亲自来阐述他在美国的遭遇;二是介绍他的《美国陷阱》中文版;三是表明我们对他的正义事业的支持。在采访前,我就把采访提纲完整地发给他,让他能够事先有充分的准备;而我在整个采访过程中基本就是按提纲上的问题来询问他。当然,当他的回答能够给我新的提问动机时,我也会进一步深入下去。但总体上而言,我们的目的是共同的、一致的。\n" +
"皮耶鲁齐在采访结束后与我愉快地交谈时说,我知道中国新闻媒体是非常严肃、认真的,今天果然如此,我几乎是畅所欲言,完全吐露了我想说的一切。当我们从中国观众的角度出发,我们就可以看到,有关皮耶鲁齐的几乎一切经历、遭遇,我们都了解到了。观众也更理解他在《美国陷阱》一书中阐述的观点。对于我和央视而言,如果美国司法当局也想接受我们的采访来解释一下美国为什么要逮捕皮耶鲁齐的话,我们也同样会给他们类似的发言权。这样,中国观众便能够更为客观地了解到了整个事件的来龙去脉。";
String result = extraction(content);
JSONArray json = JSON.parseArray(result);
for (int i = 0; i < json.size(); i++) {
JSONObject jb = json.getJSONObject(i);
System.out.println(jb);
}
}
@PostConstruct
public void init() {
staticInstance.path = path;
}
}
java直接写的工具,因为这个目前还没让我写接口模式,后续可能需要同事多人调用并且他们搞对外接口,所以我临时这么写测试一下
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* @Description: 调用制定Python方法的工具类
* @Date: 2023/2/11
* @author: TCZ
*/
public class RunPyUtils {
/**
* @param path python文件路径
* @param value1 python脚本参数
* @param value2 python脚本参数
*/
public static String runCmd3(String path, String value1, String value2) throws Exception {
String system = System.getProperty("os.name");
BufferedReader br = null;
try {
String[] args = new String[]{system.contains("Windows") ? "python" : "python3", path, value1, value2};//第二个为python脚本所在位置,后面的为所传参数(得是字符串类型)
Process proc = Runtime.getRuntime().exec(args);
br = new BufferedReader(new InputStreamReader(proc.getInputStream(), system.contains("Windows") ? "gb2312" : "utf-8"));
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
System.out.println(proc.waitFor() != 0 ? "脚本执行失败" : "脚本执行成功");
InputStream errorStream = proc.getErrorStream();
BufferedReader error = new BufferedReader(new InputStreamReader(errorStream, "gbk"));
String lineError;
while ((lineError = error.readLine()) != null) {
System.out.println("----------------------------------------------------失败原因为:" + lineError);
}
error.close();
return sb.toString();
} finally {
if (br != null) {
try {
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
这个java调用python的方法网上写法都是一样的,不描述了
Python
from collections import Counter
from paddlenlp import Taskflow
import sys
# 处理文本提取关键词和词频
# 从java来源接参数
text = sys.argv[1]
# 数据清理(分词和去掉停用词)
def clearWord(content):
# 分词
seg1 = Taskflow("word_segmentation", mode="accurate")
seg_list = seg1(content)
# 读取停用词
with open(sys.argv[2] + 'StopWord.txt', encoding="utf-8") as f:
stopwords = f.read()
new_text = []
# 去掉停用词
for w in seg_list:
if w not in stopwords:
if len(w) > 1:
new_text.append(w)
return new_text
# 数据整理(统计词频)
def statisticalData(text):
# 统计每个词的词频
counter = Counter(text)
# 输出词频最高的15个单词
return counter.most_common(100)
A = clearWord(text)
B = statisticalData(A)
resultList = []
for item in B:
result = {"name": item[0], "value": item[1]}
resultList.append(result)
print(resultList)
这里有个非常重要的步骤就是清理停用词,什么是停用词?就是我们文章中什么逗号了句号了,或者是啊、呵、哈这种语气词等等等对于我们要提取词频的词做不到关键性作用的,我们不需要提取,需要把他们清除掉
这里面使用的停用词来源
最全中文停用词表整理(1893个)
新建文件StopWord.txt放入数据
后面再利用python拼接返回数据name-value的json对象数组格式,因为这个格式需要echart的词云图使用
注意,我们python分词利用的paddlenlp包做分词处理,所以在此之前需要安装padllenlp环境和下载分词的模型包,至于怎么下载,只需要用python运行一下分词模型,就会自动下载
paddleNlp安装使用
https://github.com/PaddlePaddle/PaddleNLP
paddleNlp所有功能
https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/model_zoo/taskflow.md