如何在Jsoup中加载文档前获取HTTP Content-Length
如何在Jsoup爬取前获取文档大小并排序队列
当然可以!你完全可以在调用connection.get()下载完整文档之前,通过HTTP响应头的Content-Length字段预估文档大小,以此实现优先爬取较小文档的需求。下面是具体的实现思路和代码示例:
核心思路:发送HEAD请求获取响应头
HTTP的HEAD请求只会返回响应头信息,不会下载文档正文,这是获取Content-Length最高效的方式——既节省带宽,又能快速拿到我们需要的大小数据。
具体实现步骤
1. 使用Jsoup发送HEAD请求获取文档大小
创建Jsoup连接时指定请求方法为HEAD,执行后从响应中提取Content-Length:
public long getDocumentSize(String url) { try { Response response = Jsoup.connect(url) .method(Connection.Method.HEAD) .timeout(5000) // 设置合理超时时间,避免阻塞 .execute(); // 从响应头中读取Content-Length String lengthStr = response.header("Content-Length"); if (lengthStr != null && !lengthStr.isEmpty()) { return Long.parseLong(lengthStr); } } catch (IOException e) { e.printStackTrace(); } // 无法获取长度时返回极大值,让该链接排在队列末尾 return Long.MAX_VALUE; }
2. 用优先级队列实现按大小排序
把普通爬取队列换成PriorityQueue,自定义比较器让体积小的URL优先出队:
// 初始化优先级队列,按文档大小升序排序 PriorityQueue<Map.Entry<String, Long>> crawlQueue = new PriorityQueue<>( Comparator.comparing(Map.Entry::getValue) ); // 维护已爬取URL集合,避免重复爬取 Set<String> crawledUrls = new HashSet<>(); // 假设已从初始页面提取到待爬取链接 List<String> initialLinks = ...; // 遍历链接,获取大小后加入优先级队列 for (String link : initialLinks) { if (!crawledUrls.contains(link)) { long size = getDocumentSize(link); crawlQueue.add(new AbstractMap.SimpleEntry<>(link, size)); crawledUrls.add(link); } } // 开始按优先级爬取 while (!crawlQueue.isEmpty()) { Map.Entry<String, Long> entry = crawlQueue.poll(); String currentUrl = entry.getKey(); // 执行正常爬取逻辑:下载文档、提取新链接 try { Document doc = Jsoup.connect(currentUrl).get(); Elements newLinks = doc.select("a[href]"); // 对新链接重复流程:获取大小 -> 加入队列 for (Element link : newLinks) { String absLink = link.absUrl("href"); if (!crawledUrls.contains(absLink)) { long linkSize = getDocumentSize(absLink); crawlQueue.add(new AbstractMap.SimpleEntry<>(absLink, linkSize)); crawledUrls.add(absLink); } } } catch (IOException e) { e.printStackTrace(); } }
关键注意事项
- 部分网站不支持HEAD请求:如果遇到服务器拒绝HEAD请求的情况,可以退而求其次发送GET请求(但会开始下载正文,效率稍低),或者直接将这类链接设为默认极大值延后爬取。
- Content-Length可能缺失:动态生成内容、分块传输(
Transfer-Encoding: chunked)的响应不会返回Content-Length,此时建议给这类链接设较大默认值,让它们排在有明确大小的链接之后。 - 必须做URL去重:一定要维护已爬取URL集合,避免重复加入队列和爬取,浪费资源。
内容的提问来源于stack exchange,提问作者Daniel Valland
相关产品推荐
相关产品推荐

