You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java深度网页爬虫开发问题:无法实现深度2爬取逻辑

Java深度爬虫无法完成深度2爬取的问题排查与修复

问题分析

你的代码无法完成深度2爬取的核心原因有以下几点:

  • 全局链接集合混用:urlLinks是全局集合,深度0、1的所有链接都存在这里,导致爬深度2时会重复处理低深度的链接,且无法精准获取深度1页面提取的新链接。
  • 深度2爬取逻辑错误:twoDepthCrawling只是调用oneDepthCrawling后遍历整个urlLinks下载,没有针对每个深度1的页面单独提取链接并爬取深度2的页面。
  • 链接计数逻辑错误:getUrls中counter <= amountOfUrls会提取amountOfUrls + 1个链接,不符合单页最大URL数量的要求。
  • 未实现跨层级URL唯一逻辑:isUnique参数未被使用,无法控制跨层级的URL去重。
  • 方法耦合严重:各深度方法互相调用,导致低深度逻辑重复执行,流程混乱。

修复方案

重构代码,按深度分层存储链接,明确每个深度的爬取流程,同时修复计数和去重逻辑:

1. 调整成员变量

用分层集合存储各深度的待爬链接,同时维护全局去重集合(用于isUnique参数):

private String initialUrl;
private int amountOfUrls;
private Depth maxDepth;
private boolean isUnique;
// 按深度存储待爬链接,index对应深度值
private List<List<String>> depthUrlList = new ArrayList<>();
// 全局去重集合
private Set<String> uniqueUrlSet = new HashSet<>();

2. 重构爬取入口方法

public void crawlWebPages() {
    // 初始化深度0的链接
    depthUrlList.add(new ArrayList<>());
    depthUrlList.get(0).add(initialUrl);
    
    for (int currentDepth = 0; currentDepth <= maxDepth.ordinal(); currentDepth++) {
        List<String> currentUrls = depthUrlList.get(currentDepth);
        // 下载当前深度的所有页面
        for (String url : currentUrls) {
            downloadHtml(url, Depth.values()[currentDepth]);
            System.out.println(url + " downloaded at depth " + currentDepth);
        }
        
        // 如果不是最大深度,提取下一层级的链接
        if (currentDepth < maxDepth.ordinal()) {
            depthUrlList.add(new ArrayList<>());
            for (String url : currentUrls) {
                List<String> nextLevelUrls = extractUrls(url);
                // 处理去重逻辑
                for (String nextUrl : nextLevelUrls) {
                    if (!isUnique || !uniqueUrlSet.contains(nextUrl)) {
                        depthUrlList.get(currentDepth + 1).add(nextUrl);
                        uniqueUrlSet.add(nextUrl);
                    }
                }
            }
        }
    }
}

3. 修复URL提取方法

private List<String> extractUrls(String url) {
    List<String> extractedUrls = new ArrayList<>();
    int counter = 0;
    try {
        Document doc = Jsoup.connect(url).get();
        Elements availableLinksOnPage = doc.select("a[href]");
        for (Element element : availableLinksOnPage) {
            String absUrl = element.absUrl("href");
            // 跳过空链接或无效链接
            if (absUrl.isEmpty() || !absUrl.startsWith("http")) {
                continue;
            }
            // 达到单页最大数量就停止
            if (counter >= amountOfUrls) {
                break;
            }
            extractedUrls.add(absUrl);
            counter++;
        }
    } catch (IOException e) {
        throw new RuntimeException("couldn't fetch links from " + url, e);
    }
    return extractedUrls;
}

4. 调整构建器与初始化

确保构建器正确初始化成员变量:

private HtmlHandler(Builder builder) {
    this.initialUrl = builder.url;
    this.amountOfUrls = builder.amountOfUrls;
    this.maxDepth = builder.depth;
    this.isUnique = builder.isUnique;
}

public static Builder builder() {
    return new Builder();
}

public static class Builder {
    private String url;
    private int amountOfUrls;
    private Depth depth;
    private boolean isUnique;

    public Builder url(String url) {
        this.url = url;
        return this;
    }

    public Builder amountOfUrls(int amountOfUrls) {
        this.amountOfUrls = amountOfUrls;
        return this;
    }

    public Builder depth(Depth depth) {
        this.depth = depth;
        return this;
    }

    public Builder isUnique(boolean isUnique) {
        this.isUnique = isUnique;
        return this;
    }

    public HtmlHandler build() {
        return new HtmlHandler(this);
    }
}

5. 保留原有的downloadHtml方法

private void downloadHtml(String url, Depth depth) {
    try {
        FileUtils.copyURLToFile(new URL(url), new File(StringHandler.createFileName(url, depth)));
    } catch (IOException e) {
        throw new RuntimeException("error downloading html source file for " + url, e);
    }
}

修复后的效果

  • 深度0:下载初始URL,提取5个链接存入深度1集合
  • 深度1:下载5个URL,每个提取5个链接,总计25个链接存入深度2集合(如果isUnique为true会自动去重)
  • 深度2:下载25个URL,完成后结束程序

内容的提问来源于stack exchange,提问作者kidulf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 21:35:24