Java中使用JSoup按输入框SIZE属性解析HTML的问题
问题:JSoup提取HTML元素时触发数组越界异常
我需要解析系统生成的HTML格式错误文件,目标提取三类数据:
- 时间戳(对应HTML里的
<h4>标签) - 与Set对应的
SIZE=3输入框的值 - 与Id对应的
SIZE=5输入框的值
用JSoup处理时,时间戳能正常提取,但获取Set和Id值时直接抛出了数组越界异常。相关代码如下:
Document doc = Jsoup.parse(errorLog, "UTF-8", ""); Element body = doc.body(); Elements MessageTimestamps = doc.select("h4"); Elements MessageSets = doc.getElementsByAttributeValue("SIZE", "3"); Elements MessageID = doc.getElementsByAttributeValue("SIZE","5"); String[] timestampArray = new String[MessageTimestamps.size()]; System.out.println("Total: " + timestampArray.length); for(int i = 0; i< MessageTimestamps.size(); i++) { System.out.println("Timestamp: " + MessageTimestamps.get(i).text()); System.out.println("MessageSets: " + MessageSets.get(i).text()); }
执行后得到的结果:
Total: 6 Timestamp: 2020-07-16 10:24:22.614 java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
问题分析
从报错信息能直接看出来:MessageSets的元素数量是0,也就是JSoup根本没找到任何带有SIZE="3"属性的元素,但你循环的次数是时间戳的数量(6次),第一次循环就去取MessageSets.get(0),自然触发越界。
解决步骤
1. 先排查HTML属性的大小写匹配
HTML的属性名本身不区分大小写,但JSoup的getElementsByAttributeValue方法是大小写敏感的。如果你的HTML里输入框的属性是小写的size="3"(这是更常见的写法),那你用大写的"SIZE"去匹配就会找不到元素。
改成和HTML实际属性一致的写法,比如用小写:
Elements MessageSets = doc.select("input[size=3]"); // 同时指定是input元素,避免匹配其他标签 Elements MessageID = doc.select("input[size=5]");
如果不确定属性大小写,可以用不区分大小写的匹配方式:
// 用CSS选择器的i标记(CSS4特性,Jsoup支持) Elements MessageSets = doc.select("input[size=3 i]");
2. 增加空判断,避免越界
就算后续能找到元素,也不能保证时间戳和输入框的数量完全一致,所以循环里一定要先检查索引是否合法:
for(int i = 0; i< MessageTimestamps.size(); i++) { System.out.println("Timestamp: " + MessageTimestamps.get(i).text()); // 检查是否存在对应索引的Set元素 if (i < MessageSets.size()) { System.out.println("MessageSets: " + MessageSets.get(i).text()); } else { System.out.println("MessageSets: 未找到对应元素"); } // 同理检查Id元素 if (i < MessageID.size()) { System.out.println("MessageID: " + MessageID.get(i).text()); } else { System.out.println("MessageID: 未找到对应元素"); } }
3. 按HTML结构的对应关系提取(更可靠)
如果你的HTML里,每个时间戳和对应的Set/Id输入框是包裹在同一个父容器里的(比如每个消息项是一个<div>),那不要全局提取所有<h4>和所有size=3的输入框,而是先找到每个消息容器,再在容器内提取对应元素,这样能保证对应关系正确:
// 替换成你实际的消息容器选择器,比如每个消息项的类名是message-item Elements messageItems = doc.select(".message-item"); for (Element item : messageItems) { // 在当前容器内找时间戳 String timestamp = item.selectFirst("h4").text(); // 在当前容器内找size=3的输入框 String setValue = item.selectFirst("input[size=3]") != null ? item.selectFirst("input[size=3]").text() : "无值"; // 在当前容器内找size=5的输入框 String idValue = item.selectFirst("input[size=5]") != null ? item.selectFirst("input[size=5]").text() : "无值"; System.out.println("Timestamp: " + timestamp); System.out.println("MessageSets: " + setValue); System.out.println("MessageID: " + idValue); }
这种方式能避免全局提取时元素顺序不匹配的问题,比按索引一一对应更可靠。
内容的提问来源于stack exchange,提问作者Ron
相关产品推荐
相关产品推荐

