2

所以我正在为某个网站进行网络抓取。问题是:

给定一组 URL(按 100 到 1000 的顺序),我想以一种有效的方式检索每个 URL 的 HTML,特别是在时间方面。我需要能够每 5 分钟处理 1000 个请求。

这通常意味着使用线程池来执行来自一组尚未请求的 url 的请求。但在开始实施之前,我认为值得在这里问一下,因为我相信在进行网络抓取或网络爬虫时这是一个相当普遍的问题。

有没有我需要的图书馆?

4

4 回答 4

1

所以我正在为某个网站进行网络抓取。

您是在抓取单个服务器还是从多个其他主机抓取网站?如果是前者,那么您正在抓取的服务器可能不喜欢来自单个 i/p 的太多并发连接。

如果是后者,这确实是一个关于您应该从机器打开多少出站连接的一般问题。有物理限制,但它相当大。实际上,这将取决于该客户端的部署位置。连接性越好,它可以容纳的连接数就越多。

您可能想查看一个好的下载管理器的源代码,看看它们是否对出站连接数有限制。

绝对是用户异步 i/o,但您仍然可以很好地限制数量。

于 2013-01-17T02:17:14.387 回答
0

我将从研究异步通信开始。然后看看Netty

请记住,加载网页的速度总是有限制的。对于普通的家庭连接,大约需要一秒钟。在编写应用程序时要考虑到这一点。

于 2013-01-17T01:52:31.013 回答
0

您的带宽利用率将是您检索到的所有 HTML 文档的总和(加上一点开销),无论您如何对其进行切片(尽管某些 Web 服务器可能支持压缩的 HTTP 流,因此请务必使用能够接受它们的客户端)。

并发线程的最佳数量在很大程度上取决于您与相关站点的网络连接。只有实验才能找到最佳数字。您当然可以使用一组线程来检索 HTML 文档,并使用一组单独的线程来处理它们,以便更容易找到正确的平衡点。

我是 .NET 世界中用于 Web 抓取的HTML Agility Pack的忠实粉丝,但无法对 Java 提出具体建议。以下问题可能有助于找到一个好的、基于 Java 的抓取平台

使用 Java 进行网页抓取

于 2013-01-17T01:53:13.763 回答
0

http://wwww.Jsoup.org仅用于报废部分!我认为你应该自己实现线程池。

更新

如果这种方法适合您的需要,您可以在此处下载完整的类文件:http: //codetoearn.blogspot.com/2013/01/concurrent-web-requests-with-thread.html

    AsyncWebReader webReader = new AsyncWebReader(5/*number of threads*/, new String[]{
              "http://www.google.com",
              "http://www.yahoo.com",
              "http://www.live.com",
              "http://www.wikipedia.com",
              "http://www.facebook.com",
              "http://www.khorasannews.com",
              "http://www.fcbarcelona.com",
              "http://www.khorasannews.com",
            });

    webReader.addObserver(new Observer() {
      @Override
      public void update(Observable o, Object arg) {
        if (arg instanceof Exception) {
          Exception ex = (Exception) arg;
          System.out.println(ex.getMessage());
        } /*else if (arg instanceof List) {
          List vals = (List) arg;
          System.out.println(vals.get(0) + ": " + vals.get(1));
        } */else if (arg instanceof Object[]) {
          Object[] objects = (Object[]) arg;
          HashMap result = (HashMap) objects[0];
          String[] success = (String[]) objects[1];
          String[] fail = (String[]) objects[2];

          System.out.println("Failds");
          for (int i = 0; i < fail.length; i++) {
            String string = fail[i];
            System.out.println(string);
          }

          System.out.println("-----------");
          System.out.println("success");
          for (int i = 0; i < success.length; i++) {
            String string = success[i];
            System.out.println(string);
          }

          System.out.println("\n\nresult of Google: ");
          System.out.println(result.remove("http://www.google.com"));
        }
      }
    });
    Thread t = new Thread(webReader);
    t.start();
    t.join();
于 2013-01-17T04:03:56.383 回答