实际问题
目的
做一个成语小程序,实现类似下面的页面接口。选择对应的正确成语的字。
成语库
没自己的成语库,最后选择去网上扒拉(py爬虫),解决第一个问题。(脚本我会放到最后面打包)
字典库
需要随机抽取一个字,然后生成4个相近的字符。 这里我没找到合适可以巴拉的数据,且还要去找形近字。
解决方案
使用nlp-hanzi-similar三方包,里面包含了一定(目前我使用来说形近字至少存在空缺)的文字库,但是也基本够用 (直接节省时间)。
这里是三方开源的项目,感谢作者
使用三方包
引入maven:
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>nlp-hanzi-similar</artifactId>
<version>1.4.0</version>
</dependency>
没有使用maven的,我会后面将jar包和代码打包上传
大概看一下说明,根据自己情况设置参数即可:
double rate = HanziSimilarBs.newInstance()
// 笔画数数据
.bihuashuData(HanziSimilarDatas.bihuashu())
// 笔画数相似算法
.bihuashuSimilar(HanziSimilars.bihuashu())
// 笔画数权重
.bihuashuRate(HanziSimilarRateConst.BIAHUASHU)
// 结构数据
.jiegouData(HanziSimilarDatas.jiegou())
// 结构相似算法
.jiegouSimilar(HanziSimilars.jiegou())
// 结构权重
.jiegouRate(HanziSimilarRateConst.JIEGOU)
// 部首数据
.bushouData(HanziSimilarDatas.bushou())
// 部首相似算法
.bushouSimilar(HanziSimilars.bushou())
// 部首权重
.bushouRate(HanziSimilarRateConst.BUSHOU)
// 四角数据
.sijiaoData(HanziSimilarDatas.sijiao())
// 四角相似算法
.sijiaoSimilar(HanziSimilars.sijiao())
// 四角权重
.sijiaoRate(HanziSimilarRateConst.SIJIAO)
// 拼音权重
.pinyinRate(HanziSimilarRateConst.PINYIN)
// 拼音相似算法
.pinyinSimilar(HanziSimilars.pinyin())
// 拆字权重
.chaiziRate(HanziSimilarRateConst.CHAIZI)
// 拆字相似算法
.chaiziSimilar(HanziSimilars.chaizi())
// 初始化
.init()
// 执行文本相似度对比
.similar('末', '未');
注入Spring项目
IdiomConjectureHandler是我的成语处理器,处理器才是具体实现
@Configuration
public class IdiomConfig {
@Bean
public HanziSimilarBs getHanziSimilarBs() {
HanziSimilarBs similarBs = HanziSimilarBs.newInstance()
// 笔画数数据
.bihuashuData(HanziSimilarDatas.bihuashu())
// 笔画数相似算法
.bihuashuSimilar(HanziSimilars.bihuashu())
// 笔画数权重
.bihuashuRate(HanziSimilarRateConst.BIAHUASHU)
// 结构数据
.jiegouData(HanziSimilarDatas.jiegou())
// 结构相似算法
.jiegouSimilar(HanziSimilars.jiegou())
// 结构权重
.jiegouRate(HanziSimilarRateConst.BIAHUASHU)
// 部首数据
.bushouData(HanziSimilarDatas.bushou())
// 部首相似算法
.bushouSimilar(HanziSimilars.bushou())
// 部首权重
.bushouRate(HanziSimilarRateConst.BIAHUASHU)
// 四角数据
.sijiaoData(HanziSimilarDatas.sijiao())
// 四角相似算法
.sijiaoSimilar(HanziSimilars.sijiao())
// 四角权重
.sijiaoRate(HanziSimilarRateConst.BIAHUASHU)
// 拼音权重
.pinyinRate(HanziSimilarRateConst.JIEGOU)
// 拼音相似算法
.pinyinSimilar(HanziSimilars.pinyin())
// 拆字权重
.chaiziRate(HanziSimilarRateConst.BIAHUASHU)
// 拆字相似算法
.chaiziSimilar(HanziSimilars.chaizi())
// 初始化
.init();
return similarBs;
}
@Bean
@ConditionalOnMissingBean(value = IdiomConjectureHandler.class)
public IdiomConjectureHandler getIdiomConjectureHandler() {
return new IdiomConjectureDefaultHandler();
}
成语处理器实现
IdiomConjecture实体类
public class IdiomConjecture {
/**
* 成语
*/
private String idiom;
/**
* 猜测字符
*/
private String conjecture;
/**
* 结果字符,替换猜测字符为*
*/
private String result;
/**
* 正确答案
*/
private String correct;
/**
* 相近字符
*/
private List<String> nearConjecture;
...
}
@Service
public class IdiomConjectureDefaultHandler implements IdiomConjectureHandler {
@Autowired
private HanziSimilarBs hanziSimilarBs;
@Override
public IdiomConjecture idiomConjecture(String idiom) {
int randomInt = RandomUtil.randomInt(0, idiom.length() - 1);
String sub = StrUtil.sub(idiom, randomInt, randomInt + 1);
String replace = StrUtil.replace(idiom, sub, "?");
char c = sub.charAt(0);
List<String> list = hanziSimilarBs.similarList(c, 3);
IdiomConjecture idiomConjecture = new IdiomConjecture();
idiomConjecture.setIdiom(idiom);
idiomConjecture.setConjecture(replace);
idiomConjecture.setCorrect(sub);
List<String> conjecture = CollectionUtils.isEmpty(list) ? generateRandomChineseCharacters(3) : list;
conjecture.add(sub);
idiomConjecture.setNearConjecture(conjecture);
idiomConjecture.setResult(replace);
return idiomConjecture;
}
public static List<String> generateRandomChineseCharacters(int count) {
List<String> chineseChars = new ArrayList<>(count);
Random random = new Random();
for (int i = 0; i < count; i++) {
// 生成随机的中文字符Unicode编码
int codePoint = random.nextInt(0x9fa5 - 0x4e00 + 1) + 0x4e00;
// 将编码转换为字符,并添加到列表中
chineseChars.add(new String(Character.toChars(codePoint)));
}
return chineseChars;
}
}
提别说明:generateRandomChineseCharacters方法,从unicode编码中随机取出count个汉字。 因为在nlp库中 存在形近字不够无法满足足够多的汉字,所以随机取出汉字补够字数。
接口返回数据
{
"msg": "操作成功",
"code": 200,
"data": [
{
"id": 1646,
"idiom": "?台高筑",
"pinyin": "zhài tái gāo zhù",
"correct": null,
"answers": [
"侇",
"債",
"渍",
"债"
],
"answer": false
},
{
"id": 1544,
"idiom": "后生?畏",
"pinyin": "hòu shēng kě wèi",
"correct": null,
"answers": [
"司",
"句",
"戓",
"可"
],
"answer": false
}
}
目前来看效果还是可以
代码打包
想做到很好,建议还是维护一个本地库,但是成本很高。