使用Jsoup批量爬取URL时,如何在异常后保持代码运行?
嘿,这个问题我批量爬取页面的时候可太熟悉了!SocketTimeoutException直接打断整个循环确实闹心,给你几个实用的方案,让你的爬虫稳稳跑完1000个URL:
处理Jsoup爬取时的SocketTimeoutException,保持程序持续运行
核心思路就是精准捕获异常并隔离出错的URL,再搭配重试、超时优化等手段,既减少异常发生,又保证循环不中断。
1. 基础操作:用try-catch包裹单个URL的爬取逻辑
把每个URL的请求代码单独放进try-catch块里,这样某一个URL出错时,只会跳过它,不会终止整个循环。示例代码:
import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import java.io.IOException; import java.net.SocketTimeoutException; import java.util.List; public class Crawler { public static void main(String[] args) { List<String> urls = List.of("https://example.com/page1", "https://example.com/page2", "..."); // 你的1000个URL列表 for (String url : urls) { try { // 配置合理的超时时间,比如10秒,避免无限等待 Document doc = Jsoup.connect(url) .timeout(10000) .get(); // 这里写你的HTML数据处理逻辑 System.out.println("成功爬取:" + url); } catch (SocketTimeoutException e) { // 捕获超时异常,记录日志或标记该URL后续处理 System.err.println("连接超时,跳过URL:" + url); } catch (IOException e) { // 兜底捕获其他IO异常(比如连接拒绝、DNS失败等) System.err.println("爬取失败,跳过URL:" + url + ",错误信息:" + e.getMessage()); } } } }
2. 进阶:给超时的URL加重试机制
很多超时是临时网络波动导致的,重试1-2次大概率能成功。可以封装一个带重试的工具方法:
private static Document fetchWithRetry(String url, int maxRetries) throws IOException { int attempt = 0; while (attempt < maxRetries) { try { return Jsoup.connect(url) .timeout(10000) .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36") // 模拟浏览器UA .get(); } catch (SocketTimeoutException e) { attempt++; System.err.println("第" + attempt + "次重试URL:" + url); // 重试前加短暂延迟,避免频繁请求触发反爬 try { Thread.sleep(1000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } } } // 多次重试仍失败,抛出异常让上层处理 throw new SocketTimeoutException("重试" + maxRetries + "次后仍超时:" + url); }
然后在循环里调用这个方法:
for (String url : urls) { try { Document doc = fetchWithRetry(url, 2); // 最多重试2次 // 处理数据... } catch (SocketTimeoutException e) { System.err.println("最终失败,跳过URL:" + url); } catch (IOException e) { System.err.println("其他错误:" + url + "," + e.getMessage()); } }
3. 优化Jsoup超时配置
默认超时可能不符合目标网站的响应速度,你可以精细化配置:
.timeout(15000):统一设置连接+读取的总超时(毫秒)- 分别设置连接和读取超时:
Jsoup.connect(url) .timeout(0) // 先关闭总超时限制 .connectionTimeout(5000) // 连接超时5秒 .readTimeout(10000); // 读取响应超时10秒
4. 额外提醒:避免被目标网站封禁
爬1000个URL很容易被识别为爬虫,除了处理异常,还要注意:
- 每次请求后加随机延迟:
Thread.sleep(new Random().nextInt(2000) + 1000);(1-3秒随机) - 始终设置浏览器UA,避免被拦截
- 控制并发数(新手建议先单线程爬,熟悉后再用线程池)
这样处理后,你的爬虫遇到超时或其他IO异常时,就不会直接崩溃,而是优雅地跳过或重试出错的URL,顺利完成1000个链接的爬取!
内容的提问来源于stack exchange,提问作者kant01
相关产品推荐
相关产品推荐

