Categories

利用JTidy将HTML转为XML

信息检索快结课了,于是开始琢磨着做个什么东西,应用一下所学到的知识。做什么呢?

搭一个完整的搜索引擎?虽然有luencenutch等开源工具包的支持,可是时间上似乎不够。做网络爬虫?做网页去重?好像算法都挺复杂的。思来想去,最后我选定了“正文提取”,主要是觉得这个挺简单,应该很快就能做出来。

然而实际情况与想法总是差距甚远,从星期五到星期天下午,断断续续的,我一直在不停做这个东西。最后以也没做出什么成果,只有一些零星的思路,NND,以后等时机成熟了一定要搞出来!!

  • JTidy:HTML->XML 要分析源文件,就得先将其规范化。老师课件上讲的工具是JTidy,我用的就是这个。据说它可以方便的对HTML进行清理,生成XHTML或XML文件。网络上有关JTidy的资料少得可怜,遇到了问题连资料都没的查,只有非常简洁的API和源代码可供参考。也难怪,最新版本的JTidy竟然是2001年8月发布的,都已经快8年了,莫非这工具已经终止开发了? 典型的代码类似于下面,输入文件为1001.htm,输出文件为output.xml:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    
    package test;
     
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
     
    import org.w3c.tidy.Configuration;
    import org.w3c.tidy.Tidy;
     
    public class JTidyTest
    {
        public static void main(String[] args)
        {
            Tidy tidy = new Tidy(); // obtain a new Tidy instance
            tidy.setXmlOut(true); // set desired config options using tidy setters
            tidy.setQuoteNbsp(false);
            tidy.setQuoteMarks(false);
            tidy.setQuoteAmpersand(false);
            tidy.setCharEncoding(Configuration.RAW);
            try
            {
                FileInputStream in = new FileInputStream(new File("1001.htm"));
                FileOutputStream out = new FileOutputStream(new File("output.xml"));
                tidy.parseDOM(in, out); // run tidy, providing an input and output stream
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }

    转换完以后,我用firefox打开生成的XML文件来检验转换是否正确,发现它对很多网页都不能生成正确的结果。比如HTML源文件中有这样一段代码

    1
    2
    3
    
    <script type="text/javascript">
        document.write('| <a href="https://passport.baidu.com/?login&tpl=sp&tpl_reg=sp&u=http://hi.baidu.com' + encodeURIComponent('/icycandy') + '">登录</a>');
    </script>

    转换后的XML仍然有这段代码。用firefox打开,报错说“XML解析错误:未组织好”,大概是指&tpl中的tpl没有定义。这样的情况大多数都出现在链接中,那么可以把HTML中的所有链接用HTML Parser先去掉,然后再用JTidy处理。然而很可惜的是,HTML Parser对于不规范的HTML文档也是无能为力。也许用正则表达式来过虑掉链接是一种方法。后来我又担心如果正文中出现&tpl这种情况该怎么办?实际上这种担心是多余的,正文中的&一般会被替换为&amp;,就像双引号一般被替换为&quot;一样。

    另 外一个头疼的问题是中文编码,中文转换后在XML中显示为乱码。网上很多贴子说中文乱码可 以通过设置tidy的编码解决:tidy.setCharEncoding(Configuration.RAW);或 tidy.setCharEncoding(Configuration.ISO2022);。这样生成的XML文件编码格式是GB2312,用 UltraEdit打开确实能显示出中文了,可是用firefox打开仍然是乱码。而下一步从XML中提取信息时,DOM4J只接受UTF-8的编码格 式。我的解决办法是另外写一个类,按字节从XML中读入字符,然后用UTF-8写回到文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    
    package test;
     
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
     
    public class GB2UTF
    {
        String fileName;
     
        public GB2UTF(String fileName)
        {
            this.fileName = fileName;
        }
     
        public void convert()
        {
            try
            {
                File f = new File(fileName);
                FileInputStream in = new FileInputStream(f);
                InputStreamReader reader = new InputStreamReader(in, "GB2312");// 以GB2312编码读入文件
     
                File tmpFile = File.createTempFile("GB2312", ".xml");// 创建临时文件,以"GB2312"为前缀,".html"为后缀
                FileOutputStream out = new FileOutputStream(tmpFile);// 将文件转化为字符流
                OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");// 目标编码为UTF-8
     
                writer.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
                char[] buffer = new char[10240]; // 文件缓冲区
                int len = 0; // 使用字符读取方式,循环读取源文件内容
                while ((len = reader.read(buffer)) != -1) // 转换后写入目标文件中
                {
                    writer.write(buffer, 0, len);
                }
     
                writer.close();
                reader.close();
                out.close();
                in.close();
     
                f.delete(); // 删除原文件
                tmpFile.renameTo(f); // 用原文件名保存转换后的文件
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
     
        public static void main(String[] args)
        {
            new GB2UTF("output.xml").convert();
        }
    }
  • DOM4J:XML->TXT因为上一步的XML不能正确生成,所以这一步我没有具体实践。如果上一步能生成规范的XML,那么可以利用DOM4J从XML文件创建出一棵DOM树。然后遍历树中的节点,判断该节点是否包含了正文。如果不是,就删掉该节点。从而最后树中剩下的节点就包含了网页的正文,直接从中抽取出信息即可。非正文信息一般是广告、链接群、字体样式等。

2 comments to 利用JTidy将HTML转为XML

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

  

  

  

*