個人サイト制作:サイトマップへ戻る

Webサイト制作の効率を上げるPython

個人でサイトを作っていくとき、とにかく「金と時間をかけない」のがコツだと思ってます。
もうちょっとやりたいなぁー…と思ったところで、敢えて手を止める感じでしょうか。
そうしないと長続きしないし、Web制作みたいな奥が深い作業を「根性」だけで続けていても、辛いだけです。

フェードアウト効果の草花写真

さて、ここではサイト制作をラクにしてくれるPythonというプログラムについて書いていきます。
プログラミングも昔はハマりましたねー
ここに置いていくのは私が学生時代に作っていたノートの写しですから、あるいは間違いがあったり、その人の環境次第では動作しないケースもあるでしょう。
可能な限りミスがないよう修正していますが、もし動作しなかったらご容赦ください。

参考サイト: Python公式ドキュメント

このpythonページの要約

このページに関する注意事項

当Webサイト作成者は、例示を目的としてマークアップ及びプログラミング例を提供しており、明示または黙示にかかわらず、いかなる責任も負わないものとします。
このページは、説明されているマークアップ及びプログラミング言語、手順を作成およびデバッグするために使用される各種ツールに読者が精通していることを前提にしています。
このページは、特定の機能を説明するのに役立つ可能性がありますが、当Webサイト作成者がこれらの例を変更した上で、特定の要件を満たすために追加の機能を提供したり、システムを構築したりすることはできません。
加えて、この例の手順に従う場合は、読者の各種ファイルを事前にバックアップすることを推奨いたします。

Pythonについて

参考サイト: python.org

Pythonは非常に多用途なプログラミング言語で、次のようなカテゴリに分類されると思われます。
  1. 高水準プログラミング言語:人間が理解しやすい形で書かれた言語です。
  2. 汎用プログラミング言語:特定の用途に限定されず、幅広い分野で使用されます。
  3. インタープリタ言語:コードが逐次実行されるため、コンパイルが不要です。
  4. オブジェクト指向プログラミング言語:オブジェクトとクラスを使用してプログラムを構築します。

また、Pythonはサーバーサイドスクリプトとしても広く使用されています。
ウェブ開発だと、いろんなフレームワークを使ったものが人気ですよね。
Djangoは高機能なフルスタックフレームワークで、ウェブアプリケーションの開発に使えます。
管理画面の自動生成、認証機能、ORM(オブジェクトリレーショナルマッピング)などが標準で備わっていますね。
軽量なマイクロフレームワークとしてはFlaskとか。
FastAPIなんかは高速なAPIフレームワークとして有名で、高性能なAPIの開発ができます。
こういったいろんなフレームワークを使うことで、ウェブアプリケーションやAPIの開発が効率的に行えるってことです。

フェードアウト効果の草花写真

PythonはGuido van Rossum(グイド・ヴァンロッサム)によって作られました。
身近な話題を選んでpythonを語るなら、グイド・ヴァンロッサムがGoogleやDropboxに入社して働いていたのは有名な話です。
Google・Dropboxともにpythonを頻用しており、彼は大いに活躍したそうですよ?
InstagramはバックエンドシステムにDjangoというPythonで実装されたWebフレームワークを使っていることもよく知られていることです。

最近だと機械学習分野でpythonの話はよく聞きますが、私は上述している、主にWeb開発のフレームワーク(Django、Flaskなど)を利用したWebアプリケーションの開発という方向でpythonにはお世話になってきましたね。
まだこのサイトでDjangoやFlaskなどを導入するのは時期早々だと思いますが、いずれはそれらを込みとして作っていく方向性もあるでしょう。
このように、言語の特性というよりも、私の趣味により近いのがpythonであったということなんです。
グイド・ヴァンロッサム本人のブログである The History of Python がBloggerで作られているのもおもしろいですね。
独自ドメインでもない、プレーンなブログそのままなんです。

Pythonライブラリは、特定の機能やタスクを簡単に実行できるようにするための、コードの集まりみたいな感じでしょうか。
これらのライブラリは、Pythonプログラムにインポートして使えます。
多くのPythonライブラリは有志の開発者やコミュニティによって作成されていて、開発者は自分で一からコードを書く必要がなく、既存のライブラリを利用して効率的に開発を進めることができるってことですね。
例えば、Pillowは画像処理のためのライブラリであり、NumPyは数値計算のためのライブラリです。
これらのライブラリを使うことで、複雑な処理を簡単に実行できるようになります。

PythonによるHTTPサーバー構築

デプロイする前にサーバーを立てつつWebページを確認することもあります。
ローカル環境にHTTPサーバーを構築する方法はいろいろありますが、Pythonでやるのが一番ラクだと感じますね。
Web制作をやってる人は既にpythonをインストールしていろんな環境設定をしていることもあります。
もしやっているなら、ここから下のインストールとダウンロードの各項目は飛ばしてよろしいかと思います。

  1. Python公式サイトから最新パッケージをダウンロード。
  2. Add python.exe to Pathにチェックを入れつつInstall Nowをクリック。このチェックを忘れがちなので注意しましょう。
  3. cmdを起動してpythonと入力し、バージョン表示されるかチェックします。
  4. そのままhtmlファイルを保存しているディレクトリにcdします。
  5. python -m http.server 8000 とコマンドすればサーバーが起動するはず。Serving HTTP on :: port 8000(http://[::]:8000/)...と表示されればサーバーが起動している合図です。
  6. ブラウザのアドレスバーにhttp://localhost:8000と入力すると自分のサイトが出ます。

これで、ローカル環境でありつつ、Webサーバーに上げた状態をチェックすることができます。

ローカルサーバー起動のbatファイルを書く

win+r→cmd でもいいんだけどね。
私はめんどくさくてbatファイルを作っちゃってます。
コマンドプロンプト起動からローカルサーバー起動、そのままブラウザ起動までフルオートでやってくれるやつ。
個人の環境次第でこういうのも良いと思います。


@echo off
cd C:\Users\アレコレ\google cloud\fein-sites-dev1\www
start python -m http.server 8000
timeout /t 5
start "" "http://localhost:8000"
pause
        

私はこんな感じです。
でもこの手のbatファイルがあんまり多すぎても自分が混乱しちゃいますけどね。

pythonでExcelの表をhtmlに変換する

フェードアウト効果の草花写真

こういうところに来る人なら分かると思うけど、変換元のExcelは綺麗にしておかないとダメですよ。
変にセル結合などをせず、体裁を整えておきます。
手間を除くためにプログラミングで処理をするのですから、tableタグになってから手書きでいろいろ触っていると意味がないのでね。

Excelの表を手作業でチクチクとtableタグに置き換えるなんて…想像もしたくないです。
大変な作業になりますし、ミスも出ると思うんですよね。
あまり機会は多くないけど、ミスを防ぐという意味でも、プログラムで一括処理しちゃってます。

Excelの読み書きに必要なPythonライブラリをインストール

次の2つをインストールします。


pip install pandas openpyxl
        

上記2つのライブラリがインストールできたら、次のようにスクリプトを書きます。

Excelの表をhtmlにするtable.py


# pandasライブラリをインポート
import pandas as pd

# Excelファイルのパスを指定
excel_file = r'C:\Users\アレコレ\google cloud\web tools\office\表好きのための表.xlsx'

# Excelファイルを読み込み、データフレームに変換
df = pd.read_excel(excel_file)

# データフレームをHTMLテーブルに変換
html_table = df.to_html()

# HTMLテーブルの出力先ファイルを指定
output_file = r'C:\Users\アレコレ\google cloud\web tools\office\table.html'

# 指定したファイルにHTMLテーブルを書き込む
with open(output_file, 'w', encoding='utf-8') as file:
    file.write(html_table)

# HTMLテーブルの作成完了メッセージを出力
print(f"HTMLテーブルが作成されました: {output_file}")
    

このスクリプトに関しては構造も複雑じゃないから、1行ずつ説明しないけど、丁寧にコメントアウトを付けさせていただきました。
ライブラリの機能を使って変換しているだけです。

レスポンシブデザインと表

スマホでもまともに表示させるために、表の列に関しては多くても3列までとしていますね。
人によってやり方は違うでしょうけど、パソコンを使っていても横に長い表は扱いにくいです。
あと、過度に縦に伸びないように工夫もしています。

表というのは視覚的に構造が分かりやすいから、何かと用いられることが多いレイアウトです。
でも、モバイル表示という観点から言うなら、あまり望ましくない、ないしはできれば避けたいと考えていますね。
単純な2列の表であっても文節が折り返されて読みにくいことがある。

PDFを操作するためのPythonライブラリをインストール

まずは手軽なPDFファイルの操作からいきますか。
必要なのは次の4つです。

これらをまとめてインストールしちゃいます。
次のようにコマンドプロンプトへ入力します。


pip install pymupdf pikepdf pdf2image pytesseract

このコマンドを実行すると、上記4つのPythonパッケージがインストールされます。
これらのパッケージを使うことで、PDFや画像ファイルの操作やテキスト抽出が簡単に行えるようになります。

Popplerのバイナリをインストール

これもコマンドプロンプトでやれないことはないけど、一発ではないからね。
追加で説明書きたいこともあるから、GUIベースで行きましょう。

簡単な事前説明

フェードアウト効果の草花写真

Popplerのバイナリは、PDFファイルを操作するためのコマンドラインツールです。
Poppler自体は、PDFのレンダリングライブラリであり、xpdf-3.0コードベースに基づいています。
バイナリとは、ソースコードをコンパイルして生成された実行可能ファイルのことですね。
Popplerのバイナリを使用すると、PDFの変換、結合、抽出などの操作をコマンドラインから実行できます。
例えば、Windows環境では、コマンドプロンプトを開いて「pdfinfo」や「pdftotext」などのコマンドを実行することで、PDFの情報を取得したり、テキストを抽出したりすることができます。
Popplerのバイナリは公式サイトから直接ダウンロードすることはできませんが、GitHubなどのリポジトリから入手することができます。

PopplerはPythonと密接に関連しています。 「python-poppler」というライブラリがあり、これはPopplerのC++ライブラリであるpoppler-cppのPythonバインディングです。─ バインディングというのは「つなぎ役」と捉えてもらえれば良いですね ─
これを使ってPythonからPDFドキュメントを読み込み、レンダリングし、または修正することができます。─ レンダリングというのは「表示」と考えてください ─

例えば、上でお話ししたpdf2imageというPythonモジュールは、PDFを画像に変換する際にPopplerを使用します。
このモジュールを使うことで、PDFページを画像として抽出することが可能となるわけです。

参考サイト:

では、ダウンロードとインストールへ進みます。
ご案内するのは2024年10月現在の確認状況ですから、時間が経っているようであれば都度読み替えてください。

1.Popplerのバイナリをダウンロード

  1. GitHubのpoppler-windowsリポジトリにアクセスします。
  2. ページ内にDownloadというエリアがあり、そこにYou can download the latest build from releases.という文章があります。ここの「Releases」はリンクになっているので、そこをクリックします。
  3. 最新のZIPファイルをダウンロードします。おそらくRelease 24.07.0-0と書いてあるでしょう。その右側に「Latest」とアイコンがあると思います。zipはその下です。

2.ZIPファイルを解凍

  1. ダウンロードしたZIPファイルを右クリックし、「すべて展開」を選択します。
  2. この時点で解凍先のフォルダを指定しても良いですし、後から解凍したフォルダを移動しても良いですが、Cドライブの配下にしておきましょう。

3.環境変数に追加

  1. スタートメニューを開き、「環境変数」と入力し、「システム環境変数の編集」を選択。
  2. 「システムのプロパティ」ウィンドウが開いたら、「環境変数」ボタンをクリック。
  3. 「システム環境変数」セクションで、「Path」を選択し、「編集」ボタンをクリック。そのPathにはC:\Users\ユーザー名\AppData\Local\Programs\Python…と書いてあるはずです。
  4. 「新規」ボタンをクリックし、先ほど解凍したpoppler内部にあるbinディレクトリのパスを入力。例えばC:\Users\ユーザー名\poppler-24.07.0\Library\binといった形で入力してください。
  5. 「OK」ボタンをクリックしてすべてのウィンドウを閉じていきます。

4.動作確認

  1. すでにコマンドプロンプトが開いているなら、再起動します。
  2. 次のコマンドを入力して、popplerが正しくインストールされているか確認します。

pdfinfo -v

コマンドプロンプトを再起動しないとpdfinfo -vが正常に動作しない理由は、環境変数の変更が現在のセッションに反映されないためです。
環境変数を設定または変更した場合、その変更は新しいコマンドプロンプトセッションにのみ適用されます。
既存のセッションでは変更前の環境変数が引き続き使用されるため、再起動が必要となります。
ちょっとめんどうですが、初期の環境設定ですから。
コマンドプロンプトを再起動すれば新しい環境変数の設定が反映され、pdfinfo -vが正常に動作するようになります。

正常にインストールされていれば、popplerのバージョン情報が表示されます。
これでpopplerがインストールされ、環境変数に追加されたことになります。

環境変数

フェードアウト効果の草花写真

環境変数とは、オペレーティングシステムやアプリケーションが動作する際に使用する設定情報を格納するための変数です。
これらの変数は、システム全体や特定のユーザーの設定を定義するために使用されます。
例えば、環境変数には次のようなものがありますね。

環境変数は、システムの動作やアプリケーションの設定に大きな影響を与えるため、丁寧に作業することが必要です。
Pythonでの環境変数は、プログラムの実行時に外部から設定される変数で、プログラムの動作に影響を与える設定情報を提供します。

ここで、上記でPopplerをインストールした後に環境変数に追加する手順を踏んでいるのは、システムや他のアプリケーションがPopplerの実行ファイルやライブラリにアクセスできるようにするためです。
具体的な理由としては、次のようなものがあります。

  1. パスの設定:Popplerの実行ファイル(例えば、pdftotextやpdfinfoなど)をコマンドラインから直接実行できるようにするために、PATH環境変数にPopplerのインストールディレクトリを追加する必要があります。これでどのディレクトリからでもPopplerのコマンドを実行できるようになります。
  2. ライブラリのパス:Popplerのライブラリを使用するアプリケーションが正しく動作するために、例えばLinuxの場合ならLD_LIBRARY_PATHの環境変数にPopplerのライブラリパスを追加することがあります。これでアプリケーションが必要なライブラリを見つけてロードできるようになります。
  3. 設定ファイルのパス:一部のアプリケーションでは、Popplerの設定ファイルやリソースファイルのパスを環境変数で指定することがあります。これでカスタム設定やリソースを使用することができます。

Windowsの場合、LD_LIBRARY_PATHのような環境変数は使用しません。その代わりに、PATH環境変数にPopplerの実行ファイルやライブラリのパスを追加します。
これでシステムやアプリケーションがPopplerの実行ファイルやライブラリにアクセスできるようになります。
上記手順は、Popplerをインストールしたディレクトリを確認して環境変数の設定を行うという作業なんです。

Tesseractのインストール

PythonのTesseractは、正式にはpytesseractと呼ばれます。
このライブラリはPythonで使用できる光学文字認識(OCR)ツールです。
GoogleのTesseract-OCRエンジンのラッパーであり、画像に埋め込まれたテキストを認識して「読み取る」ことができます。

ラッパーという表現について、少し詳しくお話ししようかな…
ここで言う「GoogleのTesseract-OCRエンジンのラッパー」というのは、Tesseract-OCRエンジンをPythonなどのプログラミング言語から簡単に利用できるようにするためのインターフェースを提供するものなんだという意味です。
Tesseract-OCRエンジンの機能を呼び出すためのコードを簡略化し、使いやすくするためのPythonライブラリが「pytesseract」、すなわち今からインストールしようとしているTesseractとなります。
Tesseract-OCRエンジン自体は、画像からテキストを抽出するツールなのですが、直接使うにはコマンドライン操作や複雑な設定が必要になることがあります。
pytesseractは、これらの操作をPythonコード内で簡単に行えるようにするためのラッパーということです。

では、ダウンロードとインストールへ進みます。
ご案内するのは2024年10月現在の確認状況ですから、時間が経っているようであれば都度読み替えてください。

1.Tesseractのインストール

  1. Tesseractの公式リリースページにアクセスします。
  2. Windows用のインストーラーをダウンロードします。おそらく「tesseract-ocr-w64-setup-5.4.0.20240606.exe (64 bit)」と書いてあるはず。
  3. ダウンロードしたインストーラーを実行し、指示に従ってインストールします。

2.環境変数に追加

フェードアウト効果の草花写真

ここは、上述の「Popplerのバイナリをインストール」した時と同じです。でもササっと手順を書いておきます。

  1. スタートメニューを開き、「環境変数」と入力し、「システム環境変数の編集」を選択。
  2. 「システムのプロパティ」ウィンドウが開いたら、「環境変数」ボタンをクリック。
  3. 「システム環境変数」セクションで、「Path」を選択し、「編集」ボタンをクリック。
  4. 「新規」ボタンをクリックし、`Tesseract`のインストールディレクトリのパスを入力。おそらく多くの人がC:\Program Files\Tesseract-OCRだと思います。
  5. 「OK」ボタンをクリックしてすべてのウィンドウを閉じる。

3.動作確認

  1. コマンドプロンプトを開きますが、すでに開いているなら、再起動をお忘れなく。
  2. 次のコマンドを入力して、Tesseract が正しくインストールされているか確認します。

tesseract -v

正常にインストールされていれば、Tesseractのバージョン情報が表示されます。
これでTesseractがインストールされ、環境変数に追加されたことになります。

pythonでPDFをまとめて圧縮する

ここまでは環境が整っている人が多いかな?
そろそろ具体的なpythonスクリプトに話題を移していきます。
あんまり深入りすると大変ですからね。
あくまでも当初の目的である「Webサイト制作でラクをする」という側面を大切にしていきましょう。

まず、次のコードを見てみましょう。
ファイル名は「pdf.py」という名で保存されているものです。

PDFをまとめて圧縮するpdf.py


import pikepdf
import os

def compress_pdf(input_path, output_path):
    try:
        with pikepdf.open(input_path) as pdf:
            pdf.save(output_path)
    except Exception as e:
        print(f"Error compressing {input_path}: {e}")

def compress_pdfs_in_directory(input_dir, output_dir):
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    for filename in os.listdir(input_dir):
        if filename.endswith(".pdf"):
            input_path = os.path.join(input_dir, filename)
            output_path = os.path.join(output_dir, filename)
            compress_pdf(input_path, output_path)

input_directory = r"C:/Users/アレコレ/google cloud/fein-sites-dev1/www/another-eden/fein_report"
output_directory = r"C:/Users/アレコレ/Documents/pdf"

compress_pdfs_in_directory(input_directory, output_directory)

それぞれを簡単に説明していきます。
このコードは指定されたディレクトリ内のPDFファイルを圧縮し、別のディレクトリに保存する一連の処理を行っています。

import pikepdf
PDFファイルを操作するためのライブラリ pikepdf をインポートしています。

import os
ファイルやディレクトリの操作を行うための標準ライブラリ os をインポートしています。

def compress_pdf(input_path, output_path):
ここでは、PDFファイルを圧縮する関数 compress_pdf を定義しています。
この関数は、入力ファイルのパスと出力ファイルのパスを引数に取ります。

try:
ここから、エラーが発生する可能性のある処理となります。

with pikepdf.open(input_path) as pdf:
指定されたパスのPDFファイルを開きます。 with文を使うことで、ファイルを自動的に閉じることができます。

pdf.save(output_path)
開いたPDFファイルを指定された出力パスに保存します。

except Exception as e:
もしエラーが発生した場合、このブロックが実行されます。

print(f"Error compressing {input_path}: {e}")
エラーが発生した場合、そのエラーメッセージを表示します。

def compress_pdfs_in_directory(input_dir, output_dir):
ここでは、ディレクトリ内のすべてのPDFファイルを圧縮する関数 compress_pdfs_in_directory を定義しています。
この関数は、入力ディレクトリと出力ディレクトリを引数に取ります。

if not os.path.exists(output_dir):
出力ディレクトリが存在しない場合をチェックします。

フェードアウト効果の草花写真

os.makedirs(output_dir)
出力ディレクトリが存在しない場合、新しく作成します。

for filename in os.listdir(input_dir):
入力ディレクトリ内のすべてのファイルをループで処理します。

if filename.endswith(".pdf"):
ファイル名が「.pdf」で終わる場合のみ処理を行います。

input_path = os.path.join(input_dir, filename)
入力ファイルのフルパスを作成します。

output_path = os.path.join(output_dir, filename)
出力ファイルのフルパスを作成します。

compress_pdf(input_path, output_path)
先ほど定義した compress_pdf 関数を使って、PDFファイルを圧縮します。

input_directory = r"C:/Users/アレコレ/google cloud/fein-sites-dev1/www/another-eden/fein_report"
圧縮するPDFファイルが保存されているディレクトリのパスを指定します。

output_directory = r"C:/Users/アレコレ/Documents/pdf"
圧縮されたPDFファイルを保存するディレクトリのパスを指定します。

compress_pdfs_in_directory(input_directory, output_directory)
指定されたディレクトリ内のPDFファイルを圧縮する処理を実行します。

このコードのポイント

コードの概要

  1. ライブラリのインポート
    pikepdf:PDFファイルを操作するためのライブラリ。
    os:ファイルやディレクトリの操作を行うための標準ライブラリ。
  2. 関数 compress_pdf
    input_path から PDF ファイルを読み込み、output_path に保存します。
    エラーが発生した場合は、エラーメッセージを表示します。
  3. 関数compress_pdfs_in_directory
    input_dir 内のすべての PDF ファイルを探し、output_dir に圧縮して保存します。
    output_dir が存在しない場合は、新しく作成します。

このコードの対応関係

input_path と output_path
compress_pdf 関数内で使用され、個々のPDFファイルの入力パスと出力パスを指定します。
例:input_path が C:/Users/アレコレ/google cloud/fein-sites-dev1/www/another-eden/fein_report/sample.pdf で、output_path が C:/Users/アレコレ/Documents/pdf/sample.pdf になります。

input_directory と output_directory
compress_pdfs_in_directory 関数内で使用され、ディレクトリ全体の入力パスと出力パスを指定します。
例:input_directory が C:/Users/アレコレ/google cloud/fein-sites-dev1/www/another-eden/fein_report で、output_directory が C:/Users/アレコレ/Documents/pdf になります。

このコードのポイント

フェードアウト効果の草花写真

defで関数を定義する

def はPythonで関数を定義するためのキーワードです。
関数は特定のタスクを実行するためのコードのブロックで、再利用可能な形でまとめられています。
とりあえず def を使って関数を定義する基本的な構文から。


def 関数名(引数1, 引数2, ...):
    # 関数の処理内容
    return 戻り値

例えば…足し算する関数を定義する場合です。


def add_numbers(a, b):
    result = a + b
    return result

この関数 add_numbers は、引数 a と b を受け取り、それらを足し合わせた結果を返します。

ここで紹介しているPDF圧縮プログラムの場合

次のように def を使って関数を定義しています。

このように関数を使うことで、コードを整理し、再利用可能にすることができます。

def はPythonで関数を定義するために必ず使用しなければならないキーワードです。
これはPythonの構文の一部であり、他の言葉に置き換えることはできません。
プログラミング言語にはそれぞれのルールや構文があり、Pythonでは関数を定義するために def を使うと決められています。
例えば、他のプログラミング言語では異なるキーワードを使いますが、それぞれの言語のルールに従う必要があります。
もし def を別の言葉に置き換えようとすると、Pythonはエラーを出してしまいます。
ここで、正しい使い方と間違った使い方の例です。


def my_function():  # 正しい使い方です
    print("Hello, World!")


define my_function():  # これはエラーになります
    print("Hello, World!")

プログラミング言語の構文を守ることで、コードが正しく動作し、他のプログラマーとも共有しやすくなります。

withでリソースを扱う

with はPythonでリソースの管理を簡単にするためのキーワードです。
特にファイルの操作やネットワーク接続など、リソースの解放が必要な処理でよく使われます。
with を使うことで、リソースの解放も自動的に行うことができます。
基本的な使い方を挙げてみます。
with を使ってファイルを開く例です。


with open('example.txt', 'r') as file:
    content = file.read()
    print(content)

このコードは、Pythonでファイルを読み込んでその内容を表示するものです。
実行すると、次のように動作します。

with open('example.txt', 'r') as file: example.txt という名前のファイルを読み取りモード( 'r' )で開きます。
with ステートメントを使うことで、ファイルのクローズを自動的に行います。 content = file.read() ファイルの内容をすべて読み込み、content という変数に格納します。 print(content) 読み込んだファイルの内容をコンソールに表示します。

このコードを実行すると、example.txt ファイルの中身がそのままコンソールに出力されます。
例えば、example.txt に「Hello, World!」と書かれていた場合、実行結果はそのまんま「Hello, World!」となりますね。

with の役割

ここで紹介しているPDF圧縮プログラムの場合

次のように with を使ってPDFファイルを開いています。


with pikepdf.open(input_path) as pdf:
    pdf.save(output_path)

この部分では、input_path からPDFファイルを開き、output_path に保存しています。
with を使うことで、PDFファイルが自動的に閉じられ、リソースが適切に解放されています。

仕上げに、丁寧にコメントアウトが書かれたpythonコードを置いておきましょう。


# pikepdfとosモジュールをインポート
import pikepdf
import os

# PDFファイルを圧縮する関数
def compress_pdf(input_path, output_path):
    try:
        # 入力ファイルを開く
        with pikepdf.open(input_path) as pdf:
            # 出力ファイルとして保存
            pdf.save(output_path)
    except Exception as e:
        # エラーが発生した場合のメッセージを表示
        print(f"{input_path}の圧縮中にエラーが発生しました: {e}")

# ディレクトリ内のすべてのPDFファイルを圧縮する関数
def compress_pdfs_in_directory(input_dir, output_dir):
    # 出力ディレクトリが存在しない場合は作成
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    # 入力ディレクトリ内のすべてのファイルをループ
    for filename in os.listdir(input_dir):
        # PDFファイルのみを対象
        if filename.endswith(".pdf"):
            # 入力ファイルと出力ファイルのパスを作成
            input_path = os.path.join(input_dir, filename)
            output_path = os.path.join(output_dir, filename)
            # PDFファイルを圧縮
            compress_pdf(input_path, output_path)

# 入力ディレクトリのパス
input_directory = r"C:/Users/アレコレ/google cloud/fein-sites-dev1/www/another-eden/fein_report"
# 出力ディレクトリのパス
output_directory = r"C:/Users/アレコレ/Documents/pdf"

# ディレクトリ内のPDFファイルを圧縮
compress_pdfs_in_directory(input_directory, output_directory)
        

pythonでPDFを画像化する

フェードアウト効果の草花写真

これは昔から使用頻度が極めて高かったです。

スクリプトとしては単純ですが、重要なのはその使い道にあると思います。
html+css+JavaScriptだけだと、どうしても細かいレイアウトやいかにも文書レポートらしい味わいが出ないことがあります。
やれないことはないけど、手間に見合わない。
そういう時、次のような流れを踏むと、Webサイトに掲載する凝った文書レポートを簡単に作成できます。

  1. WordやExcelで文書レポートを作成
  2. まずはそれらを保存ないしは印刷でPDF化
  3. PDF化した原本は保管しておき、別途画像化する
  4. 画像化したものはSNS投稿用とする
  5. PDF原本はhtmlで枠を作って改めて個人サイトへ掲載する

こうすると、単に画像を貼るだけより目を引くコンテンツをWebサイトへ掲載できます。
PDF専用の枠組みやUIを用意して掲示すれば、専用文書みたいなムードが出るんですよね。

PDFを高解像度の画像に変換するpdfimg.py


from pdf2image import convert_from_path  # pdf2imageライブラリから、convert_from_path関数をインポート

pdf_path = r'C:\UsersアレコレOneDrive\_fein\google cloud\web tools\20241019サイト更新案内.pdf'  # 処理するPDFファイルのパスを指定

images = convert_from_path(pdf_path, dpi=300)  # PDFファイルを300dpiの解像度で画像に変換

for i, image in enumerate(images):  # 各画像をループして処理
    image.save(f'output_image_{i + 1}.png', 'PNG')  # 画像をPNG形式で保存

このスクリプトは指定されたPDFファイルを読み込み、そのPDFの各ページを画像に変換し、それぞれの画像をPNG形式で保存するものです。
pdf2imageライブラリのconvert_from_path関数を使って、PDFファイルを画像に変換します。
変換された画像はリストとして返され、forループを使って各画像を処理し、ファイル名にページ番号を付けてPNG形式で保存しています。
保存される画像ファイルの名前はoutput_image_1.png、output_image_2.pngというように、ページごとに異なる名前になります。

学生時代のスクリプトだからちょっと曖昧な部分もあるのですが、pdf2imageライブラリが動作するためには、PyMuPDF または Poppler のいずれかが必要だったはずです。

pdf2imageライブラリと併せて、せっかくなので両方とも紹介しましょう。

pdf2imageライブラリ

フェードアウト効果の草花写真

pdf2imageライブラリはPython用のライブラリで、PDFファイルの各ページを画像に変換するためのツールです。
これを使うと、PDFの内容をプログラム的に画像ファイルとして取り扱うことができるようになります。
例えば、PDFの各ページをJPEGやPNG形式の画像に変換して保存することが可能です。
このライブラリは、PyMuPDFやPopplerなどのバックエンドを使用して、PDFファイルから画像を抽出します。

次のコードでpdf2imageがインストールされます。
pipはPythonのパッケージマネージャですね。

pdf2imageのインストール


pip install pdf2image

pdf2imageライブラリは単独でPDFから画像を抽出できるわけではなく、他のプログラム(バックエンド)を利用してその機能を実現しています。
そのバックエンドというのが、PyMuPDF または Poppler のどちらか一つなんですよね。

PyMuPDF
これはMuPDFというPDF処理ライブラリのPythonバインディングです。PDFのページを画像として抽出するのに使えます。
Poppler
これはオープンソースのPDFレンダリングライブラリで、PDFの各ページを画像に変換するためのツールです。

そう、なので…スクリプトによってはどちらか1つでも良かったはずです。

PyMuPDFのインストール

これは特にややこしいことはないです。
Windowsなら次のコマンドでOK。


pip install pymupdf

Popplerのインストール手順(Windows)

Windowsではpopplerを直接インストールするのではなく、バイナリをダウンロードしてパスを通す必要があります。

  1. バイナリのダウンロード: Popplerのバイナリを提供しているサイト(Poppler公式サイト)からバイナリをダウンロードします。
  2. 解凍: ダウンロードしたZIPファイルを解凍します。解凍すると、フォルダにbinやincludeなどのディレクトリが含まれています。
  3. パスを通す: 解凍したフォルダのパスを環境変数に追加します。
  4. スタートメニューで「環境変数」と検索し、「システム環境変数の編集」を選択。
  5. 「システム環境変数」の下にある「環境変数」をクリック。
  6. 「システム環境変数」セクションの中から「Path」を選択し、「編集」をクリック。
  7. 「新規」をクリックし、Popplerのbinフォルダへのパス(例: C:\path\to\poppler\bin)を追加。
  8. すべてのウィンドウを「OK」で閉じて保存。

これで、Popplerが正しくインストールされ、パスが通った状態になります。

Popplerのインストール手順(Linux)

私はDebian系のUbuntuを使ってたから、そっちのパッケージマネージャーを使用したインストール方法を書きましょうか。

Debian系でPopplerのインストール


sudo apt-get update
sudo apt-get install poppler-utils

こういうところを見ると、やはりWindowsよりLinuxのほうが個人サイトは作りやすいと思います。
そこらへんのウェブサイトビルダーを使うならWindowsでも良いですが、コードを全て書くことで完全オリジナルな個人サイトを作ろうとしたとき、慣れた人ならともかく、そうでないと環境構築に手間がかかる。
Linuxのほうが手順が単純です。

アナデンのPDFレポートで大活躍したスクリプト
フェードアウト効果の草花写真

アナザーエデン:feinが書いたレポート集にあるPDFの数々は、こうやって画像化してからTweetしていたのです。

Twitterでは無料で画像化してくれるWebサービスを紹介しておりましたが、実際の私の手元ではpythonスクリプトで処理していました。
周りを見ると、あまりプログラミングをやるような人が見られなかったこともありますね。
アカウントから出るコンテンツの作成過程については、たとえこのスクリプトのような簡単なことであったとしても、あまり大っぴらにしない方がいい。
イーロンマスクの話ではないけど、SNSはどこも対抗意識や競争意識の魔窟です。
全てが終わってから表に出す方が、SNSアカウントの話題コントロールもやりやすいってことよね。
でも、もうこうして生コードの個人サイトも公開しており、アナデンの高難易度バトルについてPDFレポートを作成する必要もなくなったから。
このスクリプトは学生時代からずっと大活躍していたのですよ?

PDFがテキストベースかまとめてチェックするpython

このスクリプトはPDFファイルが既にテキストベースかどうか、まとめてチェックします。
画像からテキストを抽出できるかを確認することで、OCR処理が可能かどうかを判断するんです。
小さなことですが、Webサイトに大量のPDFがある場合、それらも検索エンジンに載せる必要があります。
この時、PDFがテキストベースでなければほとんど意味を成しません。

例えばマニアックな魚の生態などを調べていると、どこかの大学が書いた論文等がたくさん出てきますよ。
検索ワードの組み合わせによって出てくることもあるし、手持ち資料にPDFがあるなら、それらもしっかりWebサイトに載せておくと時間をかけて効いてきます。

PDFがテキストベースになっているかチェックするpdfocr.py


import os
import fitz  # PyMuPDFライブラリをインポート
import pytesseract  # OCRライブラリをインポート
from pdf2image import convert_from_path  # PDFを画像に変換するライブラリをインポート

# PDFがテキストベースかどうかを確認する関数
def is_text_based_pdf(pdf_path):
    try:
        # PDFドキュメントを開く
        pdf_document = fitz.open(pdf_path)
        # 各ページをチェック
        for page_num in range(len(pdf_document)):
            page = pdf_document.load_page(page_num)
            text = page.get_text()
            # テキストが含まれている場合はTrueを返す
            if text.strip():
                return True
        # テキストが含まれていない場合はFalseを返す
        return False
    except Exception as e:
        # エラーが発生した場合の処理
        print(f"エラーが発生しました: {e}")
        return False

# OCRが可能かどうかを確認する関数
def is_ocr_possible(pdf_path):
    # PDFがテキストベースの場合はTrueを返す
    if is_text_based_pdf(pdf_path):
        return True
    try:
        # PDFドキュメントを開く
        pdf_document = fitz.open(pdf_path)
        # 各ページをチェック
        for page_num in range(len(pdf_document)):
            page = pdf_document.load_page(page_num)
            # ページを画像に変換
            pix = page.get_pixmap()
            image = convert_from_path(pdf_path, first_page=page_num+1, last_page=page_num+1)[0]
            # 画像からテキストを抽出
            text = pytesseract.image_to_string(image)
            # テキストが含まれている場合はTrueを返す
            if text.strip():
                return True
        # テキストが含まれていない場合はFalseを返す
        return False
    except Exception as e:
        # エラーが発生した場合の処理
        print(f"エラーが発生しました: {e}")
        return False

# ディレクトリ内のPDFファイルをチェックしてOCRが可能かどうかを確認する関数
def check_directory_for_ocr(directory_path):
    # ディレクトリ内のPDFファイルをリストアップ
    pdf_files = [f for f in os.listdir(directory_path) if f.lower().endswith('.pdf')]
    results = {}
    # 各PDFファイルをチェック
    for pdf_file in pdf_files:
        pdf_path = os.path.join(directory_path, pdf_file)
        results[pdf_file] = is_ocr_possible(pdf_path)
    return results

# 使用例
directory_path = r"C:\Users\アレコレ\Downloads\drive-download"
ocr_results = check_directory_for_ocr(directory_path)
# 各PDFファイルのOCR可能性を表示
for pdf_file, is_ocrable in ocr_results.items():
    print(f"{pdf_file}: {'OCR可能' if is_ocrable else 'OCR不可能'}")

このスクリプトは、指定されたディレクトリ内のPDFファイルがOCR(光学文字認識)可能かどうかをチェックしています。
OCRのライブラリについては、このページの上部ですでに触れましたね。

必要なライブラリのインポート

os
ファイルやディレクトリの操作を行うための標準ライブラリ
fitz(PyMuPDF)
PDFファイルを操作するためのライブラリ
pytesseract
画像からテキストを抽出するためのOCRライブラリ
convert_from_path(pdf2image)
PDFを画像に変換するための関数
PDFがテキストベースかどうかを確認する関数 is_text_based_pdf
PDFファイルを開き、各ページからテキストを抽出します。 テキストが含まれている場合は True を返し、含まれていない場合は False を返します。 エラーが発生した場合は、エラーメッセージを表示し、False を返します。
OCRが可能かどうかを確認する関数 is_ocr_possible
まず、PDFがテキストベースかどうかを確認します。テキストベースであれば True を返します。 テキストベースでない場合、PDFを画像に変換し、各ページの画像からテキストを抽出します。 画像からテキストが抽出できれば True を返し、抽出できなければ False を返します。 エラーが発生した場合は、エラーメッセージを表示し、False を返します。
ディレクトリ内のPDFファイルをチェックする関数 check_directory_for_ocr
指定されたディレクトリ内のPDFファイルをリストアップします。 各PDFファイルに対して is_ocr_possible 関数を呼び出し、OCRが可能かどうかを確認します。 結果を辞書形式で返します(ファイル名をキー、OCR可能かどうかを値とする辞書)。
フェードアウト効果の草花写真

使用例

チェックするディレクトリのパスを指定します。
check_directory_for_ocr 関数を呼び出し、結果を取得します。
各PDFファイルのOCR可能性を表示します。
ちょっと分かりにくいかもしれないので、改めて該当部分を書いてみます。


# 使用例
directory_path = r"C:\Users\アレコレ\Downloads\drive-download"
ocr_results = check_directory_for_ocr(directory_path)
# 各PDFファイルのOCR可能性を表示
for pdf_file, is_ocrable in ocr_results.items():
    print(f"{pdf_file}: {'OCR可能' if is_ocrable else 'OCR不可能'}")
            

この「# 使用例」の部分は、単なる説明文ではなく、スクリプトの実行例を示す重要な部分です。
この部分がなければ、スクリプトは実際に動作しません。
関数がどのように動作するかを確認することができませんし、スクリプト全体の動作をテストすることもできません。
つまり、「# 使用例」の部分は、スクリプトの動作を確認するための実行例であり、スクリプトの一部として重要な役割を果たしています。
この部分では、次のように動作しています。

ディレクトリパスの指定
directory_path 変数に、チェックしたいディレクトリのパスを指定しています。
関数の呼び出し
check_directory_for_ocr 関数を呼び出し、指定したディレクトリ内のPDFファイルがOCR可能かどうかをチェックしています。
結果の表示
ocr_results 辞書に格納された結果をループで回し、各PDFファイルがOCR可能かどうかを表示しています。

このように、「# 使用例」は、スクリプトの機能を実際にどのように使うかを示すための例として書かれています。
あるいは実行例とか、サンプルコードといった用語でも良いかもしれない。
いずれにしても、これで全てのPDFがOCR可能であることを確認してから、このサイトではPDFを掲載しています。
でももともとWordやExcelで書いたレポートをPDF化しているだけですから、まず問題が出ることはないでしょう。

プログラミングでhtmlコーディングのミスを防ぐ

例えば report.html というページがあるとしましょう。
そのhtmlファイルがある場所に「pdf」というディレクトリがあります。
そのpdfディレクトリに大量のpdfが格納されている。

この状況で、report.htmlにpdfファイルへのハイパーリンクを記述していくのは大変な作業となります。
5つや6つくらいならともかく、100を超えてくると人力では難しいでしょう。
ハイパーリンクというのは <a href=""></a> と書かれます。
report.htmlに記述されるpdfファイルへのハイパーリンクは当然 <a href="pdf/explanation.pdf"></a> となりますが、大量にあるファイルへのハイパーリンクの記述を延々と手書きしていると、必ずと言って良いほどミスに繋がるんです。

あまり好きな表現ではないのですが、いわゆる「個人サイト臭さ」というのは、こういうところから出てきます。
たまに1つや2つのミスが見つかるくらいなら許容できるし、むしろ可愛げさえ出てくる。
しかし…どこのページに行っても、いつ見ても何かしらミスがあったり、中途半端だったり。
これが続くと、人はそのWebサイトに訪問しなくなります。
使いにくいことが分かっているからね。
悪印象が定着してしまうのです。

大量のハイパーリンクをまとめて記述するpython

ここで紹介するスクリプトは、人間の手作業によるケアレスミスを防ぐためのスクリプトです。
どんなに工夫してもミスをゼロにすることはできませんが、やれることはやったほうが良いですね。

大量のハイパーリンクをまとめて記述するpdfhtml.py


import os  # osモジュールをインポートして、ファイルやディレクトリの操作を行う

# PDFファイルが保存されているディレクトリのパスを指定
directory = r'C:\Users\アレコレ\OneDrive\_fein\google cloud\fein-sites-dev1\www\another-eden\fein_report'

# HTMLファイルの出力先のパスを指定
output_file = r'C:\Users\アレコレ\OneDrive\_fein\google cloud\web tools\pdfhtml.html'

# HTMLファイルを作成して書き込みモードで開く
with open(output_file, 'w', encoding='utf-8') as f:
    f.write('<html><body>\n')  # HTMLファイルの基本構造を作成

    # 指定したディレクトリ内のすべてのファイルをループで処理
    for filename in os.listdir(directory):
        print(f'Found file: {filename}')  # デバッグ用にファイル名をコンソールに表示
        if filename.endswith('.pdf'):  # ファイル名が.pdfで終わる場合
            # HTMLリンクを作成してファイルに書き込む
            f.write(f'<p><a href="fein_report/{filename}">{filename}</a></p>\n')

    f.write('</body></html>')  # HTMLファイルの終了タグを追加

print(f'HTML file has been created: {output_file}')  # 完了メッセージをコンソールに表示
                

このコードは、指定されたディレクトリ内のすべてのPDFファイルをリスト化し、それらのファイルへのリンクを含むhtmlファイルを生成します。
なんでhtmlファイルを生成するかというと、そのまんまコピペできるからですよ。
pythonにhtmlコードを書かせるだけ書かせて、自分はコピペするだけです。

ディレクトリとファイルの設定
directory:変数にPDFファイルが保存されているディレクトリのパスを指定しています
output_file:変数にHTMLファイルの出力先のパスを指定しています
HTMLファイルの作成
with open(output_file, 'w', encoding='utf-8') as f: で指定されたパスに新しいHTMLファイルを作成し、書き込みモードで開きます <html><body>\n を書き込んでHTMLファイルの基本構造を作成します
ディレクトリ内のファイルをループ
os.listdir(directory) を使って指定されたディレクトリ内のすべてのファイルをリスト化し、ループで処理します
各ファイル名をデバッグ出力としてコンソールに表示します(print(f'Found file: {filename}'))
PDFファイルのリンクをHTMLに追加
ファイル名が .pdf で終わる場合、HTMLリンクとして書き込みます(f.write(f'<p><a href="fein_report/{filename}">{filename}</a></p>\n'))
HTMLファイルの終了タグを追加
</body></html> を書き込んでHTMLファイルを閉じます
完了メッセージの表示
最後に、HTMLファイルが作成されたことをコンソールに表示します(print(f'HTML file has been created: {output_file}'))

こういう小さなミスを防げるスクリプトを書けると、格段に個人サイト作成がラクになりますよ?
何百回も似たような作業をしていれば必ずミスは発生するのですから、とりあえず自動化できる部分は自動化しちゃった方がいいよね。
とにかくラクをして金もかけないこと。
これが個人サイトを継続するために必要な、最も重要なポイントであるとみて間違いないです。
大変な思いをするから放置しちゃう。
そこをプログラミングで何とかするっていう。

手間のかかるhtmlコーディングをpythonに任せる

当サイトでは、PDFを気軽に閲覧できるようプレビューボタンを設置しています。
通常のハイパーリンク以外にボタンを設置しており、そこを押すとPDFがプレビュー表示できます。
この機能があればいちいちWebサイトから外部のアプリに出ずとも、そのままブラウザでPDFファイルの中身を閲覧できるからです。

JavaScriptとCSSに関しては 個人サイトでよく使うJavaScript で説明しています。
ここではpythonによるhtmlコード出力について、説明します。

このPDFプレビューボタンが、けっこう手間のかかるコードなんですよねー
CSSはともかくJavaScriptでページ送りやらページ数やらを制御していることもあって、それらのボタンまでhtmlで作ってあげないといけない。
見た目は単なるボタンだけどコードがちょっと長いので、複数のPDFを扱うと非常に面倒です。
そこで、pythonに作ってもらうんだよね。

PDFプレビューボタン設置に使うpython

やっていることは単純です。
ワンパターンなhtmlコードがあり、そこにpdfファイルを当てはめていくだけのお仕事をpythonにやってもらいます。
こういう作業が人間が100回200回とやっていくと、ミスに繋がるわけですよ。

実際のpythonスクリプトに入る前に、Webページに載せる予定のpdfファイルリストを用意します。

ファイル名と拡張子だけを抽出するコマンド


dir /b "C:\path\to\directory" > filelist.txt
        

このコマンドをコマンドプロンプトで実行すれば、ある任意のディレクトリに格納されているファイルの名称と拡張子だけを抽出できます。
こんなの手作業でやってたらキリないですよ。
実際にはこの作業もpythonにやってもらうことができますが、私の環境ではpdfファイル以外にいろいろ入っていたものでね。
いきなりhtmlを書く前に少し確認することにしたのです。

取得したpdfファイル名と拡張子のリストを使って、次のようなスクリプトを用意します。

PDFプレビューボタンhtmlを書くpdfpreview.py


# PDFファイル名称リスト
pdf_files = [
    "高難易度対策ノート:最終更新=20210404.pdf",
    "魚のさばき方.pdf",
    "黒衣の刀使いの影.pdf",
    "2部結戦役.pdf",
    "3部直前アナデンプレイ状況アンケート結果.pdf"
]

# HTMLテンプレート
html_template = """
<div class="pdf-list-add">
    <button class="pdf-link-add" data-url="fein_report/{0}">{0}を開く</button>
</div>
<div class="feinpdf-container-add addpdfhidden">
    <div class="feinpdf-viewer-add"></div>
    <div class="feinpdfcontrols-add">
        <button class="prev-page-add">前のページへ</button>
        <span>Page: <span class="page-num-add"></span> / <span class="page-count-add"></span></span>
        <button class="next-page-add">次のページへ</button>
    </div>
</div>
"""

# HTMLファイルに出力
# "output.html" という名前のファイルを作成し、書き込みモードで開きます
with open("output.html", "w", encoding="utf-8") as f:
# PDFファイルリストの各ファイル名についてループします
for pdf in pdf_files:
# HTMLテンプレートにPDFファイル名を挿入し、ファイルに書き込みます
f.write(html_template.format(pdf))
        

このスクリプトは指定されたPDFファイル名を使ってHTMLボタンを生成し、それを output.html ファイルに書き出すものです。
大量のpdf資料があっても、このスクリプトを使えば一気にWebサイトへ掲載できるのですよ。

PDFファイル名称リストの定義
pdf_files というリストに、PDFファイルの名前を格納しています。
HTMLテンプレートの定義
html_template という変数に、HTMLのテンプレートを文字列として格納しています。
{0} はプレースホルダーで、後でPDFファイル名がここに挿入されます。
HTMLファイルに出力
with open("output.html", "w", encoding="utf-8") as f:
output.html という名前のファイルを作成し、書き込みモードで開きます。
for pdf in pdf_files:
pdf_files リストの各PDFファイル名についてループします。
f.write(html_template.format(pdf))
html_template の {0} に pdf を挿入し、生成されたHTMLコードを output.html ファイルに書き込みます。

officeソフトで作られた文書類をwebサイトに掲載するなら、pdfにしてからプレビュー機能付きでハイパーリンクを添えるのが一番無難だと思います。


サイトマップ

アナザーエデン関連ページ・サイトマップ

アナザーエデンの強敵戦やストーリーコンテンツのリスト、お勧めバッジなどを掲載したコーナーです。
期間限定のない普通のRPGですので、初心者でも安心して続けていけるゲームとなっています。
もっとも重要なグラスタについては、場所別に網羅した表があります。

個人サイトのホスティングとコンテンツ作成

個人でウェブサイトを作るにはどうすればいいか。
HTML・CSS・JavaScriptの書き方はもちろん、無料かつ広告なしでホームページを作る方法を掲載したコーナーです。
Webデザインやレイアウトについても書いてあります。

魚釣りなどアウトドアのエリア

ゲームとパソコンだけじゃなく、アウトドアも趣味なんです。
このコーナーでは魚釣りの記録とか、魚料理のレシピ、はたまたサイクリングなどなど。
アウトドアに関連するコンテンツが詰め込まれています。