[java] 汇率换算器实现(3)

 

[java] 汇率换算器实现(3)

 

[java] 汇率换算器实现(3)

2 前言

在上一篇文章中, 我们充分了解了正则表达式的使用细则. 那么此处就结合java.util.regex库的使用, 实现HtmlTableParse类, 用于提取网页中table的内容.

3 提取简单表单信息

html表格的示例如下:

<table border="1">
<tr>
  <th>Month</th>
  <th>Savings</th>
</tr>
<tr>
  <td>January</td>
  <td>$100</td>
</tr>
</table>

将代码合并为一行后得:

<table border="1"><tr><th>Month</th><th>Savings</th></tr><tr><td>January</td><td>$100</td></tr></table>

针对上面一行书写相关的正则表达式, 获取表单中的内容:

<table.*?>((<tr>.*?</tr>)+?)</table>

这样 $1 就对应着 <tr><th>Month</th><th>Savings</th></tr><tr><td>January</td><td>$100</td></tr> , 接着对匹配后的结果再次进行处理, 使用得正则表达式为:

<tr>(.*?)</tr>

如此, 匹配得到每一行的内容, 如: $1 = <th>Month</th><th>Savings</th>, 接着再使用正则表达式:

<th>(.*?)</th>

就能够得到不同元素, 如:Month, Savings

3.1 Java正则表达式实现简单表单提取

import java.util.regex.*;

public class HtmlTable {
    public static void main(String[] args) {
        // 目标
        String target = "<table border=\"1\"><tr><th>Month</th><th>Savings</th></tr><tr><td>January</td><td>$100</td></tr></table>";

        // 正则表达式
        String regexTable = "<table.*?>((<tr>.*?</tr>)+?)</table>";
        String regexRow = "<tr>(.*?)</tr>";
        String regexEle = "(?:<th>|<td>)(.*?)(?:</th>|</td>)";

        Pattern r = Pattern.compile(regexTable);

        // 表单的匹配
        Matcher mTable = r.matcher(target);

        while (mTable.find()) {
            String strRow = mTable.group(1);
            System.out.println("Row: "+strRow);

            // 表单中每一行得匹配
            Matcher mRow = Pattern.compile(regexRow).matcher(strRow);
            while (mRow.find()) {
                String strEle = mRow.group(1);
                System.out.println("\tTh or td: " + strEle);

                // 每一行中每个元素得匹配
                Matcher mEle = Pattern.compile(regexEle).matcher(strEle);
                while (mEle.find()) {
                    String result = mEle.group(1);
                    System.out.println("\t\tElement: " + result);
                }
            }
        }
    }
}

 

 

但当上述的程序直接运用到 www.usd-cny.com 上时, 发现最终输出的结果为空. 也就是说一点都没有得到匹配. 这是因为上述的匹配规则过于特殊导致的, 下面给出更为普遍的匹配规则, 能够匹配如下面的格式:

格式:
<TR bgcolor=""></TR>
<TD WIDTH=""></TD>
<TD>  <DIV ALIGN="center"><b><font color"">element</font></b></td>

匹配规则:
   final static String REGEX_TABLE = "<table.*?>\\s*?((<tr.*?>.*?</tr>)+?)\\s*?</table>";
   final static String REGEX_ROW = "<tr.*?>\\s*?(.*?)\\s*?</tr>";
   final static String REGEX_ELE = "(?:<th.*?>|<td.*?>)(?:\\s*<.*?>)*(?:&nbsp;)?(.*?)(?:&nbsp;)?(?:\\s*<.*?>)*?\\s*(?:</th>|</td>)";

3.2 重新整理HtmlTable类

package com.cnblogs.grassandmoon;

import java.util.regex.*;
import java.io.*;

public class HtmlTable {
    final static String ELEMENT_SEPARATOR = "\001";
    final static String ROW_SEPARATOR = "\002";

    final static String REGEX_TABLE = "<table.*?>\\s*?((<tr.*?>.*?</tr>)+?)\\s*?</table>";
    final static String REGEX_ROW = "<tr.*?>\\s*?(.*?)\\s*?</tr>";
    final static String REGEX_ELE = "(?:<th.*?>|<td.*?>)(?:\\s*<.*?>)*(?:&nbsp;)?(.*?)(?:&nbsp;)?(?:\\s*<.*?>)*?\\s*(?:</th>|</td>)";


    public static String extract(int nStartLine, int nEndLine, BufferedReader br)
    throws IOException {
        String line;
        String target = "";
        String elements = "";
        int i = 0;
        // iStartLine[0] = 78;
        // iEndLine[0] = 303;

        while ((line = br.readLine()) != null) {
            ++i;
            if (i < nStartLine) continue;
            line.trim();
            target = target + line;
            if (i >= nEndLine) break;
        }

        // 正则表达式
        Pattern r = Pattern.compile(REGEX_TABLE, Pattern.CASE_INSENSITIVE);

        // 表单的匹配
        Matcher mTable = r.matcher(target);

        if (mTable.find()) {
            String strRows = mTable.group(1).trim();

            // 表单中每一行得匹配
            Matcher mRow = Pattern.compile(REGEX_ROW, Pattern.CASE_INSENSITIVE).matcher(strRows);
            while (mRow.find()) {
                boolean firstEle = true;
                String strEle = mRow.group(1).trim();
                // System.out.println("\nTh or td: " + strEle);

                // 每一行中每个元素得匹配
                Matcher mEle = Pattern.compile(REGEX_ELE, Pattern.CASE_INSENSITIVE).matcher(strEle);

                if (!elements.equals(""))
                    elements = elements + ROW_SEPARATOR;
                while (mEle.find()) {
                    String result = mEle.group(1).trim();
                    if (firstEle)
                        elements = elements + result;
                    else
                        elements = elements + ELEMENT_SEPARATOR + result;
                    firstEle = false;
                    // System.out.println("\nElement: " + result);
                }
                if (!elements.equals("")) {
                    int len = elements.length();
                    elements = elements.substring(0, len-2);
                }
            }
        }

        return new String(elements);
    }
}

 

4 总结

然后再次对实现代码进行了整理, 完整的代码见:RateExchange @ git

再后续的文中, 将介绍如何使用jsoup从网页中提取相应的信息.

 

 

Date: 2014-05-12 Mon

Author: Zhong Xiewei

Org version 7.8.11 with Emacs version 24

Validate XHTML 1.0

你可能感兴趣的:(java)