如何使用Jsoup按类名获取元素?

时间:2015-05-31 09:31:41

标签: android html jsoup

我正试图从Android中的雅虎财经网页中提取一些数据。

特定股票的摘要页面和历史价格页面都包含许多带有class =“yfnc_tabledata1”的td,我需要从中提取数字。我可以在历史价格页面中轻松提取这些td中的数据,如下所示:

Document document = Jsoup.connect("http://finance.yahoo.com/q/hp?s=LUX.MI").get();
            Elements html = document.getElementsByClass("yfnc_tabledata1");

但似乎这个相同的代码段不适用于摘要页面,例如:

Document document = Jsoup.connect("http://finance.yahoo.com/q?s=LUX.MI").get();
            Elements html = document.getElementsByClass("yfnc_tabledata1");

在阅读其他问题后,我也尝试了以下3种方法,但没有成功:

Elements html = document.select(".yfnc_tabledata1");
html.size() = 0
Elements html = document.getElementsByAttributeValueContaining("class", "yfnc_tabledata1");
html.size() = 0
Element el = document.getElementById("table#table1");
Elements html = el.getAllElements();
html.size() = error due for el being null 

知道我做错了吗?

这是摘要页面的片段,我无法从中提取数据:

<div class="yui-u first yfi-start-content">
  <div class="yfi_quote_summary">
    <div id="yfi_quote_summary_data" class="rtq_table">
      <table id="table1">
        <tr>
          <th scope="row" width="48%">Prev Close:</th>
          <td class="yfnc_tabledata1">61.15</td>
        </tr>
        <tr>
          <th scope="row" width="48%">Open:</th>
          <td class="yfnc_tabledata1">61.45</td>
        </tr>
        <tr>
          <th scope="row" width="48%">Bid:</th>
          <td class="yfnc_tabledata1">
            <span id="yfs_b00_lux.mi">61.20</span>
          </td>
        </tr>
        <tr>
          <th scope="row" width="48%">Ask:</th>
          <td class="yfnc_tabledata1">
            <span id="yfs_a00_lux.mi">61.30</span>
          </td>
        </tr>
        <tr>
          <th scope="row" width="48%">1y Target Est:</th>
          <td class="yfnc_tabledata1">N/A</td>
        </tr><tr><th scope="row" width="48%">Beta:</th>
        <td class="yfnc_tabledata1">N/A</td>
        </tr>
        <tr>
          <th scope="row" width="54%">Next Earnings Date:</th>
          <td class="yfnc_tabledata1">N/A</td>
        </tr>
      </table>
      <table id="table2">
        <tr>
          <th scope="row" width="48%">Day's Range:</th>
          <td class="yfnc_tabledata1">
            <span>
              <span id="yfs_g53_lux.mi">60.75</span>
            </span> - 
            <span>
            <span id="yfs_h53_lux.mi">61.60</span>
            </span>
          </td>
        </tr>
        <tr>
          <th scope="row" width="48%">52wk Range:</th>
          <td class="yfnc_tabledata1">
            <span>34.74</span>
            - <span>62.50</span>
          </td>
        </tr>
        <tr>
          <th scope="row" width="48%">Volume:</th>
          <td class="yfnc_tabledata1">
            <span id="yfs_v53_lux.mi">1,057,884</span>
          </td>
        </tr>
        <tr>
          <th scope="row" width="48%">Avg Vol 
            <span class="small">(3m)</span>
            :</th>
          <td class="yfnc_tabledata1">740,908</td>
        </tr>
        <tr>
          <th scope="row" width="48%">Market Cap:</th>
          <td class="yfnc_tabledata1"
              ><span id="yfs_j10_lux.mi">29.36B</span>
          </td>
        </tr>
        <tr>
          <th scope="row" width="48%">P/E 
            <span class="small">(ttm)</span>
            :</th>
          <td class="yfnc_tabledata1">42.28</td>
        </tr>
        <tr>
          <th scope="row" width="48%">EPS 
            <span class="small">(ttm)</span>
            :</th>
          <td class="yfnc_tabledata1">1.45</td>
        </tr>
        <tr class="end"><th scope="row" width="48%">Div &amp; Yield:</th>
          <td class="yfnc_tabledata1">N/A (N/A) </td>
        </tr>
      </table>
    </div>
  </div>

EDIT1

我发现为什么同一个代码段在两个页面上都不起作用。 该片段与历史价格页面一起正常工作,如果我尝试检索该页面的html,我可以看到它与我在Chrome页面的视图源中看到的完全相同。摘要页面也不会发生同样的情况:当我尝试检索它的html时,它与chrome中的view-source无关,它会检索不同的东西,我无法确切地知道它是什么。所以现在的问题是:为什么这个代码片段没有检索到正确的页面html?

Document document = Jsoup.connect("http://finance.yahoo.com/q?s=LUX.MI").get();
            temp = document.html();

2 个答案:

答案 0 :(得分:0)

  

最初由OP发现的解决方案:

EDIT2-解决方案: 如果发生在其他任何人身上:如果Jsoup.connect(url).get()由于某种原因没有检索到正确的页面,首先在不使用Jsoup的情况下获取字符串中的HTML,并且仅在使用Jsoup解析String之后。

HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://google.com");
HttpResponse response = httpclient.execute(httpget); 
HttpEntity entity = response.getEntity();

InputStream is = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
    sb.append(line + "\n");

String html = sb.toString();
is.close();
Document document = Jsoup.parse(html);

答案 1 :(得分:0)

另一种解决方案......

这是OP解决方案的一个变种。在这里,我们直接为Jsoup提供httpclient提供的输入流。 Jsoup能够解析输入流。

String url = "http://google.com";

HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
HttpResponse response = httpclient.execute(httpget); 
HttpEntity entity = response.getEntity();

InputStream is = entity.getContent();
Document document = Jsoup.parse(is, null, url);
is.close();

...但是如何按类名选择元素?

要按类名选择元素,需要一个简单的CSS选择器。例如:

  • HTML
<div class="container open">
    <!-- ... -->
</div>
  • CSS选择器

下面列表中的任何选择器都可以找到上一个HTML部分中显示的div。

div.container
div.open
div.container.open

它仍然无法运作......

有时候这不会起作用,因为你可以在浏览器中看到的最终HTML是由一些javascript代码动态生成的。 Jsoup(撰写本文时为1.8.3)没有Javascript支持。它无法运行javascript。