Python ftplibでFTPサーバからダウンロード

#cyberduck#ftp#Python

PythonでFTPサーバからファイルをダウンロードします。 HTTPリクエストでよく使うrequestsはFTPに対応していません。 ftplibというライブラリを使用します。

ディレクトリ内のファイルを全てダウンロード

ftplibは標準ライブラリなのでpipなど使わずにそのままインポートできます。 今回は例としてPubChemからファイルをダウンロードします。 PubChemについてはこちらの記事を参照。   フルだと大変(2017年12月現在、12345ファイル、117GB)なので適当な日付のディレクトリを使います。 Dailyディレクトリ内のディレクトリは毎週更新されるので、こちらから確認してアクセス可能な日付のものに読み替えてください。   ここでは2017-12-17/ディレクトリを使用します。 pubchem/Substance/Daily/2017-12-17/XML/ディレクトリから全ファイルをダウンロードします。

from ftplib import FTP
ftp = FTP('ftp.ncbi.nlm.nih.gov')
ftp.login()
ftp.cwd('pubchem/Substance/Daily/2017-12-17/XML/')
files = ftp.nlst('.')
for file in files:
print(file)
with open('pubchem/' + file, 'wb') as f:
ftp.retrbinary('RETR %s' % file, f.write)
ftp.quit()

  それぞれ簡単な解説を入れます。

FTP(host)

hostに対してFTP接続を開始します。 オプション引数のuserやpasswdを指定すればここで次の項目のログインを行えます。

login()

接続します。特に認証が必要なければ引数はなしで。 必要ならuser, passwdを持たせます。

cwd()

ディレクトリを移動します。 上記ソースのように現在位置からの相対パス指定で移動できます。

nlst()

カレントディレクトリ内のファイルのリストを返します。 これをfor文に渡すことで全てのファイルに対して、例えばダウンロードなどの処理を行えます。

retrbinary()

バイナリデータの取得に使います。 引数にFTPコマンドを使用します。ここではRETRを使いました。 第二引数はオプションです。何も指定しなければ標準出力、ファイルを指定すればファイルに保存できます。 テキストデータの取得にはretrlines()を使います。

quit()

通信が終わったら接続を切りましょう。

ディレクトリ内のファイルのサイズを取得する

from ftplib import FTP
size = 0
ftp = FTP('ftp.ncbi.nlm.nih.gov')
ftp.login()
ftp.cwd('pubchem/Substance/CURRENT-Full/XML/')
files = ftp.nlst('.')
for i, file in enumerate(files):
ftp.voidcmd('TYPE I')
size += ftp.size(file)
ftp.quit()
print(size)

size()

ファイルを引数にすることでそのファイルのバイト数を取得する。 *直前にpython]ftp.voidcmd('TYPE I')でバイナリモードにしないとエラーが出ます。

Cyberduck

とかやったけど普通にFTPソフト使えばよかった。 Cyberduckでダウンロードします。 右クリックでダウンロードするだけ。便利。   でもフルで取得しようと思ったらすごい時間かかる。 うまいこと分割しないと。

参考