簡體   English   中英

為什么JSoup不讀取頁面的所有元素?

[英]Why JSoup does not read all the elements of the page?

今天,我開始與JSoup一起“玩”。 我想知道JSoup到底有多強大,所以我尋找了一個包含很多元素的網頁,然后嘗試檢索所有元素。 我找到了想要的東西: http : //www.top1000.ie/companies

這是一個列表,其中包含許多相似的元素(1000個)(列表的每個公司)。 只需更改其中的文本,以便我嘗試檢索的就是該文本,但是我只能獲取前20個元素,而不能獲取其余元素。

這是我的簡單代碼:

package retrieveInfo;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class Retrieve {

    public static void main(String[] args) throws Exception{
        String url = "http://www.top1000.ie/companies";
        Document document = Jsoup.connect(url)
                 .userAgent("Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0")
                 .timeout(1000*5)
                 .get();

        Elements companies = document.body().select(".content .name");
        for (Element company : companies) {
            System.out.println("Company: " + company.text());
        }
    }

}

我雖然可能是頁面沒有時間加載,所以這就是為什么我將.timeout(1000*5)等待5秒,但是我只能得到列表的前20個元素的原因。

JSoup是否有可以從網頁檢索的元素限制? 我認為不應這樣做,因為它似乎是為此目的而准備的,因此我認為我的代碼中缺少某些內容。

任何幫助,將不勝感激。 提前致謝!

新答案:

我查看了您要解析的網站。 問題是,站點的第一個調用僅加載了前20個comanpies。 其余通過AJAX加載。 而且Jsoup不會解釋或運行JavaScript。 您可以為此使用selenium webdriver,或者直接找出AJAX調用。

舊:

如果沒有通過maxBodySize()方法告知,則Jsoup限制為1M。 因此,您可能需要這樣做:

Document document = Jsoup.connect(url)
             .userAgent("Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0")
             .maxBodySize(0)
             .timeout(1000*5)
             .get();

當心,以上完全關閉了大小限制。 這可能不是一個好主意,因為Jsoup在內存中構建DOM,因此您可能會遇到大型文檔的內存堆大小問題。 如果確實有這樣的問題,則可能有助於切換到另一個基於SAX的HTML解析器。

該站點最初僅加載前20個元素。 向下滾動時,腳本將加載下一個元素塊( POSThttp://www.top1000.ie/companies?page=2 )。 然后,腳本將接收到的元素添加到DOM。

但是,您從POST獲得的對/companies?page=的響應是JSON。

{
 "worked":true,
 "has_more":true,
 "next_url":"/companies?page=3",
 "html":"..."
 ...
}

此處的“ html”字段似乎包含將添加到DOM中的元素。

使用Jsoup獲取數據將是乏味的,因為Jsoup將在實際JSON周圍添加所有類型的標簽,並且還將轉義某些字符。

我認為你會使用過的方式之一更好地在這個崗位 ,連接到http://www.top1000.ie/companies?page=1並逐頁讀取數據頁。

編輯這是一個最小示例,說明如何使用HttpURLConnectionminimal-json解析器解決此問題。

void readPage(int page) throws IOException {
    URL url = new URL("http://www.top1000.ie/companies?page=" + page);

    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setDoOutput(true);
    connection.setRequestMethod("POST");

    try (OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream())) {
        // no need to post any data for this page
        writer.write("");
    }

    if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
        try (Reader reader = new InputStreamReader(connection.getInputStream())) {
            String html = Json
                .parse(reader)
                .asObject()
                .getString("html", "");

            Elements companies = Jsoup
                .parse(html)
                .body().select(".content .name");

            for (Element company : companies) 
                System.out.println("Company: " + company.text());
        }
    } else {
        // handle HTTP error code.
    }
}

在這里,我們使用HttpURLConnectionPOST請求(不包含任何數據)發送到URL,使用JSON解析器從結果中獲取"html"字段,然后使用Jsoup對其進行Jsoup 只需循環調用要讀取的頁面的方法即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM