基于行块分布函数的正文抽取

基于行块分布函数的正文抽取算法思路:
1、预处理:剔除网页HTML标签,去掉所有的空白符(\n,\r,\t等);
2、依据"\n"分行,若某文字行的上下存在两个空行,且此文字行长度小于阈值40,则删除此文字行;
3、设定三行为一行块,计算每段行块的长度;
4、找出每个连续有字符的段落,并找到起点和终点;
          要求:行块长度大于0(段落开始),且随后连续行块长度大于0,直到行块长度为0(即段落结束)
5、如果两块段落只差两个空行,并且两块包含文字均较多,则进行段落合并;

6、找出最长段落,如果长度小于100,则推出提供的网页为非主体性网页;否则,最长段落即为正文;

  1. import java.io.BufferedReader;  
  2. import java.io.ByteArrayInputStream;  
  3. import java.io.IOException;  
  4. import java.io.InputStreamReader;  
  5. import java.util.ArrayList;  
  6. import java.util.HashMap;  
  7. import java.util.List;  
  8. import java.util.Map;  
  9. import java.util.Map.Entry;  
  10. import java.util.Set;  
  11.   
  12. public class Ctext {  
  13.   
  14.     /**  
  15.      * 行分块的大小(块大小=BLOCKS+1)  
  16.      */  
  17.     private static int BLOCKS = 0;  
  18.     /**  
  19.      * 判断为正文的文字骤变率  
  20.      */  
  21.     private static float CHANGE_RATE = 0.7f;  
  22.     /**  
  23.      * 每行最小长度  
  24.      */  
  25.     private static int MIN_LENGTH = 10;  
  26.       
  27.     public static void main(String[] args) {  
  28.   
  29.         String html = "";  
  30.         html = deleteLabel(html);  
  31.           
  32.         Map<Integer, String> map = splitBlock(html);  
  33.         System.out.println(judgeBlocks(map));  
  34.     }  
  35.       
  36.     /**  
  37.      * 去除html标签  
  38.      * @param html 请求获得的html文本  
  39.      * @return 纯文本  
  40.      */  
  41.     public static String deleteLabel(String html){  
  42.         String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; // 定义script的正则表达式    
  43.         String regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>"; // 定义style的正则表达式    
  44.         String regEx_html = "<[^>]+>"; // 定义HTML标签的正则表达式    
  45.         String regEx_anno = "<!--[\\s\\S]*?-->"; //html注释  
  46.         html = html.replaceAll(regEx_script, "");  
  47.         html = html.replaceAll(regEx_style, "");  
  48.         html = html.replaceAll(regEx_html, "");  
  49.         html = html.replace(regEx_anno, "");  
  50.         html = html.replaceAll("((\r\n)|\n)[\\s\t ]*(\\1)+", "$1").replaceAll("^((\r\n)|\n)", "");//去除空白行  
  51.         html = html.replaceAll("    +| +| +", ""); //去除空白  
  52.         return html.trim();  
  53.     }  
  54.   
  55.     /**  
  56.      * 将纯文本按BLOCKS分块  
  57.      * @param text 纯文本  
  58.      * @return 分块后的map集合,键即为块号,值为块内容  
  59.      */  
  60.     public static Map<Integer, String> splitBlock(String text){  
  61.         Map<Integer, String> groupMap = new HashMap<Integer, String>();  
  62.         ByteArrayInputStream bais = new ByteArrayInputStream(text.getBytes());  
  63.         BufferedReader br = new BufferedReader(new InputStreamReader(bais));  
  64.         String line = null,blocksLine = "";  
  65.         int theCount = 0,groupCount = 0,count=0;//1.记录每次添加的行数;2.记录块号;3.记录总行数  
  66.         try {  
  67.             while((line=br.readLine())!=null){  
  68.                 if (line.length()>MIN_LENGTH) {  
  69.                     System.out.println(line);  
  70.                     if (theCount<=BLOCKS) {  
  71.                         blocksLine +=line.trim();   
  72.                         theCount++;  
  73.                     }  
  74.                     else {  
  75.                         groupMap.put(groupCount, blocksLine);  
  76.                         groupCount++;  
  77.                         blocksLine = line.trim();  
  78.                         theCount = 1;  
  79.                     }  
  80.                     count++;  
  81.                 }  
  82.             }  
  83.             if (theCount!=0) {//加上没凑齐的给给定块数的  
  84.                 groupMap.put(groupCount+1, blocksLine);  
  85.             }  
  86.             System.out.println("一共"+groupMap.size()+"个行块,数据行数一共有"+count);  
  87.         } catch (IOException e) {  
  88.             e.printStackTrace();  
  89.         }  
  90.         return groupMap;  
  91.     }  
  92.       
  93.     /**  
  94.      * 分析每块之间变化的情况  
  95.      * @param map 块集合  
  96.      * @return 正文  
  97.      */  
  98.     public static String judgeBlocks(Map<Integer, String> map){  
  99.         Set<Entry<Integer, String>> sets = map.entrySet();  
  100.         List<Integer> contentBlock = new ArrayList<Integer>();  
  101.         int currentBlock = map.get(0).length(); //当前行的长度  
  102.         int lastBlock = 0; //上一行的长度  
  103.           
  104.         for(Entry<Integer, String> set:sets){  
  105.             lastBlock = currentBlock;  
  106.             currentBlock = set.getValue().length();  
  107.             float between = (float)Math.abs(currentBlock - lastBlock)/Math.max(currentBlock, lastBlock);  
  108.             if (between>=CHANGE_RATE) {  
  109.                 contentBlock.add(set.getKey());  
  110.             }  
  111.         }  
  112.         //下面是取多个峰值节点中两个节点之间内容长度最大的内容  
  113.         int matchNode = contentBlock.size();  
  114.         System.out.println("一共有"+matchNode+"峰值点");  
  115.         int lastContent = 0;//前一个两节点之间的内容长度  
  116.         String context = null;//结果  
  117.         if (matchNode>2) {   
  118.             for(int i=1;i<matchNode;i++){  
  119.                 String result = "";  
  120.                 for(int j=contentBlock.get(i-1);j<contentBlock.get(i);j++){  
  121.                     result +=map.get(j);  
  122.                 }  
  123.                 if (result.length()>lastContent) {  
  124.                     lastContent = result.length();  
  125.                     context = result;  
  126.                 }  
  127.             }  
  128.         }  
  129.         return context;  
  130.     }  
  131. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值