如何修改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
相关产品推荐
相关产品推荐

