Otrzymuję SocketTimeoutException w Jsoup: upłynął limit czasu odczytu


100


Otrzymuję SocketTimeoutException, gdy próbuję przeanalizować wiele dokumentów HTML za pomocą Jsoup.
Na przykład mam listę linków:

<a href="www.domain.com/url1.html">link1</a>
<a href="www.domain.com/url2.html">link2</a>
<a href="www.domain.com/url3.html">link3</a>
<a href="www.domain.com/url4.html">link4</a>

Dla każdego linku parsuję dokument powiązany z adresem URL (z atrybutu href), aby uzyskać inne informacje na tych stronach.
Mogę sobie więc wyobrazić, że zajmuje to dużo czasu, ale jak wyłączyć ten wyjątek?
Oto cały ślad stosu:

java.net.SocketTimeoutException: Read timed out
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(Unknown Source)
    at java.io.BufferedInputStream.fill(Unknown Source)
    at java.io.BufferedInputStream.read1(Unknown Source)
    at java.io.BufferedInputStream.read(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at java.net.HttpURLConnection.getResponseCode(Unknown Source)
    at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:381)
    at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:364)
    at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:143)
    at org.jsoup.helper.HttpConnection.get(HttpConnection.java:132)
    at app.ForumCrawler.crawl(ForumCrawler.java:50)
    at Main.main(Main.java:15)

Dziękuję kumple!

EDYCJA: Hum ... Przepraszamy, właśnie znalazłem rozwiązanie:

Jsoup.connect(url).timeout(0).get();

Mam nadzieję, że to może być przydatne dla kogoś innego ... :)


3
Kod dodany w edycji ustawia limit czasu na nieskończony. Jest to niepożądane w większości przypadków użycia. Znacznie lepiej jest użyć określonego limitu czasu, jak wskazano w odpowiedzi MarcoS, nawet jeśli limit czasu jest długi.
stepanian

2
Myślę, że timeout(0)spowoduje to, że Jsoup połączy adres URL raz po raz, aż się połączy.
Evan Hu,

Odpowiedzi:


138

Myślę, że możesz to zrobić

Jsoup.connect("...").timeout(10 * 1000).get(); 

co ustawia limit czasu na 10 sekund.


3
121 głosów za, ale brak wyjaśnienia, dlaczego to rozwiązuje problem? Dlaczego to rozwiązuje problem, skoro domyślną wartością jest 30 sekund?
Alan Hay

2
@AlanHay, moja odpowiedź sugerowała rozwiązanie problemu poprzez ustawienie limitu czasu, a nie używanie tej konkretnej wartości jako limitu czasu :)
MarcoS

26

Ok - próbowałem to zaproponować jako zmianę odpowiedzi MarcoS, ale zmiana została odrzucona. Niemniej jednak następujące informacje mogą być przydatne dla przyszłych odwiedzających:

Według Javadocs , domyślny limit czasu za org.jsoup.Connectionto 30 sekund.

Jak już wspomniano, można to ustawić za pomocą timeout(int millis)

Ponadto, jak zauważa OP w edycji, można to również ustawić za pomocą timeout(0). Jednak, jak stwierdza javadocs:

Limit czasu równy zero jest traktowany jako nieskończony limit czasu.


3
W większości przypadków ustawienie nieskończonego limitu czasu jest złym pomysłem. Użyj długiego limitu czasu, ale zawsze go określ. Zobacz odpowiedź MarcoS.
stepanian

3
@stepanian - żeby było jasne, nie jestem zwolennikiem ustawiania nieskończonego limitu czasu. Zostało to zasugerowane jako rozwiązanie przez PO, chociaż chciałem zwrócić uwagę przyszłych użytkowników na konsekwencje tego. Rzeczywiście, kiedy pierwotnie zamieściłem moją „odpowiedź”, wskazałem, że uważam, że powinna to być zmiana odpowiedzi MacroS, ponieważ pojawiły się dodatkowe informacje, które mogą być przydatne dla przyszłych użytkowników ... ale zmiana została odrzucona.
wezwanie

Domyślny limit czasu to nie 3 sekundy, ale 30 sekund (30000 milisekund), możesz to zobaczyć na jsoup.org/apidocs/org/jsoup/Connection.html
aldok.


3

Miałem ten sam błąd:

java.net.SocketTimeoutException: Read timed out
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:171)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)

i tylko ustawienie .userAgent(Opera)działało dla mnie.

Więc użyłem Connection userAgent(String userAgent)metody klasy Connection do ustawienia agenta użytkownika Jsoup.

Coś jak:

Jsoup.connect("link").userAgent("Opera").get();


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.