博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
通过盘古分词自定义规则功能实现软件版本号的提取
阅读量:6934 次
发布时间:2019-06-27

本文共 4728 字,大约阅读时间需要 15 分钟。

作者:eaglet

在某些软件下载网站的全文搜索应用中往往需要根据部分或者全部的版本号来匹配查询。然而对于版本信息的提取,无论是采用增加单词还是其他什么办法都无法很好的实现。好在盘古分词提供了自定义规则的接口,我们可以通过实现自己的自定义规则来完成一些特殊信息的提取。这篇文章也作为盘古分词自定义规则使用的一个示例文章,希望大家看了这篇文章后可以举一反三,实现诸如IP地址提取,Email 提取,网址提取等等特殊提取功能的自定义规则。

首先先说一下需求。

我们希望将版本信息字符串 比如 V1.2.1.0 从文章中提取出来,分词为 v/1.2.1.0/1.2.1/1.2 这种形式,这样无论搜索用户输入 1.2.1.0 还是1.2 或者 v 1.2.1 都可以匹配到相应的结果。

下面我来谈谈如何来完成这个功能。

首先 我们需要将盘古分词版本升级到 V2.3.1.0 或以上版本。

第二 我们需要将英文多元分词开关打开,打开方法是在 Pangu.xml 中做如下设置:

true

接下来 我们要实现自定义规则接口,其接口定义如下:

///     /// 用户自定义规则接口    ///     public interface ICustomRule    {        string Text {get; set;}        void AfterSegment(SuperLinkedList
result); }

其中

Text 为输入给分词器的原始字符串,盘古分词会将这个原始字符串带入到接口中。

AfterSegement 函数在盘古分词完成了分词工作后调用,输入的参数是分词的结果,这个结果以链表形势展现。

 

下面看提取版本号的接口实现,实现方法是遍历整个分词结果,发现单词分量为v 或者 V 时,就假设为版本号的开始,然后判断后面是否出现数字,如果出现数字

且位置和V靠的很近,则认为是版本号信息,进入提取版本号的状态。提取完后,删除中间的一些不必要的单词分量,然后将版本号的单词分量加入到v 这个单词后面。

具体可以看代码。代码也可以在 中下载,下载位置:主页中的 Download 页面 PanGu_SourceCode_V2.3.1.0.zip 这个文件。

PickupVersion.cs 这个文件在 Example\CustomRuleExample 这个目录下。

 

实现了这个接口后,我们编译成一个动态库,这里假设为 CustomRuleExample.dll

最后 我们需要将这个动态库拷贝到和PanGu.dll 相同的目录中,然后修改 PanGu.xml 配置文件,打开自定义规则开关,方法如下:

在 MatchOption 中将 CustomRule 这个开关设置为 true

....
true

 

 
在 Parameters 中设置自定义程序集的文件名和类名
....
CustomRuleExample.dll
CustomRuleExample.PickupVersion

 

这些全部做完后,一个版本号提取的自定义规则就完成了。下面让我们看看分词结果

 

当然这个只是一个例子,不可能考虑所有的情况。比如在实际应用中,可能版本号不是以 v 起始,这个没有关系,因为盘古分词已经通过接口把所有信息都给了出来,大家可以根据这个例子举一反三,编写适合于自己应用的自定义规则程序。

 

PickupVersion 类的源码如下:

 

using System;
using System.Collections.Generic;
using System.Text;
using PanGu;
 
namespace CustomRuleExample
{
/// 
/// 这个规则用于将文章中的版本号单独提出来
/// V1.2.3.4 分词结果为
/// v/1.2/1.2.3/1.2.3.4
/// 这个规则要工作正常,需要将 EnglishMultiDimensionality 开关打开
/// 
public class PickupVersion : ICustomRule
{
private string _Text;
 
#region ICustomRule Members
 
public string Text
{
get
{
return _Text;
}
set
{
_Text = value;
}
}
 
/// 
/// 提取版本号
/// 
/// 盘古分词的结果
/// V 这个字符的第一个出现位置
/// 版本号的最后一个词
/// 版本号第一个词的起始位置
private void Pickup(SuperLinkedList
result, SuperLinkedListNode
vWordNode,
SuperLinkedListNode
lastNode, int versionBeginPosition)
{
SuperLinkedListNode
node = vWordNode.Next;
int lastPosition = lastNode.Value.Position + lastNode.Value.Word.Length;
 
SuperLinkedListNode
end = lastNode.Next;
 
while (node != end)
{
result.Remove(node);
node = vWordNode.Next;
}
 
if (vWordNode.Value.Word == "V")
{
vWordNode.Value.Word = "v";
}
 
string version = _Text.Substring(versionBeginPosition, lastPosition - versionBeginPosition);
 
int dotPosition = 0;
int dotCount = 0;
 
WordInfo verWord = null;
dotPosition = version.IndexOf('.', dotPosition);
 
while (dotPosition > 0)
{
verWord = null;
 
if (dotCount > 0) //第一个点之前的版本号不提取
{
//提取前n个子版本号
verWord = new WordInfo(version.Substring(0, dotPosition), POS.POS_D_K, 0);
verWord.Rank = 1; //这里设置子版本号的权重
verWord.Position = versionBeginPosition;
verWord.WordType = WordType.None;
}
 
dotCount++;
 
dotPosition = version.IndexOf('.', dotPosition + 1);
 
if (verWord != null)
{
result.AddAfter(vWordNode, verWord);
}
}
 
//提取完整版本号
verWord = new WordInfo(version, POS.POS_D_K, 0);
verWord.Rank = 5; //这里设置完整版本号的权重
verWord.Position = versionBeginPosition;
verWord.WordType = WordType.None;
result.AddAfter(vWordNode, verWord);
 
}
 
public void AfterSegment(SuperLinkedList
result)
{
SuperLinkedListNode
node = result.First;
 
SuperLinkedListNode
vWordNode = null;
SuperLinkedListNode
lastNode = null;
bool isVersion = false;
int versionBeginPosition = -1;
 
while (node != null)
{
if (vWordNode == null)
{
if (node.Value.WordType == WordType.English)
{
//匹配 V 这个字符,作为版本号的开始
if (node.Value.Word.Length == 1)
{
if (node.Value.Word[0] == 'v' || node.Value.Word[0] == 'V')
{
vWordNode = node;
lastNode = node;
}
}
}
}
else if (vWordNode != null)
{
//如果V有多元分词情况,忽略,跳到下一个
if (node.Value.Position == vWordNode.Value.Position)
{
node = node.Next;
continue;
}
 
//匹配数字或点
if (node.Value.WordType == WordType.Numeric ||
node.Value.Word == ".")
{
if (node.Value.Position - (lastNode.Value.Position + lastNode.Value.Word.Length) <= 1)
{
if (versionBeginPosition < 0)
{
versionBeginPosition = node.Value.Position;
}
 
isVersion = true;
lastNode = node;
 
node = node.Next;
continue;
}
}
 
if (isVersion)
{
//如果是版本号,提取版本号
Pickup(result, vWordNode, lastNode, versionBeginPosition);
vWordNode = null;
lastNode = null;
versionBeginPosition = -1;
isVersion = false;
continue;
}
}
 
node = node.Next;
}
 
if (isVersion)
{
//如果是版本号,提取版本号
Pickup(result, vWordNode, lastNode, versionBeginPosition);
}
}
 
#endregion
 
}
}

转载地址:http://pkwnl.baihongyu.com/

你可能感兴趣的文章
Oracle快速克隆安装
查看>>
Spring Boot中使用JdbcTemplate访问数据库
查看>>
struts2的核心和工作原理
查看>>
一种快速统计SQL Server每个表行数的方法
查看>>
(zhuan) How to Train Neural Networks With Backpropagation
查看>>
MHA快速搭建
查看>>
看过的编程类好书(资料)
查看>>
BZOJ 4517: [Sdoi2016]排列计数 [容斥原理]
查看>>
抽水算法
查看>>
.net 中struct(结构)和class(类)的区别
查看>>
Unity3D的坑系列:动态加载dll
查看>>
从JSON数据中取出相关数据
查看>>
Quartz安装包中的15个example
查看>>
12C -- DDL日志
查看>>
消息总线VS消息队列
查看>>
Eclipse SDK构建J2EE开发环境
查看>>
入门基础
查看>>
object dection资源
查看>>
Swift标识符和keyword
查看>>
【树莓派】【转载】基于树莓派,制作家庭媒体中心+下载机
查看>>