Jsoup解析案例

wen java案例 1

本文目录导读:

Jsoup解析案例

  1. 基础案例:HTML解析入门
  2. 网页内容抓取示例
  3. 表格数据提取
  4. 复杂选择器示例
  5. 处理相对URL和文件下载
  6. 处理表单数据
  7. 使用Cookies保持会话
  8. 异常处理最佳实践
  9. 使用建议

我来为您提供几个Jsoup解析的实用案例,从基础到进阶。

基础案例:HTML解析入门

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class BasicExample {
    public static void main(String[] args) {
        // 1. 解析HTML字符串
        String html = "<html><head><title>示例页面</title></head>"
                + "<body>"
                + "<div class='content'>"
                + "  <h1>标题</h1>"
                + "  <p class='text'>第一段文本</p>"
                + "  <p class='text'>第二段文本</p>"
                + "  <a href='https://example.com'>链接</a>"
                + "</div>"
                + "</body></html>";
        Document doc = Jsoup.parse(html);
        // 获取标题
        String title = doc.title();
        System.out.println("页面标题: " + title);
        // 通过类名获取元素
        Elements paragraphs = doc.getElementsByClass("text");
        for (Element p : paragraphs) {
            System.out.println("段落内容: " + p.text());
        }
        // 通过标签获取
        Element heading = doc.selectFirst("h1");
        System.out.println("H1内容: " + heading.text());
        // 获取链接
        Element link = doc.selectFirst("a");
        System.out.println("链接文本: " + link.text());
        System.out.println("链接地址: " + link.attr("href"));
    }
}

抓取示例

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
public class WebScraper {
    public static void main(String[] args) {
        try {
            // 连接并获取网页
            Document doc = Jsoup.connect("https://example.com/news")
                .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
                .timeout(10000)
                .get();
            // 提取新闻标题和链接
            Elements newsItems = doc.select("div.news-item");
            System.out.println("找到 " + newsItems.size() + " 条新闻\n");
            for (Element item : newsItems) {
                // 获取标题
                Element title = item.selectFirst("h2.title");
                // 获取链接
                Element link = item.selectFirst("a");
                // 获取摘要
                Element summary = item.selectFirst("p.summary");
                if (title != null) {
                    System.out.println("标题: " + title.text());
                }
                if (link != null) {
                    System.out.println("URL: " + link.attr("href"));
                }
                if (summary != null) {
                    System.out.println(" " + summary.text());
                }
                System.out.println("---");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

表格数据提取

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class TableParser {
    // 定义数据模型
    static class Student {
        String name;
        int age;
        String grade;
        @Override
        public String toString() {
            return String.format("学生{姓名='%s', 年龄=%d, 班级='%s'}", 
                               name, age, grade);
        }
    }
    public static void main(String[] args) {
        String html = "<html><body>"
                + "<table id='student-table'>"
                + "  <thead>"
                + "    <tr><th>姓名</th><th>年龄</th><th>班级</th></tr>"
                + "  </thead>"
                + "  <tbody>"
                + "    <tr><td>张三</td><td>18</td><td>高三(1)班</td></tr>"
                + "    <tr><td>李四</td><td>17</td><td>高三(2)班</td></tr>"
                + "    <tr><td>王五</td><td>18</td><td>高三(1)班</td></tr>"
                + "  </tbody>"
                + "</table>"
                + "</body></html>";
        Document doc = Jsoup.parse(html);
        List<Student> students = parseTable(doc);
        System.out.println("解析结果:");
        students.forEach(System.out::println);
    }
    private static List<Student> parseTable(Document doc) {
        List<Student> students = new ArrayList<>();
        // 选择表格数据行(跳过表头)
        Elements rows = doc.select("#student-table tbody tr");
        for (Element row : rows) {
            Elements cells = row.select("td");
            if (cells.size() >= 3) {
                Student student = new Student();
                student.name = cells.get(0).text();
                student.age = Integer.parseInt(cells.get(1).text());
                student.grade = cells.get(2).text();
                students.add(student);
            }
        }
        return students;
    }
}

复杂选择器示例

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class SelectorExamples {
    public static void main(String[] args) {
        String html = "<html><body>"
                + "<div id='main'>"
                + "  <ul class='nav'>"
                + "    <li class='active'><a href='/home'>首页</a></li>"
                + "    <li><a href='/products'>产品</a></li>"
                + "    <li><a href='/about'>关于我们</a></li>"
                + "  </ul>"
                + "  <div class='content'>"
                + "    <p data-id='1'>第一个段落</p>"
                + "    <p data-id='2' class='highlight'>第二个段落</p>"
                + "    <p data-id='3'>第三个段落</p>"
                + "  </div>"
                + "</div>"
                + "</body></html>";
        Document doc = Jsoup.parse(html);
        System.out.println("=== 选择器示例 ===\n");
        // 1. ID选择器
        Element mainDiv = doc.selectFirst("#main");
        System.out.println("ID选择器 #main: " + mainDiv.tagName());
        // 2. 类选择器
        Elements activeItems = doc.select(".active");
        System.out.println("类选择器 .active: " + activeItems.size() + " 个元素");
        // 3. 属性选择器
        Elements withDataId = doc.select("[data-id]");
        System.out.println("属性选择器 [data-id]: " + withDataId.size() + " 个元素");
        // 4. 组合选择器
        Elements navLinks = doc.select("ul.nav > li > a");
        System.out.println("组合选择器: " + navLinks.size() + " 个链接");
        // 5. 包含文本选择
        Elements paragraphWithText = doc.select("p:contains(第二个)");
        System.out.println("文本选择: " + paragraphWithText.text());
        // 6. 相邻兄弟选择器
        Element highlight = doc.selectFirst(".highlight");
        Element nextParagraph = highlight.nextElementSibling();
        System.out.println("相邻兄弟: " + nextParagraph.text());
        // 7. 父元素查找
        Element paragraph = doc.selectFirst("p");
        Element parentDiv = paragraph.parent();
        System.out.println("父元素: " + parentDiv.className());
        // 8. 第一个和最后一个
        Element firstP = doc.selectFirst("p:first-child");
        Element lastP = doc.selectFirst("p:last-child");
        System.out.println("第一个p: " + firstP.text());
        System.out.println("最后一个p: " + lastP.text());
    }
}

处理相对URL和文件下载

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ImageDownloader {
    public static void main(String[] args) {
        try {
            // 设置baseUri用于解析相对路径
            String baseUrl = "https://example.com/gallery";
            Document doc = Jsoup.connect(baseUrl).get();
            // 处理图片链接
            Elements images = doc.select("img");
            for (Element img : images) {
                // 获取图片地址(相对路径转绝对路径)
                String src = img.absUrl("src");
                // 获取alt文本(用于文件名)
                String alt = img.attr("alt");
                String fileName = alt.isEmpty() ? 
                    "image_" + System.currentTimeMillis() : 
                    alt.replace(" ", "_");
                System.out.println("图片地址: " + src);
                System.out.println("文件名: " + fileName);
                // 下载图片(可选)
                // downloadImage(src, "downloads/" + fileName + ".jpg");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private static void downloadImage(String imageUrl, String savePath) 
            throws IOException {
        // 创建目录
        Files.createDirectories(Paths.get(savePath).getParent());
        // 下载并保存
        try (InputStream in = new URL(imageUrl).openStream()) {
            Files.copy(in, Paths.get(savePath));
        }
        System.out.println("图片已保存: " + savePath);
    }
}

处理表单数据

import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.FormElement;
import org.jsoup.nodes.Element;
import java.io.IOException;
import java.util.Map;
public class FormProcessor {
    public static void main(String[] args) {
        try {
            // 1. 提交GET请求
            Document doc = Jsoup.connect("https://httpbin.org/get")
                .data("username", "zhangsan")
                .data("age", "25")
                .get();
            System.out.println("GET请求响应:");
            System.out.println(doc.body().text());
            // 2. 提交POST请求
            Connection.Response response = Jsoup.connect("https://httpbin.org/post")
                .data("username", "lisi")
                .data("password", "123456")
                .method(Connection.Method.POST)
                .execute();
            Document responseDoc = response.parse();
            System.out.println("\nPOST请求响应:");
            System.out.println(responseDoc.body().text());
            // 3. 模拟表单提交
            String html = "<form id='login-form' action='/login' method='post'>"
                    + "<input type='text' name='username' value=''>"
                    + "<input type='password' name='password' value=''>"
                    + "<button type='submit'>登录</button>"
                    + "</form>";
            Document formDoc = Jsoup.parse(html);
            // 获取表单
            Element form = formDoc.selectFirst("#login-form");
            // 模拟填写表单
            form.selectFirst("input[name=username]").val("张三");
            form.selectFirst("input[name=password]").val("abc123");
            // 提交表单
            // 实际项目中会发送到指定action地址
            System.out.println("\n表单数据:");
            Elements inputs = form.select("input");
            for (Element input : inputs) {
                System.out.println(input.attr("name") + " = " + input.val());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用Cookies保持会话

import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.IOException;
import java.util.Map;
public class SessionHandler {
    public static void main(String[] args) {
        Connection connection = Jsoup.connect("https://example.com/login");
        try {
            // 1. 登录获取cookies
            Connection.Response loginResponse = connection
                .data("username", "admin")
                .data("password", "123456")
                .method(Connection.Method.POST)
                .execute();
            // 获取cookies
            Map<String, String> cookies = loginResponse.cookies();
            System.out.println("登录成功,Cookies: " + cookies);
            // 2. 使用cookies访问需要认证的页面
            Document protectedPage = Jsoup.connect("https://example.com/dashboard")
                .cookies(cookies)
                .get();
            System.out.println("受保护页面标题: " + protectedPage.title());
            // 3. 保持会话状态(多次请求)
            Connection.Response firstRequest = Jsoup.connect("https://example.com/api/data")
                .cookies(cookies)
                .execute();
            // 后续请求自动携带cookies
            Connection.Response secondRequest = Jsoup.connect("https://example.com/api/more")
                .cookies(cookies)
                .execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

异常处理最佳实践

import org.jsoup.HttpStatusException;
import org.jsoup.Jsoup;
import org.jsoup.UnsupportedMimeTypeException;
import org.jsoup.nodes.Document;
import java.io.IOException;
public class ErrorHandling {
    public static void main(String[] args) {
        String[] urls = {
            "https://example.com",
            "https://nonexistent-site.com",
            "https://example.com/not-found",
            "https://example.com/file.pdf"  // 非HTML内容
        };
        for (String url : urls) {
            try {
                fetchUrl(url);
            } catch (HttpStatusException e) {
                System.out.println("HTTP状态错误: " + url);
                System.out.println("状态码: " + e.getStatusCode());
            } catch (UnsupportedMimeTypeException e) {
                System.out.println("不支持的MIME类型: " + url);
            } catch (IOException e) {
                System.out.println("IO错误: " + url);
                System.out.println("原因: " + e.getMessage());
            } catch (Exception e) {
                System.out.println("未知错误: " + url);
                e.printStackTrace();
            }
            System.out.println("---");
        }
    }
    private static void fetchUrl(String url) throws IOException {
        Document doc = Jsoup.connect(url)
            .userAgent("Mozilla/5.0")
            .timeout(5000)
            .followRedirects(true)
            .ignoreHttpErrors(false)
            .get();
        System.out.println("成功获取: " + url);
        System.out.println("标题: " + doc.title());
    }
}

使用建议

  1. 添加依赖 (Maven):

    <dependency>
     <groupId>org.jsoup</groupId>
     <artifactId>jsoup</artifactId>
     <version>1.16.1</version>
    </dependency>
  2. 性能优化

    • 使用连接池复用连接
    • 合理设置超时时间
    • 限制并发请求数量
  3. 反爬虫处理

    • 设置合理的User-Agent
    • 添加请求间隔
    • 使用代理IP
  4. 数据提取规范

    • 优先使用id选择器
    • 避免过度使用链式选择器
    • 对optional元素进行空值检查

这些案例覆盖了Jsoup的主要功能,您可以根据实际需求进行调整和扩展,如果您有特定的使用场景,我可以提供更针对性的示例。

抱歉,评论功能暂时关闭!