Python|フォルダ内のファイルを一覧をhtml出力

前回の記事「Python|できるだけ短いコードでファイル一覧を取得する。」の続き

  • 特定ファルダ内のサブフォルダとファイルをHtmlで見やすく出力
  • 単一のHtmlになるので、webサーバーなしでも見れる。
  • pythonを、実業務でちょっと活用できる。
  • pythonは勿論のこと、Html cssの最低限の知識のある方向け、(JavaScriptは使っていない。)

※本記事はwindows10でのみ動作確認済み。windows11はおそらく動きますが、Macはフォルダの区切り文字が違うので多分動きません。

目的

深い階層でフォルダ分けされた大量のPDFファイルは、どこの会社にも少なからずあるのではないだろうか。階層が深くて探すのが面倒、共有フォルダにあるので、いつか誰か消してしまうかもしれない。これをもしwebでブラウザで見ることができれば、見やすいし誤って消す心配もない。この記事ではpythonを使って、サブフォルダを含む特定のフォルダ内のファイルを、一覧にしてHtml出力してみます。

まずは完成品

以下のようにファルダ構成になっています。「files」のフォルダの中にフォルダ整理されたpdfが格納されています。ちなみにファイルは国土交通省のHPで公開されているものです。

index.html  ←----------┐
│  SCRIPT.py  ------これを実行すると「index.html」が生成される。
│
├─cssstyle.css
│
└─files
    └─港湾施設の点検診断
        │  港湾の施設の点検診断ガイドライン【第1部総論】.pdf
        │  港湾の施設の点検診断ガイドライン【第2部実施要領】.pdf
        │  港湾の施設の点検診断ガイドライン(令和3年3月一部変更)新旧表.pdf
        │
        ├─令和2年3月の主な追加内容
        │      点検診断の効率化に向けた工夫事例集(案).pdf
        │
        └─令和3年3月の主な追加内容
                港湾の施設の新しい点検技術カタログ(案).pdfCode language: CSS (css)

スクリプトを実行すると、「index.html」が作成(または更新)され、内容は以下のようににファイル一覧になっています。

実際に作成したスクリプトはこちら

import os
from glob import glob
from tokenize import blank_re
# ===================================================================================
# ファイル一覧Html作成スクリプト
# ===================================================================================
print('=====================Script Start======================')
# ===================================================================================
# 1.ヘッダー、フッターの作成
# ===================================================================================
TargetDirectry = "./files"
header = (r''' 
    <!doctype html>
    <html>
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title>タイトル記入</title>
            <link rel="stylesheet" href="css/style.css">
        </head>
        <body>
            <div class="wrapper">
                <main>
                    <h1>見出し記入</h1>
''')
footer = (r'''
                </main>
            </div>
        </body>
    </html>
''')
# ========================================================================
# 2.ファイル一覧の取得(files生成)
# ========================================================================
Directories = [p for p in glob( TargetDirectry + '/**/',recursive=True)] 
files = []
for Directory in Directories:
    temp = [p for p in glob(Directory + "**") if os.path.isfile(p)]
    files.extend(temp)
# ==================================================================================
# 3.リストの作成
# ==================================================================================
FList = []
for file in files:
    temp = []
    firstLoop = True
    for F in file.split('\\'):
        if firstLoop:
            firstLoop = False
        else:
            temp.append(F)
    temp.insert(len(temp)-1,file)
    FList.append(temp)
# =====================================================================
# 4.HTML出力
# =====================================================================
html = header
prev = [""]
for count1, F in enumerate(FList):
    for count2, f in enumerate(F):
        if count2 == len(F)-2:
            html += "    " * ( 5 + count2 )
            html += "<div class = MyHeading" + str(count2) + " ><a href = " + f + ">"
        elif count2 == len(F)-1:
            html += f + "</a></div>"
            html += "\n"
        elif len(prev) >= count2 and prev[count2] == f :
            continue
        else:
            html += "    " * ( 6 + count2 )
            html += "<div class = MyHeading" + str(count2) + " ><big><b>" + f + "</big></b></div>"
            html += "\n"
    prev = F
    
html += footer
index = open('./index.html', 'w', encoding='utf-8')
index.write(html)
index.close
print('=====================Script end========================')
  1. ヘッダー、フッターの作成
  2. ファイル一覧の取得
  3. リストの作成
  4. Htmlの作成

と四段階のステップになっています。ファイル一覧の取得後に別途リストを作成しているところがポイント。順を追って解説します。

1.ヘッダー、フッターの作成

まずHtmlを作成するのに最低限必要なヘッダーとフッターを記述する。

「r’’’」と記述すると、Raw文字列ということで、改行やタブを含む文字列を変数に格納することができます。 便利。

# ===================================================================================
# 1.ヘッダー、フッターの作成
# ===================================================================================
#「r'''」RAW文字列
header = (r''' 
    <!doctype html>
    <html>
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title>タイトル記入</title>
            <link rel="stylesheet" href="css/style.css">
        </head>
        <body>
            <div class="wrapper">
                <main>
                    <h1>見出し記入</h1>
''')
footer = (r'''
                </main>
            </div>
        </body>
    </html>
''')

2.ファイル一覧を取得

ここは、前回記事「Python|できるだけ短いコードでファイル一覧を取得する。」と同じ。

# ========================================================================
# 2.ファイル一覧の取得(files生成)
# ========================================================================
# ==================================================================================
# 指定ディレクトリ(上記の「TargetDirectry」)配下のファイル一覧をフルパスで取得する。
# 普通に取得するとフルパスの名前順になって扱いずらいので、一度ディレクトリ一覧を作成してから、
# ファイル一覧を取得する二段階構え。
# ==================================================================================
# ==================================================================================
# 2-1.ディレクトリ一覧取得
# ==================================================================================
Directories = [p for p in glob( TargetDirectry + '/**/',recursive=True)] 
# 開発時のデバッグ用
# print('===================Directories======================')
# for Directory in Directories:
#     print(Directory)
# print('====================================================')
# ==================================================================================
# 2-2.ファイル一覧取得
# ==================================================================================
files = []
for Directory in Directories:
    temp = [p for p in glob(Directory + "**") if os.path.isfile(p)]
    files.extend(temp)
# 開発時のデバッグ用
# print('===================files============================')
# for file in files:
#     print(file)
# print('====================================================')

3.リストの作成

ファイルの一覧を取得したら、次にhtmlを生成しやすいようにリストを作成します。リストを作成した後に作るhtmlは以下のような構造にしたい。

<MyHeading0>親フォルダ名</MyHeading0>
    <MyHeading1>子フォルダ名</MyHeading1>
     <MyHeading2><a href = ファイルフルパス>ファイル名</MyHeading2>

「親フォルダ名」 → 「子フォルダ名」 → 「ファイルフルパス」 → 「ファイル名」

リストはこの順番になるように作成していく。

# ==================================================================================
# 3.リストの作成
# ==================================================================================
# ==================================================================================
# Htmlを生成するための下準備。
# FListという変数名で下記のようなリストを作成する。
# 
# リストの例 
# ['港湾施設の点検診断', './files\\港湾施設の点検診断\\港湾の施設の点検診断ガイドライン【第1部総論】.pdf', '港湾の施設の点検診断ガイドライン【第1部総論】.pdf']
# ['港湾施設の点検診断', './files\\港湾施設の点検診断\\港湾の施設の点検診断ガイドライン【第2部実施要領】.pdf', '港湾の施設の点検診断ガイドライン【第2部実施要領】.pdf']
# ['港湾施設の点検診断', './files\\港湾施設の点検診断\\港湾の施設の点検診断ガイドライン(令和3年3月一部変更)新旧表.pdf', '港湾の施設の点検診断ガイドライン(令和3年3月一部変更)新旧表.pdf']
# ['港湾施設の点検診断', '令和2年3月の主な追加内容', './files\\港湾施設の点検診断\\令和2年3月の主な追加内容\\点検診断の効率化に向けた工夫事例集(案).pdf', '点検診断の効率化に向けた工夫事例集(案).pdf']
# ['港湾施設の点検診断', '令和3年3月の主な追加内容', './files\\港湾施設の点検診断\\令和3年3月の主な追加内容\\港湾の施設の新しい点検技術カタログ(案).pdf', '港湾の施設の新しい点検技術カタログ(案).pdf']
#                       ・
#                       ・
#                       ・
# ['一階層目のディレクトリ','二階層目のディレクトリ',・・・・,'ファイルパス','ファイル名']
# ==================================================================================
# ==================================================================================
# 3-1.空リストの定義
# ==================================================================================
FList = []
# ==================================================================================
# 3-2.リスト追記
# ==================================================================================
# ==================================================================================
# temp というリストを作成して、FListにappendすることで二次元リストにする。
# file:フルパス
# fileを分割してFListへ順番に格納していく。
# ==================================================================================
for file in files:
    # temp の初期化
    temp = []
    # pythonには「ループの最初だけ処理を変える」という文法がないため、FirstLoopという変数も設けて対応
    firstLoop = True
    # filesをパス区切文字で分割 Windows意外のOSでは適宜調整
    for F in file.split('\\'):
        if firstLoop: # 一回目のループ、何もしない。
            firstLoop = False
        else:  # 二回目以降のループ、末尾へ追記
            temp.append(F)
    # tempの最後から二番目にフルパスを挿入
    temp.insert(len(temp)-1,file)
    # tempをFlistへ書き足すことで二重リストを作成
    FList.append(temp)
# 開発時のデバッグ用
# print('===================FList============================')
# for F in FList:
#     print(F)
# print('====================================================')

4.html出力

html出力の部分ではforとifですこし複雑な処理をしています。

「3.リストの作成」で作成したリストは二次元リストになっていますが、このリストに二回forを使って、一要素ずつifで検証する。

ループの処理は上のフローの通り、手書きですいません。

別途cssを用意しますが、「MyHeading*」というタグがこのスクリプトの重要な部分となってきます。

# =====================================================================
# 4.HTML出力
# =====================================================================
# =====================================================================
# 「html」という変数を作成して、そこへファイル一覧をHTMLにして追記する。
# 「enumerate」というちょっとニッチな文法を使っている。
#   ‘‘‘for count1, F in enumerate(FList):‘‘‘
# これでcount1が「0,1,2,3,・・・」とリストのインデックスになる。
# =====================================================================
# =====================================================================
# 4-1.htmlの作成とheaderの追記
# =====================================================================
html = header
# =====================================================================
# 4-2.ファイル一覧の追記
# =====================================================================
prev = [""]
for count1, F in enumerate(FList):
    for count2, f in enumerate(F):
        if count2 == len(F)-2:  #最終から2番目
            html += "    " * ( 5 + count2 )
            html += "<div class = MyHeading" + str(count2) + " ><a href = " + f + ">"
        elif count2 == len(F)-1: #最終
            html += f + "</a></div>"
            html += "\n"
        elif len(prev) >= count2 and prev[count2] == f :
            continue
        else:
            html += "    " * ( 6 + count2 )
            html += "<div class = MyHeading" + str(count2) + " ><big><b>" + f + "</big></b></div>"
            html += "\n"
    prev = F
    
# =====================================================================
# 4-3.htmlの作成とheaderの追記
# =====================================================================
html += footer
# 開発時のデバッグ用
# print('===================HTML============================')    
# print(html)
# print('====================================================')
index = open('./index.html', 'w', encoding='utf-8')
index.write(html)
index.close

css

用意するcssは以下の通りです。

「MyHeading*」以外はお好みでOK

@charset "UTF-8";
/* お好みのcss */
html {
	font-family: sans-serif;
}
body {
	margin: 0 0 0 0;
	background-color: #eeece9;
}
.wrapper {
	margin: 0 auto 0 auto;
	max-width: 90%;
}
a:link {
	color: #d25833;
}
a:visited {
	color: #d25833;
}
a:hover {
	color: #e3937a;
}
a:active {
	color: #ff6a3b;
}
/*  - 書き加え */
.MyHeading0 {
	display: block;
	margin-left: 2%;
	font-size: 130%;
  }
  
.MyHeading1 {
	display: block;
	margin-left: 4%;
	font-size: 130%;
}
  
.MyHeading2 {
	display: block;
	margin-left: 6%;
	font-size: 130%;
}
  
.MyHeading3 {
	display: block;
	margin-left: 8%;
	font-size: 130%;
}
  
.MyHeading4 {
	display: block;
	margin-left: 10%;
	font-size: 130%;
}
  
.MyHeading5 {
	display: block;
	margin-left: 12%;
	font-size: 130%;
}
  
.MyHeading6 {
	display: block;
	margin-left: 14%;
	font-size: 130%;
}
.MyHeading7 {
	display: block;
	margin-left: 16%;
	font-size: 130%;
}
.MyHeading8 {
	display: block;
	margin-left: 18%;
	font-size: 130%;
}
.MyHeading9 {
	display: block;
	margin-left: 20%;
	font-size: 130%;
}

コメント

タイトルとURLをコピーしました