Android Java中如何匹配Div标签提取EBIT等财务数据?
Yahoo财经财报数据提取问题解决方案
问题梳理
- 从AAPL财报页提取EBIT的年度(9/30/2022-2019)和季度(9/30/2022、6/30/2022、3/31/2022、12/31/2021)数据,输出键值对或集合
- 提取对应Div标签的日期值
- 解决资产负债表折叠行数据提取及季度数据AJAX动态加载问题
原代码核心问题
- 误用正则匹配HTML:正则不适用于解析HTML结构,Jsoup自带的CSS选择器是更可靠的方案
- 正则语法错误:正则中未定义捕获组,
group(1)会抛出异常;^$强制匹配div完整HTML,实际页面元素存在空格/隐藏节点导致匹配失败 - 遍历效率低下:遍历所有div标签完全没必要,直接定位目标元素即可
修正后的代码方案
1. 年度EBIT数据提取(静态页面)
利用Jsoup的CSS选择器直接定位目标元素,无需正则:
private static void fetchAnnualEBIT(String url) throws IOException { String userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"; Document doc = Jsoup.connect(url).userAgent(userAgent).get(); // 提取年度日期表头 Elements dateSpans = doc.select("div[data-test=\"fin-col\"] span"); List<String> dates = new ArrayList<>(); for (Element span : dateSpans) { dates.add(span.text().trim()); } Log.d("Annual Dates", dates.toString()); // 提取EBIT行数据 Element ebitRow = doc.selectFirst("div:containsOwn(EBIT)"); if (ebitRow != null) { Elements dataSpans = ebitRow.select("div[data-test=\"fin-col\"] span"); List<String> ebitData = new ArrayList<>(); for (Element span : dataSpans) { ebitData.add(span.text().trim()); } // 组装键值对 Map<String, String> ebitMap = new HashMap<>(); for (int i = 0; i < Math.min(dates.size(), ebitData.size()); i++) { ebitMap.put(dates.get(i), ebitData.get(i)); } Log.d("Annual EBIT Data", ebitMap.toString()); } else { Log.d("EBIT Row", "Not found"); } }
2. 季度数据处理(AJAX动态加载)
Yahoo的季度数据通过AJAX请求加载,需直接调用其数据接口,示例用OkHttp实现:
private static void fetchQuarterlyEBIT(String symbol) throws IOException { OkHttpClient client = new OkHttpClient(); String url = "https://query1.finance.yahoo.com/v10/finance/quoteSummary/" + symbol + "?modules=incomeStatementHistoryQuarterly"; Request request = new Request.Builder() .url(url) .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); String json = response.body().string(); // 解析JSON提取EBIT季度数据,这里可使用Gson/Jackson等库 Log.d("Quarterly EBIT JSON", json); } }
注:需添加OkHttp依赖,解析JSON时可根据返回结构提取对应日期和EBIT值
3. 资产负债表折叠行数据提取
流动负债的折叠行可通过选择器定位父行后,提取其下属的折叠内容:
private static void fetchCurrentLiabilities(String url) throws IOException { String userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"; Document doc = Jsoup.connect(url).userAgent(userAgent).get(); // 定位流动负债父行 Element currentLiabilitiesRow = doc.selectFirst("div:containsOwn(Current Liabilities)"); if (currentLiabilitiesRow != null) { // 提取折叠的子项数据(需注意页面结构,可能是相邻的div或子元素) Elements childRows = currentLiabilitiesRow.nextElementSiblings().select("div[data-test=\"fin-row\"]"); for (Element row : childRows) { String itemName = row.selectFirst("div[data-test=\"fin-col\"] span").text().trim(); Elements values = row.select("div[data-test=\"fin-col\"] span"); Log.d("Current Liabilities Item", itemName + ": " + values.get(1).text().trim()); } } }
关键注意事项
- User-Agent设置:必须使用现代浏览器的UA,否则Yahoo会拦截请求
- API接口稳定性:Yahoo的非公开API可能随时变更,需定期验证接口地址
- JSON解析依赖:处理动态数据时,建议引入Gson或Jackson简化JSON解析
内容的提问来源于stack exchange,提问作者Zac1
相关产品推荐
相关产品推荐

