垂直搜索引擎四》文本处理模块的设计与实现

编程知识 更新时间:2023-05-03 03:58:29

4.2文本处理模块的设计与实现

4.2.1 文本处理模块的总设计

另外还对信息过滤模块主要要做的事情有三个:

(1) 对抓下来的HTML网页进行解析,提取出所关心的文章标题,时间和正文;

(2) 对文章标题和内容进行分词;

(3) 去重。

 

 

图4-7  文本处理设计图

 

4.2.2 文本模块之页面解析

页面解析主要是用开源的htmlparser工具。htmlparser是一个纯的java写的html(标准通用标记语言下的一个应用)解析的库,它不依赖于其它的java库文件,主要用于改造或提取html。它能超高速解析html,而且很少会出错。

一、整体解析过程:

(1)用一个URL或页面String做一个Parser

 (2)用这个Parser做一个Visitor

(3)使用Parser.visitAllNodeWith(Visitor)来遍历节点

(4)获取Visitor遍历后得到的数据

二、核心代码:

 

private static void testParser(String url) {  
  try {  
      //生成一个解析器对象,用网页的 url 作为参数  
       Parser parser = new Parser(url);  
      //设置网页的编码,这里只是请求了一个UTF-8编码网页  
      parser.setEncoding("UTF-8");  
     // 方法一Filter:根据tag中的class或id去解析得到想要的数据  
     NodeFilter beginNodeFilter = new AndFilter(new TagNameFilter("td"),new HasAttributeFilter("class", "b1"));  
     NodeList nodeList = parser.extractAllNodesThatMatch(beginNodeFilter);  
     if (nodeList != null && nodeList.size() > 0) {  
     Node nameNode = nodeList.elementAt(0);  
     String name = nameNode.toPlainTextString().trim();  
     System.out.println(name);  
     }  
     parser.reset();  
   }catch(ParserException e){  
     e.printStackTrace();  
  }  
}

 

4.2.3 文本过滤模块之中文分词

 

我们都知道,对于搜索引擎如果利用现成的框架是比较容易实现以下步骤:获取文本内容、建立索引、分词、检索。但是这并不能保证检索出来的东西是我们想要的结果。识别语义、查找的东西与检索出来的东西的相关性是搜索引擎的核心。

本系统的分析分为三个阶段:基本分词,词性分词和左右完整性分词。

(1)基本分词:

基本分词是采用IKAnalyzer进行分词。IKAnalyer自带一个词典作为词典库,该词典库收录了绝大部分的基本词汇,我们在输入一段字符串时,它能根据字典的词汇把这段字符串分隔同时还可以给出相对应的词性。可以这么说,利用字典库我们可以解决绝大部分的分词。

IKAnalyzer分词它的核心使用代码如下:

 

public static StringikSplit(String str){
            /*1.根据文档引入包,引入词典和xml配置
             * 2. str -->byteArrayInputStream---》InputStreamReader
             * 3.IKSegmenter --》Lexeme = ~。next--》~.getLexemeText();
             */
            String result="";
            if(StringUtil.isEmpty(str))return result;
            try {
                byte[] bt =str.getBytes();
                InputStream is = newByteArrayInputStream(bt);
                Reader read = newInputStreamReader(is);
                IKSegmenter iks = newIKSegmenter(read, true);
                Lexeme t=null;
                while((t =iks.next()) !=null){
                    result= result +  t.getLexemeText() + "  ";
                }
                System.out.println(result);
            } catch(Exception e) {
                e.printStackTrace();
            }
            return result;
     }

 

 

 

 

 

(2)词性分析:

很多时候,由于农业行业的特殊性,有很多专业名词是没有被添加到词典的,这些词语根据词典是很难判别不出语义的。例如大豆的一个品种“中黄57”,或者农场所使用的传感器“蓝牙”。在这里,“中黄57”连起来是一个候选对象;如果只是普通地按照词性来分词,那么无论“中”,“黄”,“57”都是不完整的名词对象;同样“蓝”,“牙”都不是完整的名词对象;只有连起来“中黄57”,“蓝牙”才能构成一个有意义的名词对象。为此我们要根据一定的规则来选出完整对象,那么才会更准确地理解语义。按照词性分词分为三个步骤:编写词性规则,构造词性正则表达式,递归匹配。

步骤一、 词性规则可以分为:

 

 

图4-8  词性规则表

 

步骤二、构造词性正则表达式:

/

**
 * 获取抽取规则并放在list
 * @param inputPath
 * @return
 * @throws Exception
 */
public static List<String> getRulesFromFile(String inputPath) throws Exception{
List<String> results = new ArrayList<String>();
File inputFile = new File(inputPath);
if(!inputFile.exists()){
throw new Exception("inputPath is no exists");
}
FileReader fr = new FileReader(inputFile);
BufferedReader br = new BufferedReader(fr);
try {
String regex = "[\u4E00-\u9FA5a-zA-Z0-9]*";
String temp;
while((temp = br.readLine()) != null){
String[] worlds = temp.split(" ");
String build_regx ="";
for(int i =0;i<worlds.length;i++){
build_regx += regex +ConstantString.slash+worlds[i]+" ";
}
System.out.println(build_regx);
results.add(build_regx);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(br != null){
br.close();
}
if(fr != null){
fr.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return results;
}
 

 

 

步骤三、递归匹配内容并输出:

 

public static void ExtratorWorld2File(String rulesPath,String inputPath,String outputPath) throws Exception{
if(StringUtil.isEmpty(inputPath) || StringUtil.isEmpty(rulesPath)){
throw new Exception("inputPath/rulesPath is null");
}
File file = new File(outputPath);
if(!file.exists()){
file.mkdirs();
}
ArrayList<String> rules = (ArrayList<String>) ExtratorWordUtil.getRulesFromFile(rulesPath);
ArrayList<String> paths = new StringUtil().getAllPath(inputPath);
for(String path : paths){
String result ="";
String content = StringUtil.getContent(path);
String name = StringUtil.getNameFromPath(path);
String outputFile = outputPath + ConstantString.slash + name + ConstantString.postText;
for(String rule : rules){
result += StringUtil.getContentUseRegex(rule, content, 0,ConstantString.WIN_NextLine) +ConstantString.WIN_NextLine;
}
StringUtil.String2File(result, outputFile);
}
}
 

 

 

 

 (3)左右完整性分词:

上面提到的大豆的一个品种“中黄57”,如果仅仅是按照词性来分,能把作为名词的“中”和形容词的“黄”结合在一起构成一个名词对象“中黄57”,但是很难确定后面数字“57”是否也需要结合在一起。所以这个时候就需要进行右结合性的稳定性检查。判断右边的词“57”与其结合起来是否合理。

评价对象的稳定性:针对本文中候选评价对象 Object是基于规则获得的,通常是由多个词(w1w2…w3)组成的。用各个词之间的紧密耦合程度,来衡量 Object的稳定性,本文采用下式计算获得:

 

        图4-9  词频稳定性公式

 

其中, f(Object) 表示 Object在一篇文档中出现的频率;f(wi )表示组成 Object 的词wi在该文档中出现的频率; m表示组成该 Object的词个数; S(Object ) 表示评价对象的稳定性。

它的流程图如图4-10下:

 

图4-10  左右完整结合性分词流程

 

4.2.4 文本过滤模块之网页去重

搜索引擎优化中,网站内部优化至关重要,其中网站内部还需要注意页面的重复。即:同一篇文章经常会重复出现在同一个网站的不同网址上。解决这些问题常用的方法有:

1. 最小编辑距离

 

 

图4-11  最小编辑距离

 

2.TF*IDF 特征值

TF - IDF统计方法用于评估一个字的文件集或一个语料库的文档的重要性之一。单词的重要性,因为它成正比文件中出现的次数增加,但与此同时,因为它的频率成反比下降语料库。各种形式的TF - IDF权重经常被搜索引擎应用程序,作为文件与用户查询之间的相关程度度量或评级。

3. 余弦夹角

想象两个文本分成两线段的空间,从原点([0,0,…]),在不同的方向。两个线段之间形成一个角度,如果角0度,意味着在同一方向,线重叠;如果角是90度,意味着形成一个直角,完全不相似的方向;如果角是180度,意味着相反的方向。因此,我们可以通过角的大小,判断向量的相似度。角度越小,越相似。

4.指纹算法

中国历史上最早利用指纹识别可以追溯到秦朝,1903年,青岛中国警察汉堡类型指纹方法首次应用。因为我们国家的应用和研究指纹,也建立了一个“指纹”。

本系统中实现了最小编辑距离

最小编辑距离的java代码实现如下:

 

 

图4-12  最小编辑距离动态规划

 

核心代码:

 

public static int min_edit_distance(String target,String source){  
        int t_len = target.length();  
        int s_len = source.length();  
        int[][] distance = new int[t_len+1][s_len+1];  
          
        //初始化 0状态  
        distance[0][0] = 0;  
        for(int i=1;i<=t_len;i++){  
            distance[i][0] = distance[i-1][0]+insert_cost(target.charAt(i-1));  
        }  
        for(int j=1;j<=s_len;j++){  
            distance[0][j] = distance[0][j-1]+delete_cost(source.charAt(j-1));  
        }  
          
        for(int i=1;i<=t_len;i++){  
            for(int j=1;j<=s_len;j++){  
                int a = distance[i-1][j] + insert_cost(target.charAt(i-1));  
                int b = distance[i-1][j-1] + substitute_cost(target.charAt(i-1), source.charAt(j-1));  
                int c = distance[i][j-1] + delete_cost(source.charAt(j-1));  
                distance[i][j] = min(a,min(b,c));         
            }  
        }  
        return distance[t_len][s_len];  
    }  
      
    private static int min(int a ,int b){  
        return a<b?a:b;  
    }  
    private static int insert_cost(char c){  
        return 1;  
    }  
    private static int delete_cost(char str){  
        return 1;  
    }  
    private static int substitute_cost(char a,char b){  
        if(a == b) return 0;  
        else return 2;  
}  
 

 

 

更多推荐

垂直搜索引擎四》文本处理模块的设计与实现

本文发布于:2023-04-30 12:10:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/9574d411f35faa0dcae525b0e0fc2eea.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:模块   文本   搜索引擎

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!

  • 114412文章数
  • 28945阅读数
  • 0评论数