因为过滤关键字机制到处可见,于是聪明的网友就会想到各种各样的方法突破,例如:
1、中文会用繁体字的方法避开关键字扫描
2、在关键字中间插入无意思的特殊字符,例如 * & # @ 等,而且个数可变
3、使用谐音或拆字法变换关键字
在实现自己的算法时也有些问题:
4、随着时间推移,关键字列表会越来越大,有些论坛常用的正则表达式N次扫描的方法显得效率很低。
5、关键字有不同的严重级别,有些需要禁止,有些只需要替换,还有一些可能记录一下即可。
针对这些问题,可采用的应对方法:
1、加载关键字列表时,将所有的关键字转换成繁体字一份,以扫描繁体版的关键字;
这个转换工作只需一句就可以实现了:
s=Microsoft.VisualBasic.Strings.StrConv(word, Microsoft.VisualBasic.VbStrConv.TraditionalChinese, 0);
2、在扫描原文本时,如果遇到关键字的首个文字,忽略其后的特殊字符,直到下一个有意义的文字为止,当然这里需要在定义关键字列表时指定哪些才需要这样扫描,并不是所有关键字都采用这种方式;
例如有关键字 “你好”经常会被人输入成“你x好”或者“你xxxxx好”,那么在关键字列表里就需要定义成“你*好”,在匹配关键字时,如果遇到星号就忽略原文本下一个为特殊的字符。
3、遇到谐音和拆字时,没什么好办法了,只好将这些谐音词和拆分词也加入到关键字列表。
4、不用正则表达式或者 String.IndexOf方法,可以将所有关键字的首字相同的组成一个一个小组,然后在将首字放到一个散列表(HashTable/Dictionary<T>),在扫描原文本时先在散列表里扫描,如果碰到了首字再扫描同组的关键字,这样简单处理一下效率可以提高很多。
还有一个比用散列表更好的方法,将散列表改成一个大小为char.MaxValue的数组,然后将首个文字转成int,即char->int,然后将关键词集合放到相应下标里。这样在扫描原文本时,将被扫描的字符转成int,然后试探数组相应下标的元素是否不为NULL。这样比用散列表会更快一些。
5、在定义关键字时,同时给一个“级别”属性,例如使用 E,R,B分别表示只记录、替换、禁止等情况。
于是关键字的列表如下所示:
你滚 E
他niang的 R
成*人*网*站 B
这里贴一下关键的部分代码:
Code
private WordGroup[] _wordTable;
public FilterResult Filter(ref string source,char replaceChar)
{
//NOTE::
// 如果方法返回 FilterResult.Replace或者FilterResult.Banned,则原字符串的某些字会被替代为星号,替代后的字符串可以由source取得
if (String.IsNullOrEmpty(source)) return FilterResult.Pass;
FilterResult result = FilterResult.Pass;
char[] tempString = null;
int start = 0;
for (; start < source.Length; start++)
{
WordGroup fw = _wordTable[fastToLower(source[start])];
if (fw != null)
{
for (int idx = 0; idx < fw.Count; idx++)
{
WordEntity we = fw.GetItem(idx);
int matchLength=0;
if (we.Word.Length==0 || checkString(source, we.Word, start + 1, out matchLength))
{
FilterResult fr = we.HandleType;
if (fr > result) result = fr; //记录最高级别的处理方法
if (fr == FilterResult.Replace || fr == FilterResult.Banned)
{
//替换关键字
if(tempString==null) tempString =source.ToCharArray();;
for (int pos = 0; pos < matchLength + 1; pos++)
{
tempString[pos + start] = replaceChar;
}
}
}
}
}
}
if (result > FilterResult.RecordOnly)
{
source = new string(tempString);
}
return result;
}
private bool checkString(string source, string keyword, int sourceStart, out int matchLength)
{
bool found = false;
int sourceOffset = 0;
int keyIndex = 0;
for (; keyIndex < keyword.Length; keyIndex++)
{
if (sourceOffset + sourceStart >= source.Length) break; //原始字符串已经全部搜索完毕
if (keyword[keyIndex] == '*')
{
//跳过可忽略的字符
while (sourceOffset + sourceStart < source.Length)
{
if (isIgnorableCharacter_CN(source[sourceOffset + sourceStart]))
sourceOffset++;
else
break;
}
}
else
{
//比较字母
if (fastToLower(source[sourceOffset + sourceStart]) == (int)keyword[keyIndex])
{
if (keyIndex == keyword.Length - 1)
{
found = true;
break;
}
}
else
{
break;
}
sourceOffset++;//移动原始字符串
}
}
//如果匹配中关键字,则返回原字符串中被匹配中的文字的长度,否则返回0
matchLength = sourceOffset + 1;
return found;
}
private int fastToLower(char character)
{
//将大写英文字母以及全/半角的英文字母转化为小写字母
int charVal = (int)character;
if (charVal <= 90)
{
if (charVal >= 65) //字母A-Z
return charVal - 65 + 97;
}
else if (charVal >= 65313)
{
if (charVal <= 65338)
return charVal - 65313 + 97; //全角大写A-Z
else if (charVal >= 65345 && charVal <= 65370)
return charVal - 65345 + 97; //全角小写a-z
}
return charVal;
}
private bool isIgnorableCharacter_CN(char character)
{
//NOTE::
// 中文表意字符的范围 4E00-9FA5
int charVal = (int)character;
return !(charVal >= 0x4e00 && charVal <= 0x9fa5);
}
// 单个过滤词条目
class WordEntity
{
public string Word { get; set; }
public FilterResult HandleType { get; set; }
}
// 过滤词的组
class WordGroup
{
//NOTE::用于装载一组具有同一个字开头的过滤词
private List<WordEntity> _words;
public WordGroup()
{
_words = new List<WordEntity>();
}
public void AppendWord(string word, FilterResult handleType)
{
AppendWord(new WordEntity() { Word = word, HandleType = handleType });
}
public void AppendWord(WordEntity word)
{
_words.Add(word);
}
public int Count
{
get { return _words.Count; }
}
public WordEntity GetItem(int index)
{
return _words[index];
}
}
分享到:
相关推荐
文档描写的是一个关于关键字过滤的算法,跟其他过滤算法不同的是该算法是中英文混合过滤算法
关键字过滤多模式匹配算法(支持中文),支持从文件中读取样本数据以及字典数据,文件附带中英文测试文件和中英文关键字字典可供测试,亲测效率还行
最近项目中要用到关键字过滤,就参考网上的算法自己写了个关键字过滤的java代码,思路如下: 将关键词的第1个字作为hashMap的索引,第2个字放到另一个hashMap中,并让第1个字的索引指向这个hashMap 过滤关键字的...
通过关键字文本 构建关键字库 利用算法实现过滤 所有效率很快
用多叉树实现的查找算法,速度达到 80~90Mb/s。详见博客 http://blog.csdn.net/W_SX12553/article/details/78652736
使用类别和关键字进行个性化推荐:可扩展的协作过滤算法
新一代智能双向高速过滤系统,网监王WJW110运行在IIS高效的内核层,采用独有的高速过滤算法,可保证在不影响网站运行效率的前提下实现不良信息的准确过滤和记录,网监王WJW110可对各种静态页面和动态页面实现完整...
基于协同过滤算法的个性化推荐系统 一、研究目的 基于协同过滤算法的个性化新闻推荐系统能够根据对用户在网站内的操作记录的分析,为用户推荐可能喜欢的新闻内容。另外,该系统还实现了新闻的新增、改、查、删操作...
基于协同过滤算法的个性化推荐系统【毕业设计源码+论文】 1、研究目的 基于协同过滤算法的个性化新闻推荐系统能够根据对用户在网站内的操作记录的分析,为用户推荐可能喜欢的新闻内容。另外,该系统还实现了新闻的...
关键字过滤多模式匹配算法(支持中文),支持从文件中读取样本数据以及字典数据,文件附带中英文测试文件和中英文关键字字典可供测试
Java中的关键字提取服务器化关键字提取算法的实现,包括TextRank,TF-IDF,TextRank和TFTF-IDF。切割词和过滤停用词均依赖 该存储库主要包括三个部分: 1.算法:用于服务器执行关键词提取的算法,包括TextRank,TF-...
1、可以自动搜索代理服务器,验证代理服务器,过滤出国内的IP地址,使用者不需要在去找代理服务器了; 2、可以导入外部代理服务器,并验证; 3、可以选择不同的网卡来做优化; 4、可以在优化时候动态修改本地网卡...
基于自动机的多模式匹配算法是网络内容过滤与业务监管的核心技术之一, 但随着模式集合的扩大, 对存储资源消耗过大。为降低当前匹配算法的空间复杂度, 同时保持较低的时间复杂度, 提出了一种基于关键字预处理和状态...
在介绍词频和倒文档频度的基础上,对几种常用的特征选择算法进行了分析和比较,针对现有特征选择算法过于机械的缺点,将关键字权重引入到邮件分类中,提出了一种基于关键词权重的TF*IDF特征选择改进算法,并进行了...
给出了一个多Agent松散耦合的网格服务发现框架。在该框架中把Agent分为三类:服务Agent、需求Agent和服务发现...最后基于本体论给出了一个支持部分匹配的服务匹配算法,并用一个车辆维修服务系统的例子进行了说明。
随后,文章介绍了云存储的基本概念及其安全需求,同时介绍了密文检索的相关算法,并主要针对盲存储算法做出了详细的阐述。然后,介绍了基于属性的加密算法,包括CP-ABE和MA-ABE,并分析了其中...
wm c算法实现。WM算法采用字符块技术,增大了主串和模式串不匹配的可能性.从而增加了直接跳跃的机会:它...在现有的多关键字匹配算法中,使用块字符、Hash技术和前缀特征表技术的WM算法通常被认为具有最高的效率。.rar
wm c算法实现。WM算法采用字符块技术,增大了主串和模式串不匹配的可能性.从而增加了直接跳跃的机会:它...在现有的多关键字匹配算法中,使用块字符、Hash技术和前缀特征表技术的WM算法通常被认为具有最高的效率。.zip
wm c算法实现。WM算法采用字符块技术,增大了主串和模式串不匹配的可能性.从而增加了直接跳跃的机会:它...在现有的多关键字匹配算法中,使用块字符、Hash技术和前缀特征表技术的WM算法通常被认为具有最高的效率。.zip
EBA(early-stopping blocking algorithm)算法.EBA 在BA 基础上引入了过滤域值,以便尽早终止算法的迭代次数.最 后实验结果显示语义评分函数保证了搜索结果的高查准率和查全率,所提出的BA 算法和EBA 算法改善了现有方 ...