首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > CSS >

用htmlparser分析并抽取本文

2012-07-05 
用htmlparser分析并抽取正文转:http://hannibal730816.iteye.com/blog/149493我这次要介绍的是如何抽取正

用htmlparser分析并抽取正文

转:http://hannibal730816.iteye.com/blog/149493

我这次要介绍的是如何抽取正文,这部分是最为核心的.因为如果不能很好的提取原有文章的内容和样式,那么搜索出来的东西?
就会惨不忍睹.根本就没有使用价值?

  在做正文抽取模块之前我曾经参考过很多抽取模式,有配置模版的,有搞视觉匹配的.有搞关键字识别的.我挨个做了分析?
首先配置摸版是不太现实的,因为我在搜索技术资讯的时候,根本不知道会搜索到哪个网站,也根本没精力去配置摸版.所以这个行不通?
  ?
  基于视觉效果的分析,这个难度比较大,而且只适合于规范的网站,而现在很多网站根本不规范,广告链接漫天飞.人家都把最好的?
位置留给广告了.而且我一直怀疑这个模式的可行性,它只是一个善意的推测.所以这方面没做过多尝试?

  我在想,是否有种简单的方法呢?难道就没有什么共性吗??

  我想所有的正文应该有个共同的特点,那就是正文的长度应该超过其他文字组合的长度.很少会有一句话的正文,很少会有长度?
短于标题的正文.所以这个应该成为一个突破口.?

  接下来,有一个很重要的问题,那段最长的正文在哪里呢??
  肯定是在一个TABLE,或者DIV,或者ParagraphTag里.那好,那就找到那个包含文字最多的DIV或者TABLE.?

  不过问题又来了,HTML页面,经常是HTML元素的长度超过了正文的长度,有时候混入了不少的JAVASCRIPT.这些元素?
HTMLPARSER经常会误认为是正文加以识别,导致很多正文竟然是一段JAVASCRIPT.?
  祛除杂质是一个关键,这里面要把那些HTML中常用的标签,以及连接中正文去除掉,否则,你搜索出来的很可能是别的什么,尤其?
当正文文字相对较少的时候.我在搜索SOHU页面的时候就经常遇到这个问题,原因是SOHU的页面不是严格按照DIV布局,里面有很多广告?
的JAVASCRIPT。新浪的有些页面也有这个现象,反到是一些中小网站的布局很规范,呵呵,真奇怪了。?

  做完这些工作后,我发现仍然有些网页不能正常抓取,原因是HTMLPARSER对TEXT的认识有问题.例如一段文字在?
ParagraphTag中或者span中包含的,就不能很好的识别.所以要单独做个抽取ParagraphTag内容的函数.?

  做完这些步骤后,有一个问题出来了就是正文中包含的图片,连接,粗体,正常的表格.这些问题一个个的冒出来.既然问题出来了?
那就要一个个的解决.解决了这些难题.我的网站抓取文章的质量就大大的提高了85%的准确率,基本达到实用阶段.我网站上的正文快照基本和原文保持一致.?

    提供几个例子,大家可以看下原文和我抓取的有多少不同?
    1. http://www.itsubway.com/context/20071218/11762.htm?
??????????????? 这个是单纯获取正文的例子,其中有粗体标签和链接?

    2 http://www.itsubway.com/context/20071218/12041.htm?
     这个是正文里混有图片和表格.?


  我把抽取正文的部分代码和大家共享.这些代码基本解决了我在上面列举出来的问题。包括正文中混有图片,连接,粗体,表格等。?
??? 大家要是有兴趣可以改造下这些代码 请大家重点看protected List extractHtml(Node nodeP, PageContext context, String siteUrl)?
??? 这个函数是正文抽取的入口。我的这些函数写的不是很规范,别笑话!?
????/**

    * 收集HTML页面信息 调用抓取函数 按照自己的摸版 生成网页     * @param url     * @param urlEncode     */     public void makeContext(ChannelLinkDO c) {         String metakeywords = "<META content={0} name=keywords>";         String metatitle = "<TITLE>{0}</TITLE>";         String metadesc = "<META content={0} name=description>";         String netshap = "<p> 正文快照: 时间{0}</p> ";         String tempLeate = "<LI class=active><A href="{0}" target=_blank>{1}</A></LI>";         String crop = "<p><A href="{0}" target=_blank>{1}</A></p> ";         try {             String siteUrl = getLinkUrl(c.getLink());             Parser parser = new Parser(c.getLink());             parser.setEncoding(c.getEncode());             for (NodeIterator e = parser.elements(); e.hasMoreNodes();) {                 Node node = (Node) e.nextNode();                 if (node instanceof Html) {                     PageContext context = new PageContext();                     context.setNumber(0);                     context.setTextBuffer(new StringBuffer());                     //抓取出内容                     extractHtml(node, context, siteUrl);                     StringBuffer testContext = context.getTextBuffer();                     //.....生成网页                     }             }         } catch (Exception e) {             System.out.println(e);         }     }     private String getLinkUrl(String link) {         String urlDomaiPattern = "(http://[^/]*?" + "/)(.*?)";         Pattern pattern = Pattern.compile(urlDomaiPattern,                 Pattern.CASE_INSENSITIVE + Pattern.DOTALL);         Matcher matcher = pattern.matcher(link);         String url = "";         while (matcher.find()) {             int start = matcher.start(1);             int end = matcher.end(1);             url = link.substring(start, end - 1).trim();         }         return url;     }     /**     * 递归钻取正文信息     * @param nodeP     * @return     */     protected List extractHtml(Node nodeP, PageContext context, String siteUrl)         throws Exception {         NodeList nodeList = nodeP.getChildren();         boolean bl = false;         if ((nodeList == null) || (nodeList.size() == 0)) {             if (nodeP instanceof ParagraphTag) {                 ArrayList tableList = new ArrayList();                 StringBuffer temp = new StringBuffer();                 temp.append("<p style="TEXT-INDENT: 2em">");                 tableList.add(temp);                 temp = new StringBuffer();                 temp.append("</p>").append(lineSign);                 tableList.add(temp);                 return tableList;             }             return null;         }         if ((nodeP instanceof TableTag) || (nodeP instanceof Div)) {             bl = true;         }         if (nodeP instanceof ParagraphTag) {             ArrayList tableList = new ArrayList();             StringBuffer temp = new StringBuffer();             temp.append("<p style="TEXT-INDENT: 2em">");             tableList.add(temp);             extractParagraph(nodeP, siteUrl, tableList);             temp = new StringBuffer();             temp.append("</p>").append(lineSign);             tableList.add(temp);             return tableList;         }         ArrayList tableList = new ArrayList();         try {             for (NodeIterator e = nodeList.elements(); e.hasMoreNodes();) {                 Node node = (Node) e.nextNode();                 if (node instanceof LinkTag) {                     tableList.add(node);                     setLinkImg(node, siteUrl);                 } else if (node instanceof ImageTag) {                     ImageTag img = (ImageTag) node;                     if (img.getImageURL().toLowerCase().indexOf("http://") < 0) {                         img.setImageURL(siteUrl + img.getImageURL());                     } else {                         img.setImageURL(img.getImageURL());                     }                     tableList.add(node);                 } else if (node instanceof ScriptTag ||                         node instanceof StyleTag || node instanceof SelectTag) {                 } else if (node instanceof TextNode) {                     if (node.getText().length() > 0) {                         StringBuffer temp = new StringBuffer();                         String text = collapse(node.getText()                                                    .replaceAll("&nbsp;", "")                                                    .replaceAll(" ", ""));                         temp.append(text.trim());                         tableList.add(temp);                     }                 } else {                     if (node instanceof TableTag || node instanceof Div) {                         TableValid tableValid = new TableValid();                         isValidTable(node, tableValid);                         if (tableValid.getTrnum() > 2) {                             tableList.add(node);                             continue;                         }                     }                     List tempList = extractHtml(node, context, siteUrl);                     if ((tempList != null) && (tempList.size() > 0)) {                         Iterator ti = tempList.iterator();                         while (ti.hasNext()) {                             tableList.add(ti.next());                         }                     }                 }             }         } catch (Exception e) {             return null;         }         if ((tableList != null) && (tableList.size() > 0)) {             if (bl) {                 StringBuffer temp = new StringBuffer();                 Iterator ti = tableList.iterator();                 int wordSize = 0;                 StringBuffer node;                 int status = 0;                 StringBuffer lineStart = new StringBuffer(                         "<p style="TEXT-INDENT: 2em">");                 StringBuffer lineEnd = new StringBuffer("</p>" + lineSign);                 while (ti.hasNext()) {                     Object k = ti.next();                     if (k instanceof LinkTag) {                         if (status == 0) {                             temp.append(lineStart);                             status = 1;                         }                         node = new StringBuffer(((LinkTag) k).toHtml());                         temp.append(node);                     } else if (k instanceof ImageTag) {                         if (status == 0) {                             temp.append(lineStart);                             status = 1;                         }                         node = new StringBuffer(((ImageTag) k).toHtml());                         temp.append(node);                     } else if (k instanceof TableTag) {                         if (status == 0) {                             temp.append(lineStart);                             status = 1;                         }                         node = new StringBuffer(((TableTag) k).toHtml());                         temp.append(node);                     } else if (k instanceof Div) {                         if (status == 0) {                             temp.append(lineStart);                             status = 1;                         }                         node = new StringBuffer(((Div) k).toHtml());                         temp.append(node);                     } else {                         node = (StringBuffer) k;                         if (status == 0) {                             if (node.indexOf("<p") < 0) {                                 temp.append(lineStart);                                 temp.append(node);                                 wordSize = wordSize + node.length();                                 status = 1;                             } else {                                 temp.append(node);                                 status = 1;                             }                         } else if (status == 1) {                             if (node.indexOf("</p") < 0) {                                 if (node.indexOf("<p") < 0) {                                     temp.append(node);                                     wordSize = wordSize + node.length();                                 } else {                                     temp.append(lineEnd);                                     temp.append(node);                                     status = 1;                                 }                             } else {                                 temp.append(node);                                 status = 0;                             }                         }                     }                 }                 if (status == 1) {                     temp.append(lineEnd);                 }                 if (wordSize > context.getNumber()) {                     context.setNumber(wordSize);                     context.setTextBuffer(temp);                 }                 return null;             } else {                 return tableList;             }         }         return null;     }     /**     * 设置图象连接     * @param nodeP     * @param siteUrl     */     private void setLinkImg(Node nodeP, String siteUrl) {         NodeList nodeList = nodeP.getChildren();         try {             for (NodeIterator e = nodeList.elements(); e.hasMoreNodes();) {                 Node node = (Node) e.nextNode();                 if (node instanceof ImageTag) {                     ImageTag img = (ImageTag) node;                     if (img.getImageURL().toLowerCase().indexOf("http://") < 0) {                         img.setImageURL(siteUrl + img.getImageURL());                     } else {                         img.setImageURL(img.getImageURL());                     }                 }             }         } catch (Exception e) {             return;         }         return;     }     /**     * 钻取段落中的内容     * @param nodeP     * @param siteUrl     * @param tableList     * @return     */     private List extractParagraph(Node nodeP, String siteUrl, List tableList) {         NodeList nodeList = nodeP.getChildren();         if ((nodeList == null) || (nodeList.size() == 0)) {             if (nodeP instanceof ParagraphTag) {                 StringBuffer temp = new StringBuffer();                 temp.append("<p style="TEXT-INDENT: 2em">");                 tableList.add(temp);                 temp = new StringBuffer();                 temp.append("</p>").append(lineSign);                 tableList.add(temp);                 return tableList;             }             return null;         }         try {             for (NodeIterator e = nodeList.elements(); e.hasMoreNodes();) {                 Node node = (Node) e.nextNode();                 if (node instanceof ScriptTag || node instanceof StyleTag ||                         node instanceof SelectTag) {                 } else if (node instanceof LinkTag) {                     tableList.add(node);                     setLinkImg(node, siteUrl);                 } else if (node instanceof ImageTag) {                     ImageTag img = (ImageTag) node;                     if (img.getImageURL().toLowerCase().indexOf("http://") < 0) {                         img.setImageURL(siteUrl + img.getImageURL());                     } else {                         img.setImageURL(img.getImageURL());                     }                     tableList.add(node);                 } else if (node instanceof TextNode) {                     if (node.getText().trim().length() > 0) {                         String text = collapse(node.getText()                                                    .replaceAll("&nbsp;", "")                                                    .replaceAll(" ", ""));                         StringBuffer temp = new StringBuffer();                         temp.append(text);                         tableList.add(temp);                     }                 } else if (node instanceof Span) {                     StringBuffer spanWord = new StringBuffer();                     getSpanWord(node, spanWord);                     if ((spanWord != null) && (spanWord.length() > 0)) {                         String text = collapse(spanWord.toString()                                                        .replaceAll("&nbsp;", "")                                                        .replaceAll(" ", ""));                         StringBuffer temp = new StringBuffer();                         temp.append(text);                         tableList.add(temp);                     }                 } else if (node instanceof TagNode) {                     String tag = node.toHtml();                     if (tag.length() <= 10) {                         tag = tag.toLowerCase();                         if ((tag.indexOf("strong") >= 0) ||                                 (tag.indexOf("b") >= 0)) {                             StringBuffer temp = new StringBuffer();                             temp.append(tag);                             tableList.add(temp);                         }                     } else {                         if (node instanceof TableTag || node instanceof Div) {                             TableValid tableValid = new TableValid();                             isValidTable(node, tableValid);                             if (tableValid.getTrnum() > 2) {                                 tableList.add(node);                                 continue;                             }                         }                         extractParagraph(node, siteUrl, tableList);                     }                 }             }         } catch (Exception e) {             return null;         }         return tableList;     }     protected void getSpanWord(Node nodeP, StringBuffer spanWord) {         NodeList nodeList = nodeP.getChildren();         try {             for (NodeIterator e = nodeList.elements(); e.hasMoreNodes();) {                 Node node = (Node) e.nextNode();                 if (node instanceof ScriptTag || node instanceof StyleTag ||                         node instanceof SelectTag) {                 } else if (node instanceof TextNode) {                     spanWord.append(node.getText());                 } else if (node instanceof Span) {                     getSpanWord(node, spanWord);                 } else if (node instanceof ParagraphTag) {                     getSpanWord(node, spanWord);                 } else if (node instanceof TagNode) {                     String tag = node.toHtml().toLowerCase();                     if (tag.length() <= 10) {                         if ((tag.indexOf("strong") >= 0) ||                                 (tag.indexOf("b") >= 0)) {                             spanWord.append(tag);                         }                     }                 }             }         } catch (Exception e) {         }         return;     }     /**     * 判断TABLE是否是表单     * @param nodeP     * @return     */     private void isValidTable(Node nodeP, TableValid tableValid) {         NodeList nodeList = nodeP.getChildren();         /**如果该表单没有子节点则返回**/         if ((nodeList == null) || (nodeList.size() == 0)) {             return;         }         try {             for (NodeIterator e = nodeList.elements(); e.hasMoreNodes();) {                 Node node = (Node) e.nextNode();                 /**如果子节点本身也是表单则返回**/                 if (node instanceof TableTag || node instanceof Div) {                     return;                 } else if (node instanceof ScriptTag ||                         node instanceof StyleTag || node instanceof SelectTag) {                     return;                 } else if (node instanceof TableColumn) {                     return;                 } else if (node instanceof TableRow) {                     TableColumnValid tcValid = new TableColumnValid();                     tcValid.setValid(true);                     findTD(node, tcValid);                     if (tcValid.isValid()) {                         if (tcValid.getTdNum() < 2) {                             if (tableValid.getTdnum() > 0) {                                 return;                             } else {                                 continue;                             }                         } else {                             if (tableValid.getTdnum() == 0) {                                 tableValid.setTdnum(tcValid.getTdNum());                                 tableValid.setTrnum(tableValid.getTrnum() + 1);                             } else {                                 if (tableValid.getTdnum() == tcValid.getTdNum()) {                                     tableValid.setTrnum(tableValid.getTrnum() +                                         1);                                 } else {                                     return;                                 }                             }                         }                     }                 } else {                     isValidTable(node, tableValid);                 }             }         } catch (Exception e) {             return;         }         return;     }     /**     * 判断是否有效TR     * @param nodeP     * @param TcValid     * @return     */     private void findTD(Node nodeP, TableColumnValid tcValid) {         NodeList nodeList = nodeP.getChildren();         /**如果该表单没有子节点则返回**/         if ((nodeList == null) || (nodeList.size() == 0)) {             return;         }         try {             for (NodeIterator e = nodeList.elements(); e.hasMoreNodes();) {                 Node node = (Node) e.nextNode();                 /**如果有嵌套表单**/                 if (node instanceof TableTag || node instanceof Div ||                         node instanceof TableRow ||                         node instanceof TableHeader) {                     tcValid.setValid(false);                     return;                 } else if (node instanceof ScriptTag ||                         node instanceof StyleTag || node instanceof SelectTag) {                     tcValid.setValid(false);                     return;                 } else if (node instanceof TableColumn) {                     tcValid.setTdNum(tcValid.getTdNum() + 1);                 } else {                     findTD(node, tcValid);                 }             }         } catch (Exception e) {             tcValid.setValid(false);             return;         }         return;     }     protected String collapse(String string) {         int chars;         int length;         int state;         char character;         StringBuffer buffer = new StringBuffer();         chars = string.length();         if (0 != chars) {             length = buffer.length();             state = ((0 == length) || (buffer.charAt(length - 1) == ' ') ||                 ((lineSign_size <= length) &&                 buffer.substring(length - lineSign_size, length).equals(lineSign)))                 ? 0 : 1;             for (int i = 0; i < chars; i++) {                 character = string.charAt(i);                 switch (character) {                 case '\u0020':                 case '\u0009':                 case '\u000C':                 case '\u200B':                 case '\u00a0':                 case '\r':                 case '\n':                     if (0 != state) {                         state = 1;                     }                     break;                 default:                     if (1 == state) {                         buffer.append(' ');                     }                     state = 2;                     buffer.append(character);                 }             }         }         return buffer.toString();     } 

?
????

?

1 楼 hegang126 2011-11-07   你好啊,最近做网页正文抽取,你的这个完整的源代码能给一份吗?,我邮箱是 hegang_126@126.com,谢谢啊

热点排行