Jsoup SocketTimeoutException: 读取超时

104

当我使用Jsoup解析大量HTML文档时,我遇到了SocketTimeoutException的问题。

例如,我有一个链接列表:

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

对于每个链接,我解析与URL(从href属性中获取)链接的文档,以获取这些页面中的其他信息。

所以我可以想象它需要很多时间,但如何关闭这个异常?以下是完整的堆栈跟踪:

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)

3
你在编辑中添加的代码将超时时间设置为无限大。在大多数情况下,这是不可取的。最好像MarcoS的答案中所示使用一个特定的超时时间,即使超时时间很长也要如此。 - stepanian
2
我猜 timeout(0) 会让 Jsoup 一遍又一遍地重新连接该 URL,直到成功连接为止。 - Evan Hu
这似乎是问题作者C. Maillard找到的解决方案 Jsoup.connect(url).timeout(0).get();,根据早期版本 - Scratte
6个回答

147

我认为你可以这样做

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

将超时设置为10秒。


5
为什么有121个赞,但没有解释为什么这可以解决问题?默认值是30秒,那么这样做如何解决问题? - Alan Hay
2
@AlanHay 我的回答建议通过设置超时时间来解决问题,而不是使用那个特定的值作为超时时间 :) - MarcoS
2
@AlanHay,当Q&A编写时的默认超时时间为3秒。因此,任何增加都会降低套接字超时频率并有助于解决问题。我在2016年将默认值更新为30秒。 - Jonathan Hedley

27

好的 - 那么,我试图将这个作为MarcoS答案的编辑提供,但编辑被拒绝了。然而,以下信息可能对未来的访问者有用:

根据 javadocsorg.jsoup.Connection 的默认超时时间为30秒。

如先前已经提到的,可以使用timeout(int millis)进行设置。

此外,正如OP在编辑中所指出的那样,也可以使用timeout(0)进行设置。然而,正如javadocs所述:

0的超时时间被视为无限超时时间。


3
在大多数情况下,设置无限超时都是一个糟糕的主意。使用长时间超时,但始终要明确指定一个超时时间。请参考MarcoS的答案。 - stepanian
3
@stepanian - 清楚地说,我并不主张设置无限超时。这是由原帖作者提出的解决方案,尽管我想引导未来的用户了解这种做法的影响。事实上,当我最初发布我的“答案”时,我认为它应该作为对MacroS答案的编辑,因为还有一些额外的信息可能对未来的用户有用...但是这个编辑被拒绝了。 - amaidment
默认超时时间不是3秒,而是30秒(30000毫秒),您可以在https://jsoup.org/apidocs/org/jsoup/Connection.html中查看。 - aldok
当问题被编写时,超时时间曾为3秒。 - Jonathan Hedley

4

我遇到了同样的错误:

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)

只有设置.userAgent(Opera)对我有效。

因此,我使用了Connection类的Connection userAgent(String userAgent)方法来设置Jsoup用户代理。

类似这样:

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

3

1
在Java文档中:“默认超时时间为30秒(30,000毫秒)。超时时间为零将被视为无限超时。” https://jsoup.org/apidocs/org/jsoup/Connection.html - jeton

-1
这应该可以工作: Jsoup.connect(url.toLowerCase()).timeout(0);

-6

在 jsoup 连接时设置超时时间。


2
请在您的答案中添加更多信息。 - Joe Taras
如果需要,请支持您的答案以解释和代码片段。 - Swapnil B.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接