使用rome 1.15.0解析XML Feed时报hr元素未闭合错误如何解决?
问题产生原因
- 目标站点反爬策略拦截了程序默认请求:你在浏览器中直接访问链接可以拿到符合规范的XML内容,但Java原生
URL请求默认没有携带标准浏览器头,服务器会返回HTML格式的错误页(比如403禁止访问页),这类页面中的<hr>是HTML非闭合写法,完全不符合XML语法规范,因此解析器直接抛出标签未闭合错误。 - Rome 1.15.0默认使用严格XML解析规则:哪怕是合法XML内容中嵌入了未转义的HTML未闭合标签,或者存在微小的格式不规范,解析器都会直接报错,没有自动容错处理。
可行修复方案
方案1:添加标准请求头规避反爬
手动构造HTTP请求,模拟浏览器访问,确保拿到的是XML格式内容再交给Rome解析,示例代码如下:
package com.dolphin.soa.post; import com.rometools.rome.feed.synd.SyndFeed; import com.rometools.rome.io.ParsingFeedException; import com.rometools.rome.io.SyndFeedInput; import com.rometools.rome.io.XmlReader; import lombok.extern.slf4j.Slf4j; import java.io.InputStream; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; /** * @author dolphin */ @Slf4j public class MiniExample { public static void main(String[] args) { try { URL url = new URL("http://yechengfu.com/feed.xml"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // 模拟Chrome浏览器请求头 connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"); connection.setRequestProperty("Accept", "application/xml, text/xml, */*"); connection.setConnectTimeout(5000); connection.setReadTimeout(10000); // 校验响应状态和内容类型,确保拿到的是XML if (connection.getResponseCode() == 200 && connection.getContentType().contains("xml")) { try (InputStream inputStream = connection.getInputStream()) { SyndFeed feed = new SyndFeedInput().build(new XmlReader(inputStream)); // 后续feed处理逻辑 } } else { log.error("请求返回非XML内容,状态码:{},内容类型:{}", connection.getResponseCode(), connection.getContentType()); } connection.disconnect(); } catch (ConnectException connectException) { log.error("rss parse error", connectException); } catch (ParsingFeedException e){ log.error("rss parse error", e); }catch (Exception e) { log.error("rss parse error", e); } } }
方案2:开启Rome容错解析模式
如果确认拿到的是XML内容,只是存在少量格式不规范,可以开启Rome的自动修复能力,代码如下:
SyndFeedInput input = new SyndFeedInput(); // 开启XML格式自动修复 input.setXmlHealerOn(true); // 关闭DTD校验,避免不必要的解析失败和安全风险 input.setAllowDoctypes(false); SyndFeed feed = input.build(new XmlReader(inputStream));
方案3:升级Rome版本
当前使用的1.15.0版本存在不少解析相关的已知bug,升级到最新稳定版1.18.0可以提升容错性,依赖修改为:
api "com.rometools:rome:1.18.0"
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

