
[Python] FTPから最新ファイルをダウンロードする
はじめに
Pythonで、FTPサーバー上の指定ディレクトリ内にある最新ファイルのみをダウンロードする処理を実装します。
使用するライブラリ
・ftplib
FTPサーバーとのやり取りに使用できるライブラリ。FTPコマンドベースで使用することが可能になります。標準ライブラリのため、インストールは不要です。
・datetime
日付型、時間型のライブラリ。
動作環境
・windows10
・Jupyter Notebook 6.2.0
・Python 3.8.5
実装
全体のコードは下記です。
from ftplib import FTP
from datetime import datetime
ftp_host = 'ホスト名'
ftp_user = 'ユーザー名'
ftp_pwd = 'パスワード'
with FTP(ftp_host,ftp_user,ftp_pwd) as ftp:
# ディレクトリ移動
ftp.cwd('/xxx/xxxxxxx/')
file_list = []
# ファイル情報を取得
files_info = ftp.mlsd()
for filename, info in files_info:
# ファイルのみ取得する
if info['type'] == 'file':
modify_dt = datetime.strptime(info['modify'],"%Y%m%d%H%M%S")
file_list.append([filename,modify_dt])
# ファイル更新日が最新のファイルを取得
latest_file = max(file_list, key = lambda x:x[1])
# ファイルをダウンロード
with open(latest_file[0], 'wb') as fp:
ftp.retrbinary(f'RETR {latest_file[0]}', fp.write)
実装の詳細内容です。
・FTP接続
FTP接続をするには、ftplibライブラリを使用します。今回はFTPクラスを使用して、インスタンスを生成します。
ftp = FTP(ftp_host,ftp_user,ftp_pwd)
引数には、
host:ホスト名(キーワード引数:host=)
user : ユーザ名(キーワード引数:user=)
passwd : パスワード(キーワード引数:passwd=)
の設定が可能です。
第1引数のホスト名のみ引数に設定して、後の処理でログインすることもできます。
ftp = FTP(ftp_host)
ftp.login(ftp_user, ftp_pwd)
with文もサポートしているので、下記のように記述できます。
with FTP(ftp_host,ftp_user,ftp_pwd) as ftp:
with文は、事前に定義されているクリーンアップ処理を利用する場合に使用できます。
今回の場合、with文の中のブロックから抜ける前に、接続解除を行うftp.quit()が実行されるとなるので、with文を使って実装することで、接続解除し忘れが防げます。
・ディレクトリの移動
# ディレクトリ移動
ftp.cwd('/xxx/xxxxxxx/')
FTPのCWDコマンドと同様です。引数のパスをカレントディレクトリにするメソッドです。なお、引数には移動したいパス(相対、もしく絶対)を指定します。
・ファイル一覧を標準出力に出力する
ftp.dir()
FTPのLISTコマンドで取得できる情報と一緒です。
ここから、ファイル情報の詳細を取得する場合、文字列の操作が必要になります…
・ファイル情報詳細を取得
files_info = ftp.mlsd()
FTPのMLSDコマンドと同様です。FTPサーバがMLSDコマンドをサポートしている場合、このメソッドを使用することができます。
今回は、ファイル名と更新日時を取得したいので、こちらのメソッドを使用します。
ファイル情報として取得できる内容は、下記でした。
('..',
{'modify': '20210914052253',
'perm': 'xxxxxxx',
'type': 'pdir',
'unique': 'xxxxxxxxxxxx',
'unix.group': '9999',
'unix.mode': '0755',
'unix.owner': 'xxxx'})
1番目:ファイル名、2つ目以降の情報は、辞書型で格納されています。
'modify'キーで、ファイルの更新日時を取得します。
ファイルの更新日時が文字列型となっているため、datetime型に変換します。
今回使用しているFTPサーバーでは、更新日時がYYYYMMDDHHMMSS形式で格納されていたので、フォーマットを指定して変換しています。
更新日時が最新のファイルを取得
# ファイル更新日が最新のファイルを取得
latest_file = max(file_list, key = lambda x:x[1])
mlsdメソッドで、
・ファイル名
・ファイルの更新日時
の2つの情報をリスト型で取得しました。
最新日時のファイルのリスト要素を取得するのに、max関数を使用しました。更新日時は、2つ目に格納されているので、lambda関数で要素のインデックスを指定しています。
・ファイルのダウンロード
# ファイルをダウンロード
with open(latest_file[0], 'wb') as fp:
ftp.retrbinary(f'RETR {latest_file[0]}', fp.write)
第1引数には、'RETR ファイル名'を指定します。ファイル名には、パスが指定できないので、cwdメソッドでディレクトリを移動しておく必要があります。
このメソッドを実行すると、Pythonを実行しているフォルダにファイルがダウンロードされます。
・FTPの接続解除
ftp.quit()
FTPサーバーとの接続を解除します。今回はwith文で実装したので、こちらのメソッドは使用していません。
まとめ
今回は、Pythonで、FTPサーバー上の指定ディレクトリ内にある最新ファイルのみをダウンロードする処理を実装しました。この処理は、定期実行を行うので、cronの設定を行う予定です。
なお、使用しているFTPサーバーによっては、ご紹介した実装のままだと動作しないケースもある可能性もあります。その際には、FTPサーバーの仕様をご確認ください。
参考サイト