Pythonゼミ 第9回 FTPからデータのダウンロード


Last updated: 2024/04/28

FALMAの観測データの量は非常に多いので(年間数テラバイト)、データは基本的に研究室のFTPサーバーに保存されます。
*FTPの意味について自分で調べてください。
研究室のFTPサーバーにアクセルするために、研究室に来て、大学のネットに繋がる必要があります。


まず、FTPソフトを使ってデータをダウンロードする方法を紹介します。
いろんな FTP ソフトがありますが、ここは WinSCP という無料ソフトを使います。(MacではFileZillaがいいかもしれません)


WinSCPをダウンロード、インストールする。
https://winscp.net/eng/download.php


FTP 情報を入れて。Save。(passwordはdischarge)

Save password

繋いだら、下のような画面になる。

ルートボタンを押して

mediaフォルダーを開いて

lightningフォルダーを開いて

この中にいろんなデータがあります。

2018年冬のデータはHDD1/2018LFに保存されています

*FileZillaでも同じようにFTP情報を設定して、ディレクトリ- /media/lightning/HDD1/2018LF/に入ってください。


この中に一つフォルダーは一日のデータです。その中に、各サイトのデータがあります。 データをダウンロードするときは、データを選んで、右クリック⇒Download


FTPに保存されているデータのまとめ:
2017年夏:/media/lightning/HDD1/2017backup
2018年冬:/media/lightning/HDD1/2018LF
2019年冬:/media/lightning/HDD1/2019LF
2020年冬:/media/lightning/HDD1/2020LF
各観測の標定結果・画像:/home/lightning/results
気象レーダーのデータ:/media/lightning/HDD1/radar
雨雲・落雷画像(2021年3月まで):/media/lightning/DISK/radar_lightning
雨雲画像(2021年4月から):/media/lightning/DISK/rain
落雷画像(2021年4月から):/media/lightning/DISK/lightning
雷研究論文:/media/lightning/DISK/research_paper


FTPソフトでのダウンロードは簡単ですが、実際に研究するときこの方法は非常に手間がかかります。 例えば、第8回で処理した時刻1548422986のすべてのサイトのデータをダウンロードしたいなら、 まず、この時刻を普通の時間に変換して、その日のフォルダーを開いて、さらに、その中の一つ一つのサイトのフォルダーを開いて、 各フォルダーの中に時刻1548422986のデータを見つけて、一つ一つダウンロードする必要があります。(どれほど面倒か試してみてください。)

こういう場合は、pythonを使ったほうがずっと便利です。


1. FTPにあるフォルダーの中のファイルリスト


自分のパソコンにあるフォルダーの中のファイル名の行列は、os.listdir()で作るのは皆さん既に分かると思います。 FTPにも同じようなことができます。

例えば、以下のコードは/media/lightning/2018LF/の中のすべてのフォルダーの名前を行列にする。

from ftplib import FTP #FTPモジュールをインポートする

ftp_add = '10.226.82.10'
ftp_port = 21
ftp_account = 'lightning'
ftp_key = 'discharge'
ftp_root = '/media/lightning/HDD1/2018LF/'

#log in
ftp = FTP()
ftp.connect(ftp_add, ftp_port)
ftp.login(ftp_account, ftp_key)

ftp.cwd(ftp_root) #ディレクトリーに入る

dirMat = ftp.nlst() #現在のディレクトリーのファイルリスト

ftp.close() #操作が終わったら、必ずclose

print(dirMat)
>>
['20181124', '20181125', '20181126', '20181128', '20181129', '20181130', 
'20181201', '20181204', '20181205', '20181206', '20181207', '20181208', 
'20181209', '20181210', '20181211', '20181212', '20181213', '20181214', 
'20181215', '20181216', '20181217', '20181218', '20181219', '20181220', 
'20181221', '20181222', '20181223', '20181224', '20181225', '20181226', 
'20181227', '20181228', '20181229', '20181230', '20181231', '20190101', 
'20190102', '20190103', '20190104', '20190105', '20190106', '20190107', 
'20190108', '20190109', '20190110', '20190111', '20190112', '20190113', 
'20190114', '20190115', '20190116', '20190117', '20190118', '20190119', 
'20190120', '20190121', '20190122', '20190123', '20190124', '20190125', 
'20190126', '20190127', '20190128', '20190129', '20190130', '20190131', 
'20190201', '20190202', '20190203', '20190204', '20190205', '20190206', 
'20190207', '20190208', '20190210', '20190211', '20190212', '20190213', 
'20190214', '20190215', '20190216', '20190217', '20190218', '20190219', 
'20190220', '20190221', '20190222', '20190223', '20190224', '20190225', 
'20190226', '20190227', '20190228', '20190301', '20190302', '20190303', 
'20190304', '20190305', '20190306', '20190307', '20190308', '20190309', 
'20190310', '20190311', '20190312', '20190313', '20190314', '20190315', 
'20190316', '20190317', '20190318', '20190319', '20190320', '20190321', 
'20190322', '20190323', '20190324', '20190325', '20190326', '20190327', 
'20190328', '20190329', '20190330', '20190331']

2. ファイルのダウンロード


一つファイルAKKL1548422986.bz2をダウンロードするコードを組みます。

import os
import datetime
from ftplib import FTP

#変数は最初に書いておく
strTime = '1548422986'
siteName = 'AKK'

fileName = siteName+'L'+strTime+'.bz2'

storeDir = 'F:/Course/python/09/download/'
if os.path.exists(storeDir)==False:
    os.mkdir(storeDir)
	
strDate = datetime.datetime.fromtimestamp(int(strTime)).strftime('%Y%m%d')

ftp_add = '10.226.82.10'
ftp_port = 21
ftp_account = 'lightning'
ftp_key = 'discharge'
ftp_root = '/media/lightning/HDD1/2018LF/'

#log in
ftp = FTP()
ftp.connect(ftp_add, ftp_port)
ftp.login(ftp_account, ftp_key)

#データを保存するフォルダーに入る
ftpDir = ftp_root+strDate+'/'+siteName+'/'
ftp.cwd(ftpDir)

#ダウンロード。RETRのあとは空白一つが必要
fidFile = open(storeDir+fileName, 'wb')
ftp.retrbinary('RETR '+fileName, fidFile.write)
fidFile.close()

ftp.close()

実行して、問題がなければ、指定されたstoreDirにAKKL1548422986.bz2が保存される。


3.ネットが途切れる場合の対応


特に大量なデータをダウンロードするとき、ネットが途切れることがよくあります。 ネットが途切れるたびにプログラムが止まると困りますので、対応したほうがいいです。

import os
import datetime
from ftplib import FTP
from time import sleep

strTime = '1548422986'
siteName = 'AKK'

fileName = siteName+'L'+strTime+'.bz2'

storeDir = 'F:/Course/python/09/download/'
if os.path.exists(storeDir)==False:
    os.mkdir(storeDir)
	
strDate = datetime.datetime.fromtimestamp(int(strTime)).strftime('%Y%m%d')

ftp_add = '10.226.82.10'
ftp_port = 21
ftp_account = 'lightning'
ftp_key = 'discharge'
ftp_root = '/media/lightning/HDD1/2018LF/'
ftpDir = ftp_root+strDate+'/'+siteName+'/'

while True:
    #tryの中に何かエラーがあれば、exceptの部分のコードが実行される
    #whileループの中にあるので、もう一回ダウンロードすることになる
    try:
        #log in
        ftp = FTP()
        ftp.connect(ftp_add, ftp_port)
        ftp.login(ftp_account, ftp_key)
        
        ftp.cwd(ftpDir)
        
        #Download
        fidFile = open(storeDir+fileName, 'wb')
        ftp.retrbinary('RETR '+fileName, fidFile.write)
        fidFile.close()
        #無事ダウンロードできたら、breakでwhileループから出る
        break
    except Exception as e:
        #エラーがあれば、エラーメッセージをプリントする。
        #そして、数秒休憩する(sleep関数は行4でimportした)
        print(e)
        sleep(5)
    
ftp.close()


問題


一つのプログラムで以下の時刻のすべてのサイトのデータをダウンロードして、各時刻の波形図(第8回第1問のような波形図)を作る。

[時刻リスト]
1545021124
1545208723
1547538709
1547722288
1548077742
1548086292
1548221080
1552375973


注意:一つの時刻の雷はすべてのサイトに観測されたとは限らないです。 だから、各サイトのデータをダウンロードする前に、そのサイトのその時刻のデータが存在するかどうか確認する必要があります。
*データ量はそんなに多くないので、try exceptを使わなくて結構です。使うなら若干ややこしくなります。


できた各時刻の波形図