使用jsoup将表格内容展开 方便Regex进行内容定位

背景

最近在做的项目,需要从网络上抓取部分数据,在使用正则对数据进行匹配、提取时发现,表格类的数据因表格头和数据部分分离,直接定位这样的数据,有一定的困难(好吧,承认了,是自己没有好的解决思路_),所以简化下在解析前对内容进行预处理,方便后续的正则解析,比如:通过冗余,将表格头内容附加到内容前,使用特殊符号进行分隔,这样正则就能准确定位提取内容了。

一小步

思路有了,第一个问题就是,表格的行、列合并(rowspan、colspan)问题,那就需要把表格展开,代码是一个二维表格展开的方法,但是在生产环境下还得解决像并发这样的问题,这里就不展开了

上代码

使用库 JSoup,具体使用可以参考官方文档

表格转换

import java.io.FileInputStream;
import java.io.InputStream;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.parser.Tag;
import org.jsoup.select.Elements;

public class TableConvert {
/**
     * 将表格进行二维展开
     * @param table
     * @return
     */
    public Element[][] toTable(Element table) {
        if (!table.nodeName().equals("table")) {
            return null;
        }

        Elements tableRows = table.getElementsByTag("tr");
        int tableHeight = tableRows.size();

        //找 展开的最大列数,存在问题:如果某一列 全部使用 colspan 且其值都 大于2,有可能出错
        int tableWidth = 0;
        for (int tr_idx = 0; tr_idx < tableHeight; tr_idx++) {
            Elements tds = tableRows.get(tr_idx).select("td, th");
            int td_size = tds.size();
            if (td_size > tableWidth)
                tableWidth = td_size;
        }

        System.out.println("tableHeight:"+tableHeight+";tableWidth:"+tableWidth);
        
        if (tableHeight < 2 || tableWidth < 2)
            return null;

        //定义二维数组
        Element[][] result = new Element[tableHeight][tableWidth];

        //使用canreplace 来占位
        for(int i=0;i tableWidth ,直接抛出异常
        try {
            for (int rowIndex = 0; rowIndex < tableHeight; rowIndex++) {
                Elements colCells = tableRows.get(rowIndex).select("td, th");

                System.out.println("row"+rowIndex+":\n"+colCells);              
                int pointIndex = 0;//列的索引
                for (int colIndex=0; colIndex < colCells.size();colIndex++) {                   
                    Element currentCell=colCells.get(colIndex);
                    //放到二维数组
                    if(result[rowIndex][colIndex].tagName().equalsIgnoreCase("canreplace"))
                    {
                        result[rowIndex][colIndex] = currentCell;
                        pointIndex=colIndex;
                    }else {
                        pointIndex=colIndex+1;
                        //查找可放置 一直找到一个可替换
                        while(!result[rowIndex][pointIndex].tagName().equalsIgnoreCase("canreplace") && pointIndex< tableWidth ) {
                            pointIndex++;                   
                            System.out.println("===rowIndex==="+pointIndex+"====tempColIndex==="+pointIndex+"==="+result[rowIndex][pointIndex].tagName());
                        }
                        if(pointIndex < tableWidth && result[rowIndex][pointIndex].tagName().equalsIgnoreCase("canreplace") ) {
                            result[rowIndex][pointIndex] = currentCell;
                        }else {
                            throw new Exception("table格式有错误!");
                        }
                    }
                    
                    
                    // 检查 colspan
                    int colspan = 1;
                    if (currentCell.hasAttr("colspan")) {
                        colspan = Integer.valueOf(currentCell.attr("colspan"));
                        currentCell.removeAttr("colspan");
                    }                   
                
                    //复制表格内容
                    if (colspan > 1) {      
                        for(int emptyColindex =1;emptyColindex < colspan  ;emptyColindex++)
                        {
                            pointIndex++;                           
                            while(!result[rowIndex][pointIndex].tagName().equalsIgnoreCase("canreplace") && pointIndex< tableWidth ) {
                                pointIndex++;                   
                                System.out.println("===rowIndex==="+pointIndex+"====tempColIndex==="+pointIndex+"==="+result[rowIndex][pointIndex].tagName());
                            }
                            if(pointIndex < tableWidth && result[rowIndex][pointIndex].tagName().equalsIgnoreCase("canreplace") ) {
                                result[rowIndex][pointIndex] = currentCell;
                            }else {
                                throw new Exception("table格式有错误!");
                            }
                        }
                    }

                    // 检查rowspan
                    int rowspan = 1;
                    if (currentCell.hasAttr("rowspan")) {
                        rowspan = Integer.valueOf(currentCell.attr("rowspan"));
                        currentCell.removeAttr("rowspan");
                    }

                    if (rowspan > 1) {
                        for (int i = 1; i < rowspan; i++) {
                            if (i >= tableHeight)  break; // ignore bad rowspans
                            System.out.println("===rowIndex==="+pointIndex+"====tempColIndex==="+pointIndex+"==="+result[rowIndex][pointIndex].tagName());
                            result[rowIndex+i][colIndex] = currentCell;//new Element(invalidTag, "");
                        }
                    }
                }
            }
        }       catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        return result;
    }

辅助打印

    public void printTable(Element[][] table) {
        if (table == null) return;

        System.out.println("==================");
        for (int rowIndex = 0; rowIndex < table.length; rowIndex++) {
            System.out.print("|");
            for (int colIndex = 0; colIndex < table[rowIndex].length; colIndex++) {
                if (table[rowIndex][colIndex] == null) {
                    System.out.print("  ");
                } else {
                    System.out.print(table[rowIndex][colIndex].text());
                }
                System.out.print(" |");
            }
            System.out.println();
        }
        System.out.println("==================");
    }

运行测试

public static void main(String[] args) {
        String url = "d:\\Untitled-2.html";
        InputStream in;
        TableConvert tableConvert = new TableConvert();
        try {
            in = new FileInputStream(url);;
            Document doc = Jsoup.parse(in, null, "");

            for (Element aTable : doc.getElementsByTag("table")) {
                Elements subtables = aTable.getElementsByTag("table");
                subtables.remove(aTable);
                if(subtables.size() == 0) {
                    System.out.println("converting table...");
                    Element[][] result = tableConvert.toTable(aTable);
                    if (null != result)
                        tableConvert.printTable(result);
                    else
                        System.out.println("Could not convert table.");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

测试文件内容

序号 内容
1
英文
2 法文

你可能感兴趣的:(使用jsoup将表格内容展开 方便Regex进行内容定位)