在 1-2 秒内同时建立 50+ URLConnections

Establish 50+ URLConnections simultaneously within 1-2 seconds

我正在尝试从 50 多个动态网页中抓取实时数据,并且需要每 1-2 秒更新一次数据。为此,我每 1/2 秒安排了一个计时器,它通过以下方法迭代 50 次(50 URLs):

public double fetchData(String link) {
        String data = null;
        try {
            URL url = new URL();
            urlConn = url.openConnection(link);
            InputStreamReader inStream = new InputStreamReader(urlConn.getInputStream());
            BufferedReader buff = new BufferedReader(inStream);

            /*code that scrapes webpage, stores value in "data"*/
            inStream.close();
            buff.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
}  

此方法有效,但每 URL 大约需要一秒钟,或总共需要 50 秒。我也尝试过 JSoup,希望使用以下代码可以克服延迟:

public double fetchData(String link, String identifier) {
        Document doc;
        String data = null;
        try {
            doc = Jsoup.connect(link).timeout(10*1000).get();
            data = doc.getElementById(identifier).parent().child(0).text();
        } catch (IOException e) {
            e.printStackTrace();
        } 
return data;
}

但有运行进入大致相同的处理时间。有没有更快的方法同时从动态网页中提取数据,无论是通过 URLConnection、JSoup 还是其他一些方法?

简短的回答是 "use threads"。为您要重复抓取的 50 多个 URL 中的每一个创建一个线程。

如果您使用 URLConnection、JSoup 或其他一些方式进行抓取,很可能不会有什么不同。实际瓶颈可能是由于:

  • 您要从中抓取的服务器上的负载和负载性能
  • 网络带宽
  • 网络延迟

第一个是你无法控制的(以积极的方式!)。最后两个……您也许可以解决,但只能通过向问题投入资金来解决。例如,您可以为更好的网络连接/路径付费,或者为替代托管付费以将您的抓取工具移动到您尝试抓取的站点附近。

切换到多线程抓取会改善其中一些瓶颈,但不会消除它们。


但我不认为你的做法是个好主意。

如果您编写的内容每 1 或 2 秒重复重新抓取一次相同的页面,他们会注意到。他们会采取措施阻止你。难以处理的步骤。像这样的东西:

  • 速率限制您的请求
  • 阻止您的 IP 或 IP 范围
  • 给你发"cease and desist"封信

如果这没有帮助,也许还有更严重的事情。

真正的解决办法可能是以更有效的方式获取信息;例如通过 API。这也可能会花费您金钱。因为(当它归结为它时)你的抓取将花费 他们 钱,因为没有 return ......或者负数 return 如果你的 activity 最终减少了真实用户对其网站的点击次数。