レンタルサーバーなどを利用して、Webサイトを運営している方は比較的多いことだろう。最近では、いろいろなWebアプリがあるので、Web上に売上データなどが自動生成される場合も増えている。そこで今回は、Pythonのスクリプトを作って、FTPS経由で生成されたデータを自動的にダウンロードするツールを作ってみよう。

  • FTPSでサーバーに接続しファイル一覧をダウンロードします

    FTPSでサーバーに接続しファイル一覧をダウンロードします

Webサーバーのバックアップ体制は万全?

最近は、いろいろな便利なWebアプリがあるので、それらをレンタルサーバーに転送して、ちょっと設定すれば、Wikiや掲示板、ブログや通販システムを手軽に動かすことができる。しかし、Web上でいろいろなことが完結してしまうので、ついついデータのバックアップを忘れがちになってはないだろうか。万が一、自然災害や何かしらの問題が起きて、データが失われてしまうと目も当てられない。

レンタルサーバーの業者によっては、自動バックアップの機能をサービスとして提供している場合もあるが別料金にしている場合も少なくない。また、必要なデータのみ、自力でバックアップした方が早いという場合も多く、とにかく、自分の手元に定期的にバックアップを取っておけば、それが最も安心だ。

今回は、Pythonのプログラムを作って、FTPS経由でWebサーバーにあるデータをダウンロードする方法を紹介しよう。

FTPSについて

以前、多くのレンタルサーバーでは、FTPプロトコルを利用して、ファイルをアップロードしたり、ダウンロードしたりしていた。FTP(File Transfer Protocol)というのは、ファイルを転送することが目的の通信規約であり、専用のFTPクライアントを利用することで、手軽にWebサーバーにファイルを転送できる。

しかし、FTPはパスワードなど認証情報を暗号化せずに転送するため安全ではないと言われている。そこで、最近では、より安全に通信を行うFTPSやSFTP、SCPなどの通信プロトコルが推奨されている。なお、FTPSとSFTPは名前が似ているが、FTPSは「FTP over SSL/TLS」の略であり、SFTPは「SSH FTP」の略なので、全く異なる通信方式だ。自分の利用しているサーバーがどちらの方式を利用しているのか確認しておこう。

簡単なプログラム

それでは、最初にサーバーにFTPS経由で接続して、ファイルの一覧を取得するプログラムを作ってみよう。なお、今回は、多くのレンタルサーバーで利用されている、FTPS(FTP over SSL/TLS)を利用して、ファイルの一覧をダウンロードするプログラムを作ってみまよう。

以下のプログラムは、指定したFTPSサーバーに接続し、指定のディレクトリにあるCSVファイルを一括でダウンロードするというものだ。

まず、このプログラムを「ftps_downloader.py」という名前で保存しよう。そして、プログラムの冒頭にあるFTPSの設定を書き換える。

# 最初に以下のFTP情報を書き換えてください --- (*1)
FTP_HOST     = 'ftp.*****.jp'
FTP_ACCOUNT  = 'xxxxxx'
FTP_PASSWORD = 'xxxxxx'
FTP_DIR      = './' # ダウンロードするディレクトリの指定

# FTPのライブラリを取り込む --- (*2)
import ftplib

# サーバーに接続 --- (*3)
ftp = ftplib.FTP_TLS(FTP_HOST) # ホストに接続
ftp.set_pasv("true") # PASVモードにする
ftp.login(FTP_ACCOUNT, FTP_PASSWORD) # ログインする
ftp.prot_p() # セキュアコネクションに変更
ftp.cwd(FTP_DIR) # 指定したディレクトリ変更

# ディレクトリ内にあるCSVファイルの一覧を取得 --- (*4)
files = ftp.nlst('*.csv')

# 上記ファイルを連続でダウンロード --- (*5)
for fname in files:
    print('Downloading: ', fname)
    with open(fname, "wb") as f:
        ftp.retrbinary('RETR ' + fname, f.write)
    print('ok')

ftp.quit()

上記のプログラムを実行するには、コマンドライン上で、以下のコマンドを実行する。その際、あらかじめ適当なCSVファイルをサーバーにアップロードしておいてから実行すると、正しく動作するのか確認できる。

python ftps_downloader.py

実行して、正しくFTPSで接続できると、サーバーの指定したディレクトリにあるCSVファイルをダウンロードする。

  • 実行したところ

    実行したところ

プログラムの流れを確認してみよう。プログラムの冒頭(*1)の部分では、FTPの設定を記述している。このようにプログラムの冒頭に設定をまとめておけば変更が容易だ。

(*2)の部分では、FTPのライブラリ「ftplib」を取り込む。このプログラムでは、ftplibの機能を大々的に利用してFTPS通信を行っている。

(*3)の部分でFTPSサーバーに接続する。ホストに接続し、PASVモードを有効にして、アカウントとパスワードでログインを行う。ログインしたら、セキュアコネクションに変更する。そして、cwdメソッドで任意のディレクトリに変更する。

(*4)の部分では、nlstメソッドでファイルの一覧を取得する。もし、テキストファイルを列挙したい場合には、この引数を'*.txt'のように書き換えれば動作を変更する。そして、(*5)の部分では、取得した一覧を元に、ファイルを一つずつダウンロードしていく。

エラーが出る場合のヒント

筆者は、レンタルサーバーのLolipop!およびHetemlで実行できることを確認している。しかし、ご利用のFTPSサーバーの設定によっては、接続方法を変更しないといけないかもしれない。

PythonのFTPライブラリ「ftplib」のマニュアルがこちらにあるので、修正する際の参考にすると良いだろう。また、表示されたエラーメッセージと「ftplib」を組み合わせて検索すると、解決のヒントが得られるかもしれない。

FTP情報をプログラムにべた書きしても大丈夫?

ところで、このプログラムでは、冒頭(*1)の部分で、FTPの設定情報のような重要な情報をプログラムの中にべた書きしている。これが良いかどうかは賛否の分かれるところだ。

暗号化されたデータベースの中にFTP設定情報を仕込んでおいて、データベースから読み込むとか、設定ファイルを暗号化しておいて、実行時にパスワードを入れることでプログラムを実行できるようにするなど工夫できる。

とは言え、そもそもプログラム自体を、安全な場所(サーバー管理者の手元や、暗号化されて普段は見れない暗号化ディスクなど)に保管するなら、FTP情報をべた書きしてあるのは、それほど問題にならないかもしれない。

同じファイルをダウンロードしないように工夫しよう

それでは、上記のプログラムをちょっと改良して、同じファイルを無駄にダウンロードしないようにしてみよう。例えば、毎月のレポートなど別々の名前で出力されている場合に、既にダウンロード済みのデータを繰り返しダウンロードしないようにするための仕組みだ。

以下のプログラムを「ftps_download1time.py」という名前で保存しよう。そして、同じようにプログラムの冒頭にあるFTPSの設定を書き換えよう。

# 最初に以下のFTP情報を書き換えてください
FTP_HOST     = 'ftp.*****.jp'
FTP_ACCOUNT  = 'xxxxxx'
FTP_PASSWORD = 'xxxxxx'
FTP_DIR      = './' # ダウンロードするディレクトリの指定

# FTPのライブラリを取り込む
import ftplib

# 既にダウンロード済みのファイルを確認 --- (*1)
import glob
localfiles = {}
for f in glob.glob("*.csv"):
    localfiles[f] = True

# サーバーに接続
ftp = ftplib.FTP_TLS(FTP_HOST)
ftp.set_pasv("true")
ftp.login(FTP_ACCOUNT, FTP_PASSWORD)
ftp.prot_p() # セキュアコネクションに変更
ftp.cwd(FTP_DIR)

# ディレクトリ内にあるCSVファイルの一覧を取得
files = ftp.nlst('*.csv')

# 上記ファイルを連続でダウンロード
for fname in files:
    # ダウンロード済みファイルをスキップ --- (*2)
    if fname in localfiles:
        print('Skip:', fname)
        continue
    print('Downloading: ', fname)
    with open(fname, "wb") as f:
        ftp.retrbinary('RETR ' + fname, f.write)
    print('ok')

ftp.quit()

プログラムを実行するには、コマンドライン上で「python ftps_download1time.py」とコマンドを実行する。前回のプログラムから変更したのは二点だ。

(*1)の部分では、ローカルにある既にダウンロード済みのファイルの一覧を取得する。そして、(*2)の部分で、ダウンロード済みのファイルのダウンロードをスキップするようにした。

まとめ

以上、今回は、FTPSを利用してWebサイトのバックアップを自動で行う方法を紹介した。Windowsのタスクスケジューラ、macOSやLinuxのcronのなどを利用して、今回のプログラムを自動で定期的に実行するようにしておけば、バックアップの取り忘れを防ぐことができる。

毎回、手動でクライアントアプリを起動して、特定のファイルを選んでダウンロードするという面倒な作業を自動化できる。本記事を参考にして、Webのバックアップ作業を自動化すると良いだろう。

自由型プログラマー。くじらはんどにて、プログラミングの楽しさを伝える活動をしている。代表作に、日本語プログラミング言語「なでしこ」 、テキスト音楽「サクラ」など。2001年オンラインソフト大賞入賞、2004年度未踏ユース スーパークリエータ認定、2010年 OSS貢献者章受賞。技術書も多く執筆している。