html解析器——jericho-html-3.3解析table

原文部分内容来源于网上其他博客,不过由于时间长了,忘记参考的是谁的了,在此说声抱歉。。

先贴出一段html页面:

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=GBK">
<title>HTML Parser</title>
<meta name="generator" content="Namo WebEditor">
</head>
<body>
<table width=620 border=0 cellpadding=1 cellspacing=0 bgcolor=#0066cc>
	<tr>
		<td width=100%>
		<table width=100% border=0 cellpadding=4 cellspacing=0 bgcolor=#D3E5FB>
			<tr bgcolor=#D3E5FB>
				<td width=20%><font size="2" face="Arial,Verdana"><b>想学习
				Name</b></font><br>
				</td>
				<td width=13%><font size="2" face="Arial,Verdana"><b>Result</b></font><br>
				</td>
				<td width=8%><font size="2" face="Arial,Verdana"><b>Time</b></font><br>
				</td>
				<td width=59%><font size="2" face="Arial,Verdana"><b>Synopsis</b></font><br>
				</td>
			</tr>
			<tr bgcolor=#eeeeee>
				<td width=20%><font size="1" face="Arial,Verdana"><b>9</b>
				想学习</font><br>
				</td>
				<td width=13%><font size="1" face="Arial,Verdana"><font
					color=#ff0033>+FAIL</font> <a
					href="v4_wireless_802.1x_full/cdrouter_dhcp_20.txt">想学习</a></font><br>
				</td>
				<td width=8%><font size="1" face="Arial,Verdana">12:31</font><br>
				</td>
				<td width=59%><font size="1" face="Arial,Verdana">想学习</font><br>
				</td>
			</tr>
			<tr bgcolor=#ffffff>
				<td width=20%><font size="1" face="Arial,Verdana"><b>1</b>
				cdrouter_basic_1</font><br>
				</td>
				<td width=13%><font size="1" face="Arial,Verdana">Pass <a
					href="v4_wireless_802.1x_full/cdrouter_basic_1.txt">想学习</a></font><br>
				</td>
				<td width=8%><font size="1" face="Arial,Verdana">00:00</font><br>
				</td>
				<td width=59%><font size="1" face="Arial,Verdana">想学习</font><br>
				</td>
			</tr>
		</table>
		</td>
	</tr>
</table>
</body>
</html>

对于这个页面来说我想取出所有的td里面的文字内容,该怎么办呢,如果用正则表达式,我还真是难以写出正确的,来解析出我所要的结果。

在网上搜索了一下jericho-html-3.3这个插件,用来解析table,的确很方便。

代码如下:

package com.xxx.hbuassys.test;

import java.net.URL;
import java.util.Iterator;
import java.util.List;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.HTMLElementName;
import net.htmlparser.jericho.Segment;
import net.htmlparser.jericho.Source;

public class HtmlParser
{
    public static void main(String[] args) throws Exception
    {
        String sourceUrlString="test.html";

        if(sourceUrlString.indexOf(':') == -1)
            sourceUrlString ="file:"+sourceUrlString;
        Source source=new Source(new URL(sourceUrlString));
        List Elements_TABLE=source.getAllElements(HTMLElementName.TABLE);
        Elements_TABLE.remove(0);//由于table相互嵌套,我们需要的是第二个,所以删掉第一个
        Iterator it_TABLE = Elements_TABLE.iterator();
        while(it_TABLE.hasNext())
        {
            Element Element_TABLE = (Element)it_TABLE.next();
//        	System.out.println("**"+Element_TABLE.toString()+"\n**");
            Segment getContent_TABLE = (Segment)Element_TABLE.getContent();
            List Elements_TR = getContent_TABLE.getAllElements(HTMLElementName.TR);
            Iterator it_TR = Elements_TR.iterator();
            while(it_TR.hasNext())
            {
                Element Element_TR = (Element)it_TR.next();
                Segment getContent_TR = (Segment)Element_TR.getContent();
                List Elements_FONT = getContent_TR.getAllElements(HTMLElementName.FONT);
                Iterator it_FONT = Elements_FONT.iterator();
                int i = 1;
                while(it_FONT.hasNext())
                {
                    Element Element_FONT = (Element)it_FONT.next();
                    Segment getContent_FONT = (Segment)Element_FONT.getContent();
                    String a1 = getContent_FONT.toString();
                    System.out.println(i + " = " + Element_FONT.getContent().getTextExtractor().toString());
                    i++;
                }
                System.out.println();
            }
        }
    }
}

结果:

1 = 想学习 Name

2 = Result

3 = Time

4 = Synopsis

1 = 9 想学习

2 = +FAIL 想学习

3 = +FAIL

4 = 12:31

5 = 想学习

1 = 1 cdrouter_basic_1

2 = Pass 想学习

3 = 00:00

4 = 想学习

大致的思路就是,先取出所有的table标签,然后对需要的table进行解析,取出里面的tr,在从tr里面取出td这样就可以得到我们需要的内容了。

如果只说到这,那么就跟网上其他人讲的没有什么区别了。

因为项目的需要,使用此插件发现了一个问题:

如果html页面的编码是UTF-8的格式,那么解析出来的内容就会是乱码,如果直接对这些乱码编码,采用new String(str.getBytes(),"GBK");等之类的操作都不能解决问题,本人亲自测试过。

例如html页面变为:

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
<title>HTML Parser</title>
<meta name="generator" content="Namo WebEditor">
</head>
<body>
<table width=620 border=0 cellpadding=1 cellspacing=0 bgcolor=#0066cc>
	<tr>
		<td width=100%>
		<table width=100% border=0 cellpadding=4 cellspacing=0 bgcolor=#D3E5FB>
			<tr bgcolor=#D3E5FB>
				<td width=20%><font size="2" face="Arial,Verdana"><b>想学习
				Name</b></font><br>
				</td>
				<td width=13%><font size="2" face="Arial,Verdana"><b>Result</b></font><br>
				</td>
				<td width=8%><font size="2" face="Arial,Verdana"><b>Time</b></font><br>
				</td>
				<td width=59%><font size="2" face="Arial,Verdana"><b>Synopsis</b></font><br>
				</td>
			</tr>
			<tr bgcolor=#eeeeee>
				<td width=20%><font size="1" face="Arial,Verdana"><b>9</b>
				想学习</font><br>
				</td>
				<td width=13%><font size="1" face="Arial,Verdana"><font
					color=#ff0033>+FAIL</font> <a
					href="v4_wireless_802.1x_full/cdrouter_dhcp_20.txt">想学习</a></font><br>
				</td>
				<td width=8%><font size="1" face="Arial,Verdana">12:31</font><br>
				</td>
				<td width=59%><font size="1" face="Arial,Verdana">想学习</font><br>
				</td>
			</tr>
			<tr bgcolor=#ffffff>
				<td width=20%><font size="1" face="Arial,Verdana"><b>1</b>
				cdrouter_basic_1</font><br>
				</td>
				<td width=13%><font size="1" face="Arial,Verdana">Pass <a
					href="v4_wireless_802.1x_full/cdrouter_basic_1.txt">想学习</a></font><br>
				</td>
				<td width=8%><font size="1" face="Arial,Verdana">00:00</font><br>
				</td>
				<td width=59%><font size="1" face="Arial,Verdana">想学习</font><br>
				</td>
			</tr>
		</table>
		</td>
	</tr>
</table>
</body>
</html>

得到的结果是:

1 = ???? Name

2 = Result

3 = Time

4 = Synopsis

1 = 9 ????

2 = +FAIL ????

3 = +FAIL

4 = 12:31

5 = ????

1 = 1 cdrouter_basic_1

2 = Pass ????

3 = 00:00

4 = ????

采用的方法是:改变<meta http-equiv="content-type" content="text/html;charset=UTF-8">变为:<meta http-equiv="content-type" content="text/html;charset=GBK">

详细情况,参考代码如下:

package com.xxx.hbuassys.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Iterator;
import java.util.List;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.HTMLElementName;
import net.htmlparser.jericho.Segment;
import net.htmlparser.jericho.Source;

public class HtmlParser
{
    public static void main(String[] args) throws Exception
    {
    	BufferedReader reader=new BufferedReader(new InputStreamReader(new FileInputStream(new File("test.html"))));
//    	BufferedReader reader=new BufferedReader(new FileReader(new File("test.html")));
    	StringBuilder sbf=new StringBuilder();
    	String str=null;
    	while((str=reader.readLine())!=null){
    		sbf.append(str).append("\n");
    	}
    	//解决中文乱码的方法
    	String html=sbf.toString().replace("<meta http-equiv=\"content-type\" content=\"text/html;charset=UTF-8\">", "<meta http-equiv=\"content-type\" content=\"text/html;charset=GBK\">");
//    	System.out.println(html);
        Source source=new Source(html);
        List Elements_TABLE=source.getAllElements(HTMLElementName.TABLE);
        Elements_TABLE.remove(0);//由于table相互嵌套,我们需要的是第二个,所以删掉第一个
        Iterator it_TABLE = Elements_TABLE.iterator();
        while(it_TABLE.hasNext())
        {
            Element Element_TABLE = (Element)it_TABLE.next();
//        	System.out.println("**"+Element_TABLE.toString()+"\n**");
            Segment getContent_TABLE = (Segment)Element_TABLE.getContent();
            List Elements_TR = getContent_TABLE.getAllElements(HTMLElementName.TR);
            Iterator it_TR = Elements_TR.iterator();
            while(it_TR.hasNext())
            {
                Element Element_TR = (Element)it_TR.next();
                Segment getContent_TR = (Segment)Element_TR.getContent();
                List Elements_FONT = getContent_TR.getAllElements(HTMLElementName.FONT);
                Iterator it_FONT = Elements_FONT.iterator();
                int i = 1;
                while(it_FONT.hasNext())
                {
                    Element Element_FONT = (Element)it_FONT.next();
                    Segment getContent_FONT = (Segment)Element_FONT.getContent();
                    String a1 = getContent_FONT.toString();
                    System.out.println(i + " = " + Element_FONT.getContent().getTextExtractor().toString());
                    i++;
                }
                System.out.println();
            }
        }
    }
}

结果如下:

1 = 想学习 Name

2 = Result

3 = Time

4 = Synopsis

1 = 9 想学习

2 = +FAIL 想学习

3 = +FAIL

4 = 12:31

5 = 想学习

1 = 1 cdrouter_basic_1

2 = Pass 想学习

3 = 00:00

4 = 想学习

html解析器——jericho-html-3.3解析table,布布扣,bubuko.com

时间: 2024-10-21 18:10:32

html解析器——jericho-html-3.3解析table的相关文章

使用Scala基于词法单元的解析器定制EBNF范式文法解析

一.前言 近期在做Oracle迁移到Spark平台的项目上遇到了一些平台公式翻译为SparkSQL(on Hive)的需求,而Spark采用亲妈语言Scala进行开发.分析过大概需求过后,拟使用编译原理中的EBNF范式模式,进行基于词法的文法解析.于是拟采用传统的正则词法解析到EBNF文法解析的套路来实现,直到发现了StandardTokenParsers这个Scala基于词法单元的解析器类. 二.平台公式及翻译后的SparkSQL 平台公式的样子如下所示: 1 if(XX1_m001[D003

PHP XML Expat 解析器

PHP XML Expat 解析器 内建的 Expat 解析器使在 PHP 中处理 XML 文档成为可能. XML 是什么? XML 用于描述数据,其焦点是数据是什么.XML 文件描述了数据的结构. 在 XML 中,没有预定义的标签.您必须定义自己的标签. 如需学习更多关于 XML 的知识,请访问我们的 XML 教程. Expat 是什么? 如需读取和更新 - 创建和处理 - 一个 XML 文档,您需要 XML 解析器. 有两种基本的 XML 解析器类型: 基于树的解析器:这种解析器把 XML

【Android进阶】解析XML文件之使用DOM解析器

在前面的文章中,介绍了使用SAX解析器对XML文件进行解析,SAX解析器的优点就是占用内存小.这篇文章主要介绍使用DOM解析器对XML文件进行解析.DOM解析器的优点可能是理解起来比较的直观,当然,每个人对不同的解析方法可能有不同的喜好.但是DOM解析器有个比较大的缺点,就是占用内存比较多,在Android中的XML解析中,还是更推荐其他的解析方式. 下面介绍使用DOM解析器对XML进行解析. 下面是我们需要解析的xml文件 <?xml version="1.0" encodin

笔记:XML-解析文档-流机制解析器(SAX、StAX)

DOM 解析器完整的读入XML文档,然后将其转换成一个树型的数据结构,对于大多数应用,DOM 都运行很好,但是,如果文档很大,并且处理算法又非常简单,可以在运行时解析节点,而不必看到完整的树形结构,那么我们应该使用流机制解析器(streaming parser),Java 类库提供的流解析机制有 SAX 解析器和 StAX 解析器,SAX 解析器是基于事件回调机制,而 StAX解析器提供了解析事件的迭代器. 使用SAX解析器 SAX 解析器在解析XML 输入的组成部分时会报告事件,在使用 SAX

解析器组合子

本文引自:http://www.ibm.com/developerworks/cn/java/j-lo-compose/ Ward Cunningham 曾经说过,干净的代码清晰地表达了代码编写者所想要表达的东西,而优美的代码则更进一步,优美的代码看起来就像是专门为了要解决的问题而存在的.在本文中,我们将展示一个组合式解析器的设计.实现过程,最终的代码是优美的,极具扩展性,就像是为了解析特定的语法而存在的.我们还会选取 H.248 协议中的一个例子,用上述的组合式解析器实现其语法解析器.读者在这

通过pull解析器操作安卓的xml

通过pull解析器操作安卓的xml 例子定义了一个javabean用于存放上面解析出来的xml内容, 这个javabean为Person,代码请见本页下面备注: ============================================================================================== 使用pull解析器解析person.xml文件 public class PersonService {  public static List g

AFN解析器里的坑

AFN框架是用来用来发送网络请求的,它的好处是可以自动给你解析JSON数据,还可以发送带参数的请求AFN框架还可以监测当前的网络状态,还支持HTTPS请求,分别对用的类为AFNetworkReachabilityManager,AFSecurityPolicy 虽然AFN可以发送请求,但是里面有许多坑,  1.你想要得到正确的JSON数据必须要:网络请求成功,服务器返回的必须是JSON 数据,自己(AFN)还能够解析,也就是说你发送的请求,返回的数据类型必须是JSON数据,而且必须以JSON结尾

Android下使用pull解析器生成XML文件、读取XML文件

Android下使用Pull解析器 1,Pull解析器的运行方式与SAX解析器相似.它提供了类似的事件,如:开始元素和结束元素事件. 2,使用parser.next()可以进入下一个元素并触发相应事件. 3,事件将作为一个int数值被发送,因此可以使用一个switch对相应的事件进行处理. 4,当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型节点的值. 5,相关API: 获得当前节点事件类型:parser.getEventType(); 获得下一节点事件类型

FFmpeg的H.264解码器源代码简单分析:解析器(Parser)部分

本文继续分析FFmpeg中libavcodec的H.264解码器(H.264 Decoder).上篇文章概述了FFmpeg中H.264解码器的结构:从这篇文章开始,具体研究H.264解码器的源代码.本文分析H.264解码器中解析器(Parser)部分的源代码.这部分的代码用于分割H.264的NALU,并且解析SPS.PPS.SEI等信息.解析H.264码流(对应AVCodecParser结构体中的函数)和解码H.264码流(对应AVCodec结构体中的函数)的时候都会调用该部分的代码完成相应的功

解析XML文件之使用SAM解析器

XML是一种常见的传输数据方式,所以在开发中,我们会遇到对XML文件进行解析的时候,本篇主要介绍使用SAM解析器,对XML文件进行解析. SAX解析器的长处是显而易见的,那就是SAX并不须要将全部的文档都载入内存之后才进行解析.SAX是事件驱动机制的,也就是碰到元素节点.文本节点.文档节点的时候,都会触发一定的事件.我们仅仅须要在对应的回调事件里面进行对应的处理就能够了.由于这个特点,所以SAX解析占用的内存比較少.其它的解析方式,比方下一节要介绍的DOM解析器,则占用内存比較多.在解析比較小的