使用Java爬取xxx律师协会网站上公开的律所信息并导出到Excel

发布于:2025-08-07 ⋅ 阅读:(18) ⋅ 点赞:(0)

1. 引言:介绍背景和目的 2. 技术栈:使用的库(Jsoup, Apache POI) 3. 实现步骤: a. 分析目标网站结构 b. 分页爬取数据 c. 数据解析与存储 d. 导出Excel 4. 完整代码(带详细注释) 5. 可能遇到的问题及解决方案 6. 结语注意:由于是公开博客,我们需要提醒读者遵守网站的robots.txt,尊重网站数据的使用条款,不要过度爬取。下面开始撰写博客:

使用Java爬取成都市律师协会律所信息并导出Excel

本文将分享一个实用的Java爬虫案例,通过Jsoup+POI技术实现成都市律师协会网站律所信息的自动化采集与Excel导出。

一、代码背景与需求

在法务行业调研中,需要获取成都市所有律师事务所的公开信息,包括:

  • 律所名称

  • 负责人

  • 主管司法局

  • 执业许可证号

  • 联系电话

  • 办公地址

目标网站采用分页展示(共218页),手动复制效率低下,因此开发此自动化采集程序。

二、技术栈与工具

技术/工具 用途
Jsoup HTML解析和数据提取
Apache POI Excel文件生成
Java 8+ 基础编程语言
Maven 依赖管理

Maven依赖

<dependencies>
    <!-- Jsoup HTML解析 -->
    <dependency>
        <groupId>org.jsoup</groupId>
        <artifactId>jsoup</artifactId>
        <version>1.14.3</version>
    </dependency>
    
    <!-- Apache POI Excel操作 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.0</version>
    </dependency>
</dependencies>

三、实现思路详解

1. 网站结构分析

通过浏览器开发者工具分析目标网站:

  • 分页URL模式:https://www.cdslsxh.org/lvsuo?page={页码}

  • 单页律所容器:div.zz-loop-item

  • 关键信息选择器:

    • 名称:a.zz-text.zz-comp-content div

    • 其他信息:div.zz-comp-text

2. 爬虫核心流程
3. 关键技术点

(1)防反爬策略

Document doc = Jsoup.connect(url)
    .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64)...") // 模拟浏览器
    .referrer("https://www.cdslsxh.org") // 设置来源页
    .timeout(30000) // 30秒超时
    .get();

(2)数据提取方法

private static String extractValue(Element parent, String label) {
    Elements elements = parent.select("div.zz-comp-text");
    for (Element elem : elements) {
        if (elem.text().contains(label)) {
            return elem.text().replace(label, "").trim();
        }
    }
    return "";
}

(3)Excel导出优化

// 创建加粗表头样式
CellStyle headerStyle = workbook.createCellStyle();
Font font = workbook.createFont();
font.setBold(true);
headerStyle.setFont(font);

// 自动调整列宽
for (int i = 0; i < headers.length; i++) {
    sheet.autoSizeColumn(i);
}

四、完整实现代码

package com.example.demo.ok;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

public class GongkaiNetwork {

    public static void main(String[] args) throws Exception {
        // 基础URL模板
        String baseUrl = "https://www.cdslsxh.org/lvsuo?page=";
        
        List<LawFirm> lawFirms = new ArrayList<>();
        
        // 设置总页数
        int totalPages = 218;
        
        // 循环处理每一页
        for (int page = 1; page <= totalPages; page++) {
            System.out.println("正在处理第 " + page + " 页...");
            
            try {
                // 构建当前页URL
                String url = baseUrl + page;
                
                // 设置请求头模拟浏览器访问
                Document doc = Jsoup.connect(url)
                        .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                        .referrer("https://www.cdslsxh.org")
                        .timeout(30000) // 30秒超时
                        .get();
                
                // 提取律所信息
                Elements loopItems = doc.select("div.zz-loop-item");
                
                for (Element item : loopItems) {
                    LawFirm firm = new LawFirm();
                    
                    // 提取律所名称
                    Element nameElement = item.selectFirst("a.zz-text.zz-comp-content div");
                    if (nameElement != null) {
                        firm.setName(nameElement.text().trim());
                    }
                    
                    // 提取其他信息
                    firm.setPrincipal(extractValue(item, "负责人:"));
                    firm.setBureau(extractValue(item, "主管司法局:"));
                    firm.setLicense(extractValue(item, "许可证号:"));
                    firm.setPhone(extractValue(item, "电话:"));
                    firm.setAddress(extractValue(item, "地址:"));
                    
                    lawFirms.add(firm);
                }
                
                System.out.println("成功提取第 " + page + " 页的 " + loopItems.size() + " 家律所信息");
                
                // 添加延迟避免请求过快
                Thread.sleep(0); // 1秒延迟
                
            } catch (Exception e) {
                System.err.println("处理第 " + page + " 页时出错: " + e.getMessage());
                // 继续处理下一页
            }
        }
        
        // 创建Excel文件
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("律所信息");
        
        // 创建表头
        String[] headers = {"律所名称", "负责人", "主管司法局", "许可证号", "电话", "地址"};
        Row headerRow = sheet.createRow(0);
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            
            // 设置表头样式
            CellStyle headerStyle = workbook.createCellStyle();
            Font font = workbook.createFont();
            font.setBold(true);
            headerStyle.setFont(font);
            cell.setCellStyle(headerStyle);
        }
        
        // 填充数据
        int rowNum = 1;
        for (LawFirm firm : lawFirms) {
            Row row = sheet.createRow(rowNum++);
            row.createCell(0).setCellValue(firm.getName() != null ? firm.getName() : "");
            row.createCell(1).setCellValue(firm.getPrincipal() != null ? firm.getPrincipal() : "");
            row.createCell(2).setCellValue(firm.getBureau() != null ? firm.getBureau() : "");
            row.createCell(3).setCellValue(firm.getLicense() != null ? firm.getLicense() : "");
            row.createCell(4).setCellValue(firm.getPhone() != null ? firm.getPhone() : "");
            row.createCell(5).setCellValue(firm.getAddress() != null ? firm.getAddress() : "");
        }
        
        // 自动调整列宽
        for (int i = 0; i < headers.length; i++) {
            sheet.autoSizeColumn(i);
        }
        
        // 保存Excel文件
        String outputPath = "D:\\work\\律所信息汇总.xlsx";
        try (FileOutputStream outputStream = new FileOutputStream(outputPath)) {
            workbook.write(outputStream);
        }
        
        System.out.println("成功提取 " + lawFirms.size() + " 家律所信息到Excel文件: " + outputPath);
        workbook.close();
    }
    
    // 辅助方法:根据标签文本提取值
    private static String extractValue(Element parent, String label) {
        Elements elements = parent.select("div.zz-comp-text");
        for (Element elem : elements) {
            if (elem.text().contains(label)) {
                return elem.text().replace(label, "").trim();
            }
        }
        return "";
    }
    
    static class LawFirm {
        private String name;
        private String principal;
        private String bureau;
        private String license;
        private String phone;
        private String address;
        
        // Getters and Setters
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        public String getPrincipal() { return principal; }
        public void setPrincipal(String principal) { this.principal = principal; }
        public String getBureau() { return bureau; }
        public void setBureau(String bureau) { this.bureau = bureau; }
        public String getLicense() { return license; }
        public void setLicense(String license) { this.license = license; }
        public String getPhone() { return phone; }
        public void setPhone(String phone) { this.phone = phone; }
        public String getAddress() { return address; }
        public void setAddress(String address) { this.address = address; }
    }
}

五、常见问题与解决方案

  1. 请求被拒绝(403错误)

    • 解决方案:更新User-Agent和Referrer

    • 扩展:添加Cookie和随机延迟

  2. 数据提取不全

    • 检查点:网站结构是否更新

    • 调试方法:保存HTML快照分析

      // 调试时保存HTML
      Files.write(Paths.get("debug.html"), doc.html().getBytes());

六、注意事项

  1. 法律与道德约束

    • 遵守网站robots.txt规则

    • 控制请求频率(≥1秒/页)

    • 仅用于学习研究,禁止商用

  2. 程序优化方向

    • 增加代理IP支持

    • 实现断点续爬功能

    • 添加邮件通知机制

  3. 扩展应用

    • 适配其他律师协会网站

    • 集成SpringBoot作为定时任务

    • 添加数据库存储支持


七、执行效果

运行程序后:

  1. 控制台实时显示采集进度

  2. 最终生成结构化的Excel文件

  3. 输出路径:D:\work\律所信息汇总.xlsx

通过此项目,我们实现了:

  • 高效获取218页律所数据(约5分钟)

  • 自动化数据清洗与格式化

  • 专业级的Excel报表输出

技术总结:本案例展示了Java在网络爬虫领域的强大能力,通过合理的架构设计,可以高效解决实际工作中的数据采集需求。读者可在此基础上扩展更多实用功能。


网站公告

今日签到

点亮在社区的每一天
去签到