在 Yahoo Finance 上使用 JSoup 提取 Table 数据

Extracting Table Data with JSoup on Yahoo Finance

尝试练习使用 JSoup 从 table 中提取数据。无法弄清楚为什么我不能从

中提取 "Shares Outstanding" 字段

https://finance.yahoo.com/q/ks?s=AAPL+Key+Statistics

这里有两次尝试,其中 's' 是 AAPL:

public class YahooStatistics {
String sharesOutstanding = "Shares Outstanding:";

public YahooStatistics(String s)    {
    String keyStatisticsURL = ("https://finance.yahoo.com/q/ks?s="+s+"+Key+Statistics");

//Attempt 1       
    try {
        Document doc = Jsoup.connect(keyStatisticsURL).get();

        for (Element table : doc.select("table.yfnc_datamodoutline1"))  {
            for (Element row : table.select("tr"))  {
                Elements tds = row.select("td");
                for (Element td : tds.select(sharesOutstanding)) {
                    System.out.println(td.ownText());
                }
            }
        }
    }
    catch (IOException ex)   {
        ex.printStackTrace();
    }

//Attempt 2

    try {
    Document doc = Jsoup.connect(keyStatisticsURL).get();

        for (Element table : doc.select("table.yfnc_datamodoutline1"))    {
            for (Element row : table.select("tr"))   {
                Elements tds = row.select("td");
                for (int j = 0; j < tds.size() - 1; j++) {
                    Element td = tds.get(j);
                    if ((td.ownText()).equals(sharesOutstanding)) {
                    System.out.println(tds.get(j+1).ownText());
                    }
                }
            }
        }
    }
    catch(IOException ex)   {
        ex.printStackTrace();
    }

尝试 return:构建成功,仅此而已。

我在我的浏览器上禁用了 JavaScript 并且 table 仍然显示,所以我假设这不是写在 JavaScript 而是 HTML.

如有任何建议,我们将不胜感激。

编辑后关于您的来源的说明:

  • 你应该比较 ownText() 而不是 text()text() 为您提供所有元素及其所有子元素的组合文本。在本例中,元素包含 Shares Outstanding<font size="-1"><sup>5</sup></font>:,因此其组合文本为 "Shares Outstanding5:"。如果您使用 ownText,它将只是 "Shares Outstanding:"
  • 注意冒号 (:)。相应地更新 sharesOutstanding 中的值。
  • 你传错了URL。 AAPL.
  • 后面应该有一个 +
  • 您当前的查询(至少是第二次尝试)返回元素两次,因为有一个嵌套 table 所以它找到了两次 TD。

您可以在找到匹配项后中断循环,返回到您的原始版本(进行上述更正)- 参见注释 - 或者您可以尝试使用更复杂的查询,该查询只会匹配一次:

Elements elems = doc.select("td.yfnc_tablehead1:containsOwn("+sharesOutstanding+") + td.yfnc_tabledata1");

if ( ! elems.isEmpty() ) {
    System.out.println( elems.get(0).owntext() );
}

这个 selector 为您提供所有 td 元素,其 class 是 yfnc_tabledata1,其紧邻的前一个兄弟是 td 元素,其 class 是 yfnc_tablehead1 并且其自己的文本包含 "Shares Outstanding:" 字符串。这基本上应该 select 您需要的确切 TD。

注意:这个答案的前一个版本是关于 Elements.select()Element.select() 之间的区别的长篇大论。事实证明我完全错了,你的原始版本应该有效——如果你纠正了以上四点。因此,直接设置记录:Elements 上的 select() 实际上会查看每个元素的内部,结果列表可能包含原始列表中与 selection 匹配的任何元素的后代.抱歉。