You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Java抓取Morningstar数据时实体引用需以';'结尾的错误

错误原因
  • 你使用的Java原生DocumentBuilder是严格XML格式校验的解析器,目标站点返回的是普通HTML页面,存在大量未转义的&字符(通常出现在页面内的链接参数、资源地址中),XML解析器会将&后的字符识别为实体引用,要求必须以;结尾,匹配失败就会抛出该SAX解析异常。
解决方法

方案1(推荐):替换为HTML专用解析器Jsoup

Jsoup对非规范HTML的兼容性极高,原生支持CSS选择器查询,代码实现更简单,还自带HTTP请求能力,不需要手动处理HTTP连接:

  1. 先引入Jsoup依赖(Maven示例):
<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.17.2</version>
</dependency>
  1. 替换原有解析逻辑:
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

public class MSExtrctor {
    public static void main(String[] args) throws Exception {
        String url = "https://www.morningstar.co.uk/uk/funds/snapshot/snapshot.aspx?id=F00000WYA1";
        // 模拟浏览器UA避免被站点拦截
        Document doc = Jsoup.connect(url)
                .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
                .get();
        Elements starEl = doc.select("span[class*=rating_sprite star]");
        String classVal = starEl.attr("class");
        // 提取星级,class值格式为rating_sprite starX,X就是星级数字
        String starLevel = classVal.replace("rating_sprite star", "");
        System.out.println("基金星级:" + starLevel);
    }
}

方案2:保留原有XML/XPath逻辑

如果必须使用现有XPath逻辑,需要先用JTidy工具将原始HTML清理为符合XML规范的XHTML格式,再交给DOM解析器处理:

  1. 引入JTidy依赖
<dependency>
    <groupId>net.sf.jtidy</groupId>
    <artifactId>jtidy</artifactId>
    <version>r938</version>
</dependency>
  1. 在原有代码调用builder.parse前,先用JTidy处理输入流:
// 获取到connection.getInputStream()后替换原有builder.parse逻辑
Tidy tidy = new Tidy();
tidy.setXHTML(true);
tidy.setQuiet(true);
tidy.setShowWarnings(false);
org.w3c.dom.Document document = tidy.parseDOM(connection.getInputStream(), null);

内容的提问来源于stack exchange,提问作者serah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 08:45:04