我只想抓一些黑客新闻故事和我的代码:
import org.apache.http.client.fluent.Request;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Logger;
import java.util.stream.IntStream;
public class HackCrawler {
private static String getUrlResponse(String url) throws IOException {
return Request.Get(url).execute().returnContent().asString();
}
private static String crawlItem(int id) {
try {
String json = getUrlResponse(String.format("https://hacker-news.firebaseio.com/v0/item/%d.json", id));
if (json.contains("\"type\":\"story\"")) {
return json;
}
} catch (IOException e) {
System.out.println("crawl " + id + " failed");
}
return "";
}
public static void main(String[] args) throws FileNotFoundException {
Logger logger = Logger.getLogger("main");
PrintWriter printWriter = new PrintWriter("hack.json");
for (int i = 0; i < 10000; i++) {
logger.info("batch " + i);
IntStream.range(12530671 - (i + 1) * 100, 12530671 - i * 100)
.parallel()
.mapToObj(HackCrawler::crawlItem).filter(x -> !x.equals(""))
.forEach(printWriter::println);
}
}
}
现在抓取100(1批)物品需要3秒钟。
我发现parallel
使用多线程会加速(大约5次),但我不知道如何进一步优化它。
有人可以提出一些建议吗?
答案 0 :(得分:1)
要实现Fayaz意味着我将使用Jetty Http Client异步功能(https://webtide.com/the-new-jetty-9-http-client/)。
httpClient.newRequest("http://domain.com/path")
.send(new Response.CompleteListener()
{
@Override
public void onComplete(Result result)
{
// Your logic here
}
});
此客户端在内部使用Java NIO来监听每个连接使用单个线程的传入响应。然后,它将内容分派给不涉及任何阻塞I / O操作的工作线程。
您可以尝试使用每个目的地的最大连接数(目的地基本上是主机)
由于您正在大量加载单个服务器,因此这应该非常高。
答案 1 :(得分:0)
以下步骤可帮助您入门。
基本上,您将拥有一个生产者线程,可以从网站和处理这些响应的多个消费者那里获得响应。