淘先锋技术网

首页 1 2 3 4 5 6 7

领导需求:基于Python开发一个小工具,使其能够实现从目标FTP服务器指定路径中实时轮训下载或更新文件到本地指定路径,仅供学习或参考。

SQLite3安装教程:点击转到我参考的SQLite安装教程

废话不多说直接上代码:

FTPwindow.py:

# -*- coding: utf-8 -*-
import time
import os
from ftplib import FTP, error_perm
import configparser
import datetime
from datetime import datetime
import sqlite


class FTP_OP:
    def __init__(self, host, username, password, port, passive):
        self.host = host
        self.username = username
        self.password = password
        self.port = port
        self.passive = passive
        self.downloaded_files = {}

    def ftp_connect(self):
        try:
            ftp = FTP()
            ftp.encoding = 'gbk'
            ftp.set_debuglevel(0)
            ftp.connect(self.host, self.port)
            ftp.login(self.username, self.password)
            ftp.set_pasv(self.passive)
            return ftp
        except Exception as e:
            print(f"连接ftp server失败:{e}")
            return None

    def download_directory(self, ftp, path, local_path):
        try:
            file_list = []
            ftp.retrlines('LIST', file_list.append)

            for file in file_list:
                split = file.split()
                permissions = split[0]
                file_name = split[-1]
                file_size = split[4]  # 获取文件大小
                file_mtime = split[5] + ' ' + split[6]  # 获取文件修改时间

                if permissions.startswith('d'):
                    new_path = os.path.join(path, file_name)
                    local_new_path = os.path.join(local_path, file_name)
                    print("正在创建对应目录:", new_path)
                    os.makedirs(local_new_path, exist_ok=True)
                    ftp.cwd(file_name)
                    self.download_directory(ftp, new_path, local_new_path)
                    ftp.cwd('..')
                else:
                    file_path = os.path.join(local_path, file_name)
                    if file_name not in self.downloaded_files:
                        last_size, last_mtime = None, None
                    else:
                        # 获取字典中保存的文件大小和修改时间
                        last_size, last_mtime = self.downloaded_files[file_name]

                    if file_name in self.downloaded_files:
                        # 比较FTP服务器中的文件大小和修改时间与字典中的是否一致
                        if file_size == last_size and self.compare_time(file_mtime, last_mtime):
                            print(f"文件 '{file_name}' 未做过任何变化,无需更新")
                            continue

                    print(f"正在下载文件:{file_path}")
                    with open(file_path, 'wb') as f:
                        ftp.retrbinary(f'RETR {file_name}', f.write)

                    # 将文件名、文件大小和修改时间保存到字典中
                    self.downloaded_files[file_name] = (file_size, file_mtime)

                    if file_size != last_size:
                        print(f"文件 '{file_name}' 根据大小判断有变化,进行了更新")
                        updatetime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                        sqlite.insert(file_name, file_size, updatetime,file_mtime)

                    else:
                        print(f"文件 '{file_name}' 根据修改时间判断有变化,进行了更新")
                        updatetime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                        sqlite.insert(file_name, file_size,updatetime, file_mtime)
        except Exception as e:
            print(f"下载目录失败:{e}")

    def compare_time(self, time1, time2):
        # 将时间字符串转换为datetime对象
        dt1 = datetime.strptime(time1, '%b %d')
        dt2 = datetime.strptime(time2, '%b %d')
        return dt1 == dt2

    def download_file(self, ftp_filefolder, dst_filefolder):
        try:
            ftp = self.ftp_connect()
            if ftp is not None:
                ftp.cwd(ftp_filefolder)
                self.download_directory(ftp, ftp_filefolder, dst_filefolder)
                ftp.quit()
        except Exception as e:
            print(f"下载文件失败:{e}")


def read_config(config_file):
    config = configparser.ConfigParser()
    config.read(config_file)
    host = config.get('FTP', 'host')
    username = config.get('FTP', 'username')
    password = config.get('FTP', 'password')
    port = config.getint('FTP', 'port')
    ftp_filefolder = config.get('FTP', 'ftp_filefolder')
    dst_filefolder = config.get('FTP', 'dst_filefolder')
    return host, username, password, port, ftp_filefolder, dst_filefolder


if __name__ == '__main__':
    config_file = 'config.ini'
    host, username, password, port, ftp_filefolder, dst_filefolder = read_config(config_file)
    os.makedirs(dst_filefolder, exist_ok=True)
    sqlite = sqlite.Sqlite()  # 创建 Sqlite 实例
    ftp = FTP_OP(host, username, password, port, passive=False)
    try:
        while True:
            ftp.download_file(ftp_filefolder, dst_filefolder)
            time.sleep(10)
    except KeyboardInterrupt:
        print('用户终止程序')

sqlite.py:

import sqlite3


class Sqlite:

    def __init__(self):
        self.conn = sqlite3.connect('ftpdown_log.db')
        print("Opened database successfully")
        self.cursor = self.conn.cursor()
        self.create_table()
        self.select()

    def create_table(self):
        create_table = '''CREATE TABLE IF NOT EXISTS ftpdown_log (
           id INTEGER PRIMARY KEY AUTOINCREMENT,
           file_name TEXT ,
           file_size TEXT ,
           update_time TEXT ,
           file_mtime TEXT
        );
        '''
        self.cursor.execute(create_table)
        self.conn.commit()
        print("Table created successfully")

    def insert(self, file_name, file_size, update_time, file_mtime):
        insert_data = f"INSERT INTO ftpdown_log (file_name, file_size, update_time,file_mtime) VALUES (?, ?, ?, ?);"
        self.cursor.execute(insert_data, (file_name, file_size, update_time, file_mtime))
        self.conn.commit()
        print("Records created successfully")

    def select(self):
        select_data = "SELECT * FROM ftpdown_log"
        cursor = self.conn.execute(select_data)
        for row in cursor:
            print("id =", row[0])
            print("file_name =", row[1])
            print("file_size =", row[2])
            print("update_time =", row[3])
            print("file_mtime =", row[4], "\n")
        print("Operation done successfully")

config.ini:

[FTP]
host = 192.168.0.253
username = root
password = password
port = 21
ftp_filefolder = /log/
dst_filefolder = d:/1/

项目工程结构如下:
FTPwindow.py  // 实现FTP的连接,对ini配置文件的读取,指定路径中的文件夹及文件的下载

sqlite.py:  //实现sqlite的数据库的创建,表的创建

config.ini:  //实现为程序提供FTP地址、用户名、密码、端口号、目标指定路径、下载路径

效果如下:

以上为个人学习的记录,仅供参考和交流学习。