Recebo uma SocketTimeoutException em Jsoup: Tempo limite de leitura esgotado

100


Eu recebo uma SocketTimeoutException quando tento analisar vários documentos HTML usando Jsoup.
Por exemplo, obtive uma lista de links:

<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>

Para cada link, analiso o documento vinculado à URL (do atributo href) para obter outras informações nessas páginas.
Posso imaginar que demore muito, mas como desligar essa exceção?
Aqui está o rastreamento de pilha completo:

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)

Obrigado camaradas!

EDIT: Hum ... Desculpe, acabei de encontrar a solução:

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

Espero que isso possa ser útil para outra pessoa ... :)

C. Maillard
fonte
3
O código que você adicionou em sua edição define o tempo limite para infinito. Isso é indesejável na maioria dos casos de uso. É muito melhor usar um tempo limite específico conforme indicado na resposta do MarcoS, mesmo se o tempo limite for longo.
stepanian de
2
Eu acho que timeout(0)isso fará com que o Jsoup conecte a url novamente e novamente até conectar.
Evan Hu

Respostas:

138

Eu acho que você pode fazer

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

que define o tempo limite para 10s.

MarcoS
fonte
3
121 votos positivos, mas nenhuma explicação de por que isso corrige o problema? Por que isso resolve o problema quando o padrão é, ao que parece, 30 segundos?
Alan Hay
2
@AlanHay minha resposta foi sugerir resolver o problema definindo um tempo limite, não usando esse valor específico como tempo limite :)
MarcoS
26

Ok - então, tentei oferecer isso como uma edição à resposta do MarcoS, mas a edição foi rejeitada. No entanto, as seguintes informações podem ser úteis para futuros visitantes:

De acordo com os javadocs , o tempo limite padrão para um org.jsoup.Connectioné 30 segundos.

Como já foi mencionado, isso pode ser definido usando timeout(int millis)

Além disso, como as notas de OP na edição, isso também pode ser definido usando timeout(0). No entanto, como os javadocs afirmam:

Um tempo limite de zero é tratado como um tempo limite infinito.

amaidment
fonte
3
Definir um tempo limite infinito é uma má ideia na maioria dos casos. Use um tempo limite longo, mas sempre especifique um. Veja a resposta do MarcoS.
stepanian
3
@stepanian - para ser claro, não estou defendendo a definição de um tempo limite infinito. Isso havia sido sugerido como a solução pelo OP, embora eu quisesse direcionar os usuários futuros às implicações disso. De fato, quando postei minha 'resposta' originalmente, indiquei que achava que deveria ser uma edição na resposta de MacroS, pois havia algumas informações adicionais que poderiam ser úteis para futuros usuários ... mas a edição foi rejeitada.
amaidment
O tempo limite padrão não é 3 segundos, mas 30 segundos (30.000 milis), você pode vê-lo em jsoup.org/apidocs/org/jsoup/Connection.html
aldok
3

Eu tive o mesmo erro:

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)

e apenas a configuração .userAgent(Opera)funcionou para mim.

Então, usei o Connection userAgent(String userAgent)método da classe Connection para definir o agente de usuário Jsoup.

Algo como:

Jsoup.connect("link").userAgent("Opera").get();
invzbl3
fonte
-1

Isso deve funcionar: Jsoup.connect(url.toLowerCase()).timeout(0);.

Prasanna Mendon
fonte
-6

Defina o tempo limite durante a conexão do jsoup.

Gaurab Pradhan
fonte
2
Por favor, adicione mais informações sobre sua resposta
Joe Taras
Por favor, suporte sua resposta com explicações e trechos de código, se necessário.
Swapnil B.