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

背景 最近在做的项目,需要从网络上抓取部分数据,在使用正则对数据进行匹配、提取时发现,表格类的数据因表格头和数据部分分离,直接定位这样的数据,有一定的困难(好吧,承认了,是自己没有好的解决思路_),所以简化下在解析前对内容进行预处理,方便后续的正则解析,比如:通过冗余,将表格头内容附加到内容前,使用特殊符号进行分隔,这样正则就能准确定位提取内容了。
一小步 思路有了,第一个问题就是,表格的行、列合并(rowspan、colspan)问题,那就需要把表格展开,代码是一个二维表格展开的方法,但是在生产环境下还得解决像并发这样的问题,这里就不展开了
上代码 【使用jsoup将表格内容展开|使用jsoup将表格内容展开 方便Regex进行内容定位】使用库 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 法文

    推荐阅读