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

如何修改Java+JSoup程序补全网页抓取缺失内容并保存文件

问题

使用JSoup抓取指定网页的主内容并保存到文件,测试网页为https://netbasal.com/using-the-angular-http-client-in-angular-v15-f4bec3c11926。当前基于Java 11、JSoup 1.15.3的测试程序输出内容缺失主标题「Using the Angular Http Client in Angular v15」、Github源码以及标题「Interceptors in Lazy Loaded Modules」,需修改程序补全这些内容。

当前测试程序代码:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class App
{
    public static void main( String[] args )
    {
        try {
            String dir = "/home/ak/using-the-http-client-v15";
            String filename = "Out";
            Path path = Paths.get(dir + "/" + filename + ".txt");
            Document doc = Jsoup.connect("https://netbasal.com/using-the-angular-http-client-in-angular-v15-f4bec3c11926").get();
            String searchStrings[] = {
                "pw-post-body-paragraph"
            };
            Set<String> tagNameSet = Set.of("span", "p");
            List<String> output = new ArrayList<String>();
            for (String searchString : searchStrings) {
                Elements searchStringElements = doc.getElementsByClass(searchString);
                if (searchStringElements == null)
                    continue;
                if (searchStringElements.hasClass(searchString)) {
                    for (Element e : searchStringElements) {
                        if (tagNameSet.contains(e.tagName())) {
                            String str = e.wholeText() + "\n\n";
                            output.add(str);
                        }
                    }
                }
                int size = output.size();
                for (int i = 0; i < size; i++) {
                    // Java 11 Append mode
                    Files.writeString(path, output.get(i),
                            StandardOpenOption.CREATE, StandardOpenOption.APPEND);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
问题分析

当前程序仅抓取pw-post-body-paragraph类下的<span>和<p>标签内容,而主标题、次级标题、代码块(包括Github源码)不在这个选择范围内,导致内容缺失。需要扩展选择器,覆盖这些遗漏的元素类型。

修改后的完整代码
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class App {
    public static void main(String[] args) {
        try {
            String dir = "/home/ak/using-the-http-client-v15";
            String filename = "Out";
            Path path = Paths.get(dir + "/" + filename + ".txt");
            Document doc = Jsoup.connect("https://netbasal.com/using-the-angular-http-client-in-angular-v15-f4bec3c11926").get();
            List<String> output = new ArrayList<>();

            // 1. 抓取主标题
            Element mainTitle = doc.selectFirst("h1.pw-post-title");
            if (mainTitle != null) {
                output.add("# " + mainTitle.wholeText() + "\n\n");
            }

            // 2. 抓取所有次级标题(如h2,包含「Interceptors in Lazy Loaded Modules」)
            Elements subTitles = doc.select("h2");
            for (Element title : subTitles) {
                output.add("## " + title.wholeText() + "\n\n");
            }

            // 3. 抓取段落内容(保留原逻辑)
            String searchStrings[] = { "pw-post-body-paragraph" };
            Set<String> tagNameSet = Set.of("span", "p");
            for (String searchString : searchStrings) {
                Elements paragraphElements = doc.getElementsByClass(searchString);
                if (paragraphElements == null || paragraphElements.isEmpty()) {
                    continue;
                }
                for (Element e : paragraphElements) {
                    if (tagNameSet.contains(e.tagName())) {
                        output.add(e.wholeText() + "\n\n");
                    }
                }
            }

            // 4. 抓取代码块(包括Github源码)
            Elements codeBlocks = doc.select("pre.highlight");
            for (Element code : codeBlocks) {
                output.add("```\n" + code.wholeText().trim() + "\n```\n\n");
            }

            // 一次性写入所有内容,避免重复IO操作
            Files.writeString(path, String.join("", output),
                    StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
关键修改说明
  • 抓取主标题:通过选择器h1.pw-post-title定位网页主标题,添加Markdown一级标题格式后加入输出列表。
  • 抓取次级标题:通过选择器h2获取所有二级标题,添加Markdown二级标题格式,覆盖「Interceptors in Lazy Loaded Modules」这类内容。
  • 抓取代码块:通过选择器pre.highlight定位页面中的代码块(包括Github源码),用Markdown代码块格式包裹后加入输出。
  • 优化写入逻辑:将所有内容收集完成后一次性写入文件,替换原循环中重复写入的逻辑,提升效率并避免内容重复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 12:15:48