我有这样的页面:
www.foo1.bar
www.foo2.bar
www.foo3.bar
.
.
www.foo100.bar
我正在使用库jsoup,并使用Thread:同时连接到每个页面
Thread matchThread = new Thread(task);
matchThread.start();
每个任务,连接到这样的页面,并解析HTML:
Jsoup.connect("www.fooX.bar").timeout(0).get();
获得大量这样的异常:
java.net.ConnectException: Connection timed out: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
at java.net.Socket.connect(Socket.java:529)
at sun.net.NetworkClient.doConnect(NetworkClient.java:158)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:388)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:523)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:227)
at sun.net.www.http.HttpClient.New(HttpClient.java:300)
at sun.net.www.http.HttpClient.New(HttpClient.java:317)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:970)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:911)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:836)
at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:404)
at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:391)
at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:157)
at org.jsoup.helper.HttpConnection.get(HttpConnection.java:146)
jsoup同时只允许1个线程吗?或者我做错了什么关于如何更快地连接到我的页面的任何建议,因为一个接一个需要很长时间
编辑:
所有700个线程都使用这种方法,也许这是问题所在。这个方法能处理这么多线程吗?或者它是单例的?
private static Document connect(String url) {
Document doc = null;
try {
doc = Jsoup.connect(url).timeout(0).get();
} catch (IOException e) {
System.out.println(url);
}
return doc;
}
EDIT:全线程代码
public class MatchWorker implements Callable<Match>{
private Element element;
public MatchWorker(Element element) {
this.element = element;
}
@Override
public Match call() throws Exception {
Match match = null;
Util.connectAndDoStuff();
return match;
}
}
我的全部700个元素:
Collection<Match> matches = new ArrayList<Match>();
Collection<Future<Match>> results = new ArrayList<Future<Match>>();
for (Element element : elements) {
MatchWorker matchWorker = new MatchWorker(element);
FutureTask<Match> task = new FutureTask<Match>(matchWorker);
results.add(task);
Thread matchThread = new Thread(task);
matchThread.start();
}
for(Future<Match> match : results) {
try {
matches.add(match.get());
} catch (Exception e) {
e.printStackTrace();
}
}
我试过这个:
ExecutorService executorService = Executors.newFixedThreadPool(5);
List<Future<Void>> handles = new ArrayList<Future<Void>>();
Future<Void> handle;
for (int i=0;i < 12; i++) {
handle = executorService.submit(new Callable<Void>() {
public Void call() throws Exception {
Document d = Jsoup.connect("http://www.google.hr").timeout(0).get();
System.out.println(d.title());
return null;
}
});
handles.add(handle);
}
for (Future<Void> h : handles) {
try {
h.get();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
executorService.shutdownNow();
它几乎立即完成并打印出正确的标题。也许你有防火墙问题?("连接超时"表示根本无法连接到服务器)
编辑:
我使用了JSoup 1.7.1
编辑^2:
AFAIK,这应该证明关系JSoup-Thread没有问题,因为它最终使用的是线程。。
编辑^3:
此外,如果您使用代理,以下是如何设置代理设置。
编辑^4:
public static Document connect(String url) {
Document doc = null;
try {
doc = Jsoup.connect(url).timeout(0).get();
} catch (IOException ex) {
ex.printStackTrace();
}
return doc;
}
调用函数重写:
public Void call() throws Exception {
System.out.println(App.connect("http://www.google.hr").title());
return null;
}
给出了相同的结果。我唯一能想到的是一些隐含的静态同步,但这没有多大意义,因为有一个超时异常:/pls发布线程代码
编辑:
必须离开几个小时。在这里,我所有的三个类都重写了
- 应用程序
- 匹配
- MatchWorker
仍然有效,速度较慢,但有效。我明确建议使用固定线程池来提高性能。
但是,我认为这一定是一个网络问题。祝你好运:)
编辑:
连接超时意味着根本无法访问目标服务器。AFAIK,这意味着(服务器从未发送/客户端从未接收)TCP SYN+ACK消息。
首先可以得出的结论是,目标服务器未联机,但造成此问题的原因可能更多,其中一个原因可能是目标服务器的请求过载(在极端情况下,这是(D)DoS攻击)。
目前,您尝试了parallel方法——每个请求都在自己的线程中:
1) 在700个线程中发出700个请求(实际上不是700个,但与您的操作系统所能承受的一样多)
2) 通过n<lt;700线程
首先,你可以尝试在每个请求中放入一个0-10 s的随机睡眠形式
Thread.currentThread.sleep(new Random().nextInt(10000))
但考虑到目前的结果,这可能不会奏效。下一步是用您在注释中提到的顺序方法取代并行方法——每个请求都是从单个主线程的for循环中一个接一个地运行的。你也可以试着把随机睡眠。
这是你能走的最优雅(最慢)的路,如果这不起作用,我不知道如何解决:(
编辑:
通过使用5个线程的线程池,我成功下载了1141场足球比赛的标题。
- 应用程序
- 请求
这类网站保护他们的数据是合乎逻辑的,所以当你在开发和测试(使用尽可能多的线程重复调用)时,他们的系统会将你(rIP)识别为一个想要他们所有数据的爬虫,他们显然不喜欢也不想要,所以他们禁止了你。他们甚至决定不拒绝你的请求,而是装死——因此连接超时。现在这是有道理的。Phew:)
如果这是正确的,您应该能够通过代理获取数据,但要礼貌并使用<10个线程:)
Jsoup只是调用HTTPUrlConnection进行连接。它对该连接是否失败没有影响。可能影响它的是防火墙和DDOS防护设备。网站拒绝大量的同时连接并不奇怪。