Java基于Hutool实现SFTP文件夹递归下载与断点续传优化

wx02374e436a4b8350

1. 为什么需要SFTP文件夹递归下载与断点续传

在实际开发中,我们经常需要从远程服务器下载文件。SFTP作为SSH协议的一部分,提供了安全的文件传输能力。但原生SFTP客户端有个明显的痛点:它只能单文件操作,无法直接下载整个文件夹。想象一下,如果你要下载一个包含数百个子文件夹和数千个文件的目录结构,手动一个个下载简直是噩梦。

更糟糕的是,当网络不稳定时,下载大文件夹经常会在中途断开。我曾经在一个项目中,花了3小时下载一个20GB的文件夹,结果在95%的时候网络闪断,一切都要从头开始。这种体验实在太糟糕了,于是我决定用Hutool工具库来解决这个问题。

Hutool的Sftp工具类已经封装了基本的SFTP操作,但它的递归下载功能还不够完善。我们需要在它的基础上增加两个关键能力:一是完整的文件夹递归下载,二是可靠的断点续传机制。这样即使在网络不稳定的环境下,也能保证文件传输的可靠性。

2. 环境准备与基础配置

2.1 添加必要的依赖

首先,我们需要在项目中引入Hutool和JSch的依赖。JSch是Java实现的SSH2库,Hutool的SFTP功能就是基于它封装的。

如果你使用Maven,在pom.xml中添加:

xml复制<dependencies>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.8.16</version>
    </dependency>
    <dependency>
        <groupId>com.jcraft</groupId>
        <artifactId>jsch</artifactId>
        <version>0.1.54</version>
    </dependency>
</dependencies>

如果是Gradle项目,在build.gradle中添加:

groovy复制dependencies {
    implementation 'com.jcraft:jsch:0.1.54'
    implementation 'cn.hutool:hutool-all:5.8.16'
}

2.2 建立SFTP连接

Hutool提供了非常简便的方式来创建SFTP连接。基本连接代码如下:

java复制import cn.hutool.extra.ssh.JschUtil;
import cn.hutool.extra.ssh.Sftp;

public class SftpDemo {
    public static void main(String[] args) {
        String host = "your.sftp.server";
        int port = 22;
        String username = "your_username";
        String password = "your_password";
        
        Sftp sftp = JschUtil.createSftp(host, port, username, password);
        
        // 使用完毕后记得关闭连接
        sftp.close();
    }
}

在实际项目中,我建议把这些连接参数放在配置文件中,而不是硬编码在代码里。这样既安全又便于维护。

3. 实现文件夹递归下载

3.1 基础递归下载实现

Hutool的Sftp类已经提供了基本的文件操作,但没有直接的文件夹递归下载功能。我们需要自己实现这个逻辑。核心思路是:

  1. 列出远程目录下的所有文件和子目录
  2. 对于每个文件,直接下载到本地对应路径
  3. 对于每个子目录,在本地创建对应目录,然后递归处理

下面是实现代码:

java复制import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ssh.Sftp;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.SftpException;
import java.io.File;
import java.util.Vector;

public class SftpDownloader {
    /**
     * 递归下载SFTP文件夹
     * @param sftp SFTP连接
     * @param remotePath 远程路径
     * @param localPath 本地路径
     * @throws SftpException
     */
    public static void downloadDir(Sftp sftp, String remotePath, String localPath) throws SftpException {
        ChannelSftp channelSftp = sftp.getClient();
        channelSftp.cd(remotePath);
        
        // 列出远程文件夹下的所有内容
        Vector<ChannelSftp.LsEntry> fileList = channelSftp.ls(".");
        
        for (ChannelSftp.LsEntry entry : fileList) {
            String filename = entry.getFilename();
            // 跳过当前目录和上级目录
            if (".".equals(filename) || "..".equals(filename)) {
                continue;
            }
            
            String remoteFilePath = StrUtil.appendIfMissing(remotePath, "/") + filename;
            String localFilePath = StrUtil.appendIfMissing(localPath, "/") + filename;
            
            if (entry.getAttrs().isDir()) {
                // 如果是目录,先创建本地目录,然后递归下载
                FileUtil.mkdir(localFilePath);
                downloadDir(sftp, remoteFilePath, localFilePath);
            } else {
                // 如果是文件,确保父目录存在后下载
                FileUtil.mkdir(FileUtil.file(localFilePath).getParent());
                channelSftp.get(remoteFilePath, localFilePath);
                System.out.println("下载完成: " + remoteFilePath);
            }
        }
    }
}

3.2 处理特殊字符和路径问题

在实际使用中,我发现路径处理有几个常见问题需要注意:

  1. 路径分隔符问题:不同操作系统使用不同的路径分隔符(Windows用\,Linux用/)。Hutool的FileUtil已经处理了这个问题,但远程路径必须使用Linux风格的/。

  2. 特殊字符处理:如果文件名包含空格或特殊字符,需要特别注意。Hutool的StrUtil.appendIfMissing方法可以确保路径拼接正确。

  3. 权限问题:确保本地有创建目录和文件的权限,远程用户有读取文件的权限。

4. 断点续传优化

4.1 断点续传的基本原理

断点续传的核心思想是:在下载中断后,能够从中断点继续下载,而不是从头开始。实现这个功能需要:

  1. 记录已下载的文件信息
  2. 在重新下载时检查本地已有文件
  3. 对于部分下载的文件,从断点处继续

对于SFTP协议,JSch库本身不支持真正的断点续传(即从文件中间继续下载),但我们可以实现"文件级别"的断点续传:只下载那些未完成或缺失的文件。

4.2 实现文件级别的断点续传

下面是增强版的下载工具类,增加了断点续传功能:

java复制import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ssh.Sftp;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.SftpException;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;

public class SftpResumableDownloader {
    // 用于记录已下载的文件路径
    private static Set<String> downloadedFiles = new HashSet<>();
    
    /**
     * 带断点续传功能的递归下载
     * @param sftp SFTP连接
     * @param remotePath 远程路径
     * @param localPath 本地路径
     * @param resume 是否启用断点续传
     * @throws SftpException
     */
    public static void downloadDir(Sftp sftp, String remotePath, String localPath, boolean resume) throws SftpException {
        ChannelSftp channelSftp = sftp.getClient();
        channelSftp.cd(remotePath);
        
        Vector<ChannelSftp.LsEntry> fileList = channelSftp.ls(".");
        
        for (ChannelSftp.LsEntry entry : fileList) {
            String filename = entry.getFilename();
            if (".".equals(filename) || "..".equals(filename)) {
                continue;
            }
            
            String remoteFilePath = StrUtil.appendIfMissing(remotePath, "/") + filename;
            String localFilePath = StrUtil.appendIfMissing(localPath, "/") + filename;
            
            if (entry.getAttrs().isDir()) {
                // 处理目录
                FileUtil.mkdir(localFilePath);
                downloadDir(sftp, remoteFilePath, localFilePath, resume);
            } else {
                // 处理文件
                File localFile = new File(localFilePath);
                
                if (resume && localFile.exists()) {
                    // 如果启用断点续传且文件已存在,跳过下载
                    if (!downloadedFiles.contains(remoteFilePath)) {
                        System.out.println("文件已存在,跳过: " + remoteFilePath);
                        downloadedFiles.add(remoteFilePath);
                    }
                    continue;
                }
                
                // 确保父目录存在
                FileUtil.mkdir(localFile.getParent());
                
                // 下载文件
                channelSftp.get(remoteFilePath, localFilePath);
                downloadedFiles.add(remoteFilePath);
                System.out.println("下载完成: " + remoteFilePath);
            }
        }
    }
}

4.3 更完善的断点续传方案

上面的实现虽然解决了基本的断点续传需求,但还有改进空间:

  1. 文件校验:仅检查文件是否存在是不够的,还应该检查文件大小或校验和(如MD5)是否匹配。

  2. 下载进度记录:将已下载的文件信息持久化到文件或数据库,这样即使程序重启也能恢复。

  3. 并发控制:对于大量文件,可以考虑使用多线程下载提高速度。

下面是增强版的实现,增加了文件大小校验:

java复制// 在原有代码基础上增加文件大小检查
if (resume && localFile.exists()) {
    long localSize = localFile.length();
    long remoteSize = entry.getAttrs().getSize();
    
    if (localSize == remoteSize) {
        System.out.println("文件已完整存在,跳过: " + remoteFilePath);
        downloadedFiles.add(remoteFilePath);
        continue;
    } else if (localSize < remoteSize) {
        System.out.println("发现不完整文件,重新下载: " + remoteFilePath);
        localFile.delete();
    }
    // 如果本地文件比远程还大,也重新下载
    else {
        System.out.println("本地文件异常,重新下载: " + remoteFilePath);
        localFile.delete();
    }
}

5. 完整工具类与使用示例

5.1 完整工具类代码

结合前面的所有优化,下面是完整的工具类实现:

java复制import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ssh.Sftp;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.SftpException;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;

public class EnhancedSftpDownloader {
    private Set<String> downloadedFiles = new HashSet<>();
    private boolean resumeEnabled;
    private Sftp sftp;
    
    public EnhancedSftpDownloader(Sftp sftp, boolean resumeEnabled) {
        this.sftp = sftp;
        this.resumeEnabled = resumeEnabled;
    }
    
    public void downloadDirectory(String remotePath, String localPath) throws SftpException {
        ChannelSftp channelSftp = sftp.getClient();
        channelSftp.cd(remotePath);
        
        Vector<ChannelSftp.LsEntry> entries = channelSftp.ls(".");
        
        for (ChannelSftp.LsEntry entry : entries) {
            String filename = entry.getFilename();
            if (".".equals(filename) || "..".equals(filename)) {
                continue;
            }
            
            String remoteFilePath = StrUtil.appendIfMissing(remotePath, "/") + filename;
            String localFilePath = StrUtil.appendIfMissing(localPath, "/") + filename;
            
            if (entry.getAttrs().isDir()) {
                handleDirectory(remoteFilePath, localFilePath);
            } else {
                handleFile(entry, remoteFilePath, localFilePath);
            }
        }
    }
    
    private void handleDirectory(String remotePath, String localPath) throws SftpException {
        FileUtil.mkdir(localPath);
        downloadDirectory(remotePath, localPath);
    }
    
    private void handleFile(ChannelSftp.LsEntry entry, String remotePath, String localPath) throws SftpException {
        File localFile = new File(localPath);
        
        if (resumeEnabled && localFile.exists()) {
            if (isFileComplete(entry, localFile)) {
                System.out.println("跳过已下载文件: " + remotePath);
                downloadedFiles.add(remotePath);
                return;
            }
            FileUtil.del(localPath);
        }
        
        FileUtil.mkdir(localFile.getParent());
        sftp.getClient().get(remotePath, localPath);
        downloadedFiles.add(remotePath);
        System.out.println("成功下载: " + remotePath);
    }
    
    private boolean isFileComplete(ChannelSftp.LsEntry entry, File localFile) {
        return localFile.length() == entry.getAttrs().getSize();
    }
}

5.2 使用示例

下面是如何使用这个增强版的下载工具类:

java复制import cn.hutool.extra.ssh.JschUtil;
import cn.hutool.extra.ssh.Sftp;

public class Demo {
    public static void main(String[] args) {
        String host = "sftp.example.com";
        int port = 22;
        String username = "user";
        String password = "password";
        String remotePath = "/path/to/remote/folder";
        String localPath = "C:/downloads/local_folder";
        
        // 创建SFTP连接
        Sftp sftp = JschUtil.createSftp(host, port, username, password);
        
        try {
            // 创建下载器实例,启用断点续传
            EnhancedSftpDownloader downloader = new EnhancedSftpDownloader(sftp, true);
            
            // 开始下载
            downloader.downloadDirectory(remotePath, localPath);
            
            System.out.println("下载任务完成");
        } catch (Exception e) {
            System.err.println("下载过程中出错: " + e.getMessage());
            e.printStackTrace();
        } finally {
            // 确保关闭连接
            sftp.close();
        }
    }
}

5.3 实际应用中的注意事项

在实际项目中使用这个工具时,有几个经验分享:

  1. 连接超时设置:默认情况下,JSch的连接超时时间可能不够长。可以通过以下方式调整:
java复制import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

Session session = JSch.getSession(username, host, port);
session.setPassword(password);
// 设置连接超时为30秒
session.setTimeout(30000);
session.connect();
Sftp sftp = new Sftp(session);
  1. 错误处理:网络操作很容易出错,需要完善的错误处理和重试机制。我通常会为下载操作添加重试逻辑:
java复制private void downloadWithRetry(String remotePath, String localPath, int maxRetries) throws SftpException {
    int retries = 0;
    while (retries < maxRetries) {
        try {
            sftp.getClient().get(remotePath, localPath);
            return;
        } catch (SftpException e) {
            retries++;
            if (retries >= maxRetries) {
                throw e;
            }
            System.out.println("下载失败,第" + retries + "次重试...");
            try {
                Thread.sleep(1000 * retries); // 指数退避
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                throw new SftpException(0, "下载被中断");
            }
        }
    }
}
  1. 性能优化:对于包含大量小文件的目录,递归下载可能会很慢。可以考虑使用多线程来并行下载不同子目录中的文件。但要注意线程安全和SFTP连接的限制。

内容推荐

FastLIO点云去畸变实战:解析Velodyne雷达时间戳的“负值”之谜
本文深入解析FastLIO处理Velodyne雷达点云时遇到的“负时间戳”现象,揭示其硬件工作机制,并提出两种时间补偿方案(首点基准补偿法和末包时间基准法)的实战对比。通过5Hz与10Hz扫描频率的差异分析及参数调优建议,帮助开发者有效解决点云去畸变问题,提升定位精度和建图效果。
别再瞎调采样率了!NI-DAQmx硬件定时与软件定时实战选择指南(附避坑清单)
本文深入解析NI-DAQmx硬件定时与软件定时的核心差异、性能边界及适用场景,提供实战选择指南和避坑清单。通过对比测试数据和应用案例,帮助工程师在数据采集项目中做出精准决策,避免采样率设置不当导致的系统问题。特别适合工业自动化和设备监测领域的专业人士参考。
Spring Boot Actuator自定义端点踩坑记:为什么我的@Endpoint注解Restful路径访问不了?
本文深入分析了Spring Boot Actuator中自定义端点Restful路径访问失效的问题,揭示了因缺少Java编译参数`-parameters`导致`@Selector`注解参数名丢失的根源。通过源码追踪和环境验证,提供了IntelliJ、Maven、Gradle等多环境下的具体解决方案,帮助开发者正确配置以实现Restful风格路径访问。
从滞回到滤波:集成运放三波形发生器的设计与调测全解析
本文详细解析了集成运放三波形发生器的设计与调测过程,涵盖滞回比较器、积分电路和滤波电路的设计要点。通过LF347运放实现正弦波、方波和三角波的同步生成,提供实用的调试技巧和性能优化方案,适合模电设计者和电子爱好者参考。
ATK-ESP8266模块AP模式实战:5分钟搭建一个属于你的智能硬件调试Wi-Fi热点
本文详细介绍了如何使用ATK-ESP8266模块的AP模式快速搭建智能硬件调试Wi-Fi热点。通过硬件准备、AT指令配置和网络调试实战,帮助开发者在5分钟内完成热点的创建与通信测试,适用于户外调试、展会演示等场景。文章还提供了常见问题排查和性能优化建议,确保热点的稳定性和实用性。
SwiftUI 5.0 中 @Observable 状态管理的性能优化与内存陷阱
本文深入探讨了SwiftUI 5.0中@Observable状态管理的性能优化与内存陷阱。通过对比@Observable与传统的@ObservedObject,展示了其在细粒度观察和性能提升上的优势,并提供了三大实战策略和常见内存问题的解决方案,帮助开发者高效利用这一新特性。
从GEO下载单细胞数据到Seurat对象,保姆级避坑指南(附MTX格式文件检查清单)
本文详细解析了单细胞测序数据MTX格式的全流程处理,从GEO数据库下载到Seurat对象构建的实战指南。重点介绍了MTX格式文件的规范检查、环境配置、数据加载和质量控制等关键步骤,帮助研究者避免常见错误,提高数据分析效率。
PyCharm Conda路径识别失败:从环境变量到解释器配置的完整排错指南
本文详细解析了PyCharm无法识别Conda路径的常见原因及解决方案,包括系统环境变量配置、PyCharm内部环境设置及高级排查技巧。通过实战案例和最佳实践建议,帮助开发者快速解决Python解释器配置问题,提升开发效率。
别再死记硬背LFSR了!用Verilog手把手带你玩转FPGA上的伪随机数生成(附完整代码)
本文深入探讨了基于线性反馈移位寄存器(LFSR)的FPGA伪随机数生成技术,通过Verilog代码实现和优化技巧,帮助开发者高效构建高性能随机数引擎。文章详细解析了LFSR的原理、工程化实现及高级应用场景,并提供了完整的代码示例和可靠性增强方案,适合硬件工程师和FPGA开发者参考。
【thop.profile实战】从零解析模型复杂度:参数量与计算效率的精准评估
本文详细解析了如何使用thop.profile工具评估深度学习模型的复杂度,包括参数量和计算效率(FLOPs)的精准测量。通过实战案例展示了ResNet、Transformer等经典模型的评估方法,并提供了模型优化和部署前的关键检查项,帮助开发者提升模型计算效率与部署效果。
别再踩坑了!PyTorch3D 保姆级安装指南(附CUDA 11.3/11.7、Python 3.8/3.9版本匹配清单)
本文提供了PyTorch3D的保姆级安装指南,详细解析了版本依赖关系,包括Python、CUDA和PyTorch的精确匹配要求。通过分场景安装方案和常见错误解决方案,帮助开发者高效完成安装并验证性能,避免常见的安装陷阱。
预测股价?先搞懂AR模型平稳性的3个统计‘体检’指标:从ACF/PACF图到单位根检验
本文深入解析了AR模型平稳性的三个关键统计指标:ACF/PACF图和单位根检验,帮助投资者在预测股价前准确判断时间序列的平稳性。通过均值稳定性观察、方差有限性诊断和ACF/PACF图解读,结合Python代码示例,指导读者避免常见建模误区,提升金融时间序列分析的准确性。
Windows平台下pg_jieba编译实战:从源码到中文分词扩展
本文详细介绍了在Windows平台下编译pg_jieba中文分词扩展的完整流程,包括环境准备、源码修改、CMake配置调整、Visual Studio编译实战以及常见问题排查。通过实战案例,帮助开发者快速掌握pg_jieba的编译与安装技巧,提升中文文本处理效率。
【Telephony】AOSP中SIM卡状态机与广播机制深度剖析
本文深度剖析了AOSP中SIM卡状态机与广播机制的核心架构,详细解析了从硬件层到应用层的完整事件链路。通过状态机设计、广播优化及典型问题排查指南,帮助开发者理解Telephony子系统的工作原理,提升SIM卡状态管理的可靠性和性能。
从PTA链表重排到实战:双指针与数组映射的解题艺术
本文深入探讨了链表重排问题的解决策略,重点介绍了双指针技术和数组映射的应用。通过快慢指针定位中点、链表反转和合并等步骤,展示了如何高效处理PTA链表重排问题,同时优化时间和空间复杂度。文章还提供了完整的C语言实现和边界条件处理技巧,帮助读者掌握数据结构与算法的实战应用。
别再问OA运维难不难了!从B/S到C/S,手把手教你搞定Windows服务器上的OA系统部署
本文详细解析了OA系统在Windows服务器上的部署流程,涵盖B/S和C/S架构的配置要点。从环境准备到安全加固,提供完整的运维指南,帮助解决OA系统部署中的常见问题,提升运维效率。特别针对OA运维中的难点给出实用解决方案。
用Arduino和树莓派搞定麦克纳姆轮小车:从PID调参到循迹避坑的实战心得
本文详细介绍了如何利用Arduino和树莓派协同开发麦克纳姆轮小车,涵盖从PID调参到智能循迹的实战经验。通过硬件架构设计、运动控制算法实现及多传感器融合策略,打造响应迅速的全向移动平台,特别适合机器人爱好者与工程实践者参考。
UE5蓝图通信别再死记硬背了!用‘开关门’和‘BOSS死亡’两个实战案例,带你彻底搞懂事件分发器和接口
本文通过UE5中‘开关门’和‘BOSS死亡’两个实战案例,深入解析蓝图通信的核心机制。重点介绍了事件分发器和接口的应用,帮助开发者摆脱死记硬背,灵活选择最佳通信方案。内容涵盖从基础实现到高级架构设计,是提升虚幻引擎开发效率的实用指南。
从零构建渗透测试沙箱:iptables端口隔离、ICMP策略与hosts加固实战
本文详细介绍了如何从零构建渗透测试沙箱,重点讲解了iptables端口隔离、ICMP策略与hosts加固的实战方法。通过三层防护体系(网络层、应用层、监控层)确保沙箱既保持网络可达性又严格封锁所有服务端口,适用于渗透测试训练和攻击行为分析。文章还提供了自动化监控脚本和防护效果验证方案,帮助安全工程师打造坚不可摧的测试环境。
十三、USB PD之Power Supply:从协议规范到工程实践的关键考量
本文深入探讨USB PD Power Supply从协议规范到工程实践的关键考量,涵盖电压切换、动态负载管理、保护机制及性能优化等核心问题。通过实际案例解析,如VBUS电压震荡、PPS电源调节等,揭示协议参数背后的工程意义,为电源设计提供实用指导。
已经到底了哦
精选内容
热门内容
最新内容
用ZYNQ FPGA和NVMe盘,我手搓了一个2GB/s的国产高速存储盒(附完整配置流程)
本文详细介绍了如何利用ZYNQ FPGA和NVMe固态盘构建读写速度突破2GB/s的高速存储系统。从硬件选型、PCIe链路调优到Linux驱动适配,全面解析了实现极速存储方案的关键技术,为开发者提供了完整的配置流程和性能优化策略。
手把手教你用STM32F103的SPI2驱动FPGA:从Verilog代码到硬件联调(附完整工程)
本文详细介绍了如何使用STM32F103的SPI2驱动FPGA,涵盖从Verilog代码编写到硬件联调的全过程。通过硬件连接指南、STM32端SPI配置、FPGA端Verilog实现以及系统联调技巧,帮助开发者快速掌握STM32与FPGA的SPI通信技术,解决实际开发中的常见问题。
60、Flink CEP实战:从模式定义到超时处理的复杂事件检测全流程解析
本文全面解析Flink CEP在复杂事件处理中的实战应用,从模式定义、条件设置到超时处理的全流程。通过金融风控、工业物联网等典型场景示例,详细讲解如何利用Flink CEP API检测实时数据流中的关键模式,并分享生产环境的最佳实践和性能优化技巧。
基于Docker Compose编排DataX与DataX-Web的自动化部署实践
本文详细介绍了如何使用Docker Compose编排DataX与DataX-Web实现自动化部署,提升数据同步效率。通过环境准备、镜像选择、Docker Compose配置、服务优化等实战步骤,帮助开发者快速搭建稳定可靠的数据同步平台,解决传统部署中的环境配置难题。
实战解析 | TSMaster 总线记录高级配置与性能优化
本文深入解析TSMaster总线记录功能的高级配置与性能优化技巧,涵盖CAN、LIN等多协议支持。通过智能文件分割、多通道隔离记录等实战方案,提升汽车电子测试效率,并分享系统资源控制、高效过滤器配置等优化经验,助力工程师精准分析总线数据。
QFN芯片焊接翻车实录:从‘吹飞芯片’到‘完美归位’,我的热风枪参数调试血泪史
本文分享了QFN芯片焊接的实战经验,从热风枪参数调试到完美焊接的全过程。详细解析了风速、温度、距离等关键参数的科学设置,以及焊盘预处理、芯片对位等实用技巧,帮助读者避免常见焊接问题,提升QFN封装芯片的焊接成功率。
影刀RPA高级考试实战:用Python绕过反爬,把电影票房数据自动存进MySQL数据库
本文详细介绍了如何利用影刀RPA和Python技术实现电影票房数据的自动化采集与存储。通过实战案例,展示了如何绕过反爬机制、使用XPath精准提取数据、进行数据清洗与类型转换,并将处理后的数据高效存储至MySQL数据库。文章还提供了连接池管理、批量插入优化等工业级解决方案,帮助开发者提升自动化数据处理能力。
告别人工规则!用PyTorch+图神经网络(GNN)打造车间调度AI大脑(附代码实战)
本文介绍如何利用PyTorch和图神经网络(GNN)构建智能车间调度系统,替代传统人工规则方法。通过深度强化学习(DRL)与GNN结合,解决Job Shop Scheduling Problem (JSSP)中的多约束耦合和动态环境变化挑战,并提供工业级代码实现和部署方案,显著提升调度效率和适应性。
别再死记硬背MAML公式了!用PyTorch手把手实现一个5-way 1-shot图像分类任务
本文详细介绍了如何使用PyTorch实现MAML(Model-Agnostic Meta-Learning)算法,解决5-way 1-shot图像分类任务。通过元学习方法,模型能够快速适应新任务,仅需少量样本即可实现高效分类。文章包含代码实现、数据加载器设计、网络结构优化及训练技巧,帮助开发者深入理解MAML的核心机制并应用于实际场景。
FPGA仿真太慢?教你用Verilog parameter快速搭建“调试模式”,效率提升10倍
本文探讨了如何利用Verilog parameter快速搭建调试模式,显著提升FPGA仿真效率。通过参数化设计动态调整时序尺度,结合分层参数传递和自动化参数注入技术,实现仿真速度10倍以上的提升,特别适用于大型数字电路设计的调试与验证。