java中几种解析html的工具

html-css010

java中几种解析html的工具,第1张

HTML分析是一个比较复杂的工作,Java世界主要有几款比较方便的分析工具:

1.Jsoup 

Jsoup是一个集强大和便利于一体的HTML解析工具。它方便的地方是,可以用于支持用jQuery中css selector的方式选取元素,这对于熟悉js的开发者来说基本没有学习成本。

String content = "blabla"

Document doc = JSoup.parse(content)

Elements links = doc.select("a[href]")

Jsoup还支持白名单过滤机制,对于网站防止XSS攻击也是很好的。

2.HtmlParser

HtmlParser的功能比较完备,也挺灵活,但谈不上方便。这个项目很久没有维护了,最新版本是2.1。HtmlParser的核心元素是Node,对应一个HTML标签,支持getChildren()等树状遍历方式。HtmlParser另外一个核心元素是NodeFilter,通过实现NodeFilter接口,可以对页面元素进行筛选。这里有一篇HtmlParser的使用文章:使用 HttpClient 和 HtmlParser 实现简易爬虫。

3.Apache tika

tika是专为抽取而生的工具,还支持PDF、Zip甚至是Java Class。使用tika分析HTML,需要自己定义一个抽取内容的Handler并继承org.xml.sax.helpers.DefaultHandler,解析方式就是xml标准的方式。crawler4j中就使用了tika作为解析工具。SAX这种流式的解析方式对于分析大文件很有用,我个人倒是认为对于解析html意义不是很大。

InputStream inputStream = null

HtmlParser htmlParser = new HtmlParser()

htmlParser.parse(new ByteArrayInputStream(page.getContentData()),

contentHandler, metadata, new ParseContext())

4.HtmlCleaner与XPath

HtmlCleaner最大的优点是:支持XPath的方式选取元素。XPath是一门在XML中查找信息的语言,也可以用于抽取HTML元素。XPath与CSS Selector大部分功能都是重合的,但是CSS Selector专门针对HTML,写法更简洁,而XPath则是通用的标准,可以精确到属性值。XPath有一定的学习成本,但是对经常需要编写爬虫的人来说,这点投入绝对是值得的。

步骤:

一、使用java.net包下的URL类,可以将一个网页(链接)封装成一个URL对象。

二、URL对象有一个openStream()方法,使用该方法可以获取该网页的输入流,我们可以通过读取输入流的方式获得网页的内容,并通过输出流写入HTML文件中。

补充:

步骤:

1.通过URL对象的openStream()方法获得网页的字节输入流 。

2.为字节输入流加缓冲 。

3. 创建字节输出流对象 。

4. 为字节输出流加缓冲 。

5. 读取数据,并写入HTML文件 。

     java读取html文件跟读取普通文件一样,都是使用输入输出流,但是java读取html文件之后还需要解析,使用Jsoup对html进行解析。下面是一个java读取带表格的任意html文件,并把html文件转换成excel的例子。

  要求: 要求能够实现给出任意带table表格的html文件,生成与表格相同内容的excel文件,附件可以作为测试文件,提供给定的roster.html文件,通过java代码,实现生成与html页面的table相同样式的roster.xls文件。

首先看roster.html:

java代码:

import java.io.BufferedReader

import java.io.File

import java.io.FileReader

import java.io.IOException

import jxl.Workbook

import jxl.write.Label

import jxl.write.WritableCellFormat

import jxl.write.WritableFont

import jxl.write.WritableSheet

import jxl.write.WritableWorkbook

import jxl.write.WriteException

import jxl.write.biff.RowsExceededException

import org.jsoup.Jsoup

import org.jsoup.nodes.Document

import org.jsoup.nodes.Element

import org.jsoup.select.Elements

public class HTMLTOExcel {

public static void main(String args[]) throws IOException{

///读取classpath目录下面的路径

String path=HTMLTOExcel.class.getResource("/").getPath()

path+="roster.html"

toExcel(path,"roster")      

    }

    //得到Document并且设置编码格式

public static Document getDoc(String fileName) throws IOException{

      File myFile=new File(fileName)

      Document doc= Jsoup.parse(myFile, "GBK","")

      return doc

}

///这个方法用于根据trs行数和sheet画出整个表格

public static void mergeColRow(Elements trs,WritableSheet sheet) throws RowsExceededException, WriteException{

int[][] rowhb=new int[300][50]

for(int i=0i<trs.size()i++){

 Element tr=trs.get(i)

 Elements tds=tr.getElementsByTag("td")

 

 int realColNum=0

 for(int j=0j<tds.size()j++){

  Element td=tds.get(j)  

  if(rowhb[i][realColNum]!=0){

  realColNum=getRealColNum(rowhb,i,realColNum)

  }

  int rowspan=1

  int colspan=1

  if(td.attr("rowspan")!=""){

  rowspan = Integer.parseInt(td.attr("rowspan"))

  }

  if(td.attr("colspan")!=""){

  colspan = Integer.parseInt(td.attr("colspan"))

  }

  String text=td.text()

  drawMegerCell(rowspan,colspan,sheet,realColNum,i,text,rowhb)

  realColNum=realColNum+colspan

 }

 

}

}

///这个方法用于根据样式画出单元格,并且根据rowpan和colspan合并单元格

public static void drawMegerCell(int rowspan,int colspan,WritableSheet sheet,int realColNum,int realRowNum,String text,int[][] rowhb) throws RowsExceededException, WriteException{

  for(int i=0i<rowspani++){

  for(int j=0j<colspanj++){

  if(i!=0||j!=0){

 text=""

  }

  Label label = new Label(realColNum+j,realRowNum+i,text)

   WritableFont countents = new WritableFont(WritableFont.TIMES,10) // 设置单元格内容,字号12  

   WritableCellFormat cellf = new WritableCellFormat(countents ) 

   cellf.setAlignment(jxl.format.Alignment.CENTRE)//把水平对齐方式指定为居中

   cellf.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE)//把垂直对齐方式指定为居

   label.setCellFormat(cellf)

   sheet.addCell(label)

   rowhb[realRowNum+i][realColNum+j]=1

  }

  }

  sheet.mergeCells(realColNum,realRowNum, realColNum+colspan-1,realRowNum+rowspan-1)

}

public static int getRealColNum(int[][] rowhb,int i,int realColNum){

while(rowhb[i][realColNum]!=0){

realColNum++

}

return realColNum

}

///根据colgroups设置表格的列宽

public static void setColWidth(Elements colgroups,WritableSheet sheet){

 if(colgroups.size()>0){

 Element colgroup=colgroups.get(0)

 Elements cols=colgroup.getElementsByTag("col")

 for(int i=0i<cols.size()i++){

 Element col=cols.get(i)

 String strwd=col.attr("width")

 if(col.attr("width")!=""){

 int wd=Integer.parseInt(strwd)

 sheet.setColumnView(i,wd/8)

 }

 

 }

 

 }

}

//toExcel是根据html文件地址生成对应的xls

public static void toExcel(String fileName,String excelName)throws IOException{

Document doc=getDoc(fileName)

    String title = doc.title()

    ///得到样式,以后可以根据正则表达式解析css,暂且没有找到cssparse

    Elements style= doc.getElementsByTag("style")

    ///得到Table,demo只演示输入一个table,以后可以用循环遍历tables集合输入所有table

    Elements tables= doc.getElementsByTag("TABLE")    

    if(tables.size()==0){

    return

    }

    Element table=tables.get(0)

   //得到所有行

    Elements trs = table.getElementsByTag("tr")

    ///得到列宽集合

    Elements colgroups=table.getElementsByTag("colgroup")

    

   try {

   //文件保存到classpath目录下面

    String path=HTMLTOExcel.class.getResource("/").getPath()

path+=excelName+".xls"

 System.out.println(path)

    WritableWorkbook book = Workbook.createWorkbook(new File(path))    

    WritableSheet sheet = book.createSheet("人事关系", 0)  

    setColWidth(colgroups,sheet)

    mergeColRow(trs,sheet)    

    book.write()    

    book.close()    

   } catch (RowsExceededException e) {

        e.printStackTrace()

   } catch (WriteException e) { 

        e.printStackTrace()

   }

}

}

解析html文件的例子文档地址:http://blog.csdn.net/androidwuyou/article/details/52636821