自動でページをめくれるようなWEBサイトを生成するPythonコードをCopilotに質問して作ってみた

## WEB漫画サイトとかで使えそうな自動生成Pythonコードを作ってみた

最初、javaScriptで画像フォルダ内の枚数分ページを生成するようなものを作ろうか考えましたが、サーバーサイドで動かす必要が有るため、完全ローカル環境で動かす方法は無いかと思い、Pythonならやれるんじゃね？って思ったのがきっかけで作りました。

目的は、趣味でイラストを描いていて、作成した本をWEB公開する方法として、
Copilotに質問してWEBサイトを作らせたという経緯です。
いちいちＨＴＭＬを作り直す手間暇が減るので便利そうだな～って思って、案外Copilotでやれちゃうもんなんだなぁという感想を持ちました。面白い。

### 概要とか注意点とか
- imagesフォルダに入っている画像データの枚数分、ページを作成します。
- png、jpg、jpeg、gifに対応しています。
- ぶっちゃけCopilotに任せっぱなしのプログラムです。細かい調整はしていません。ページ数の所をマウスで選択出来なかったり、ページ数が左上に配置されているので、気にくわなければCSSは自分で調整してください。

### 使い方
- 同一フォルダ内に、「images」フォルダと、pyファイルを配置して利用します。
- imagesフォルダ内に画像を入れてください。
- imagesフォルダ内の画像はナンバリングしてください。半角数字で動作します。
- pyを実行すると、同一フォルダ内に「gallery.html」が生成されます。
- 以下のような感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4044110/fd19206b-f2be-4875-a994-7c74534686e0.png)


```
import os

# 画像を取得し番号順にソートする関数
def get_sorted_images(folder_path):
    images = [img for img in os.listdir(folder_path) if img.endswith(('.png', '.jpg', '.jpeg', '.gif'))]
    images.sort(key=lambda x: int(os.path.splitext(x)[0]))
    return images

# HTMLファイルを生成する関数
def generate_html(folder_path, output_file):
    images = get_sorted_images(folder_path)

    html_content = """
    <!DOCTYPE html>
    <html>
    <head>
        <title>Image Gallery</title>
        <style>
            body {
                font-family: Arial, sans-serif;
                display: flex;
                flex-direction: column;
                justify-content: center;
                align-items: center;
                height: 100vh;
                margin: 0;
                overflow: hidden;
                background-color: #f0f0f0;
            }
            .gallery-container {
                width: 80%;
                height: 80%;
                position: relative;
            }
            .slide {
                position: absolute;
                width: 100%;
                height: 100%;
                opacity: 0;
                transition: opacity 1s ease-in-out;
            }
            .slide img {
                width: 100%;
                height: 100%;
                object-fit: contain;
            }
            .slide.active {
                opacity: 1;
            }
            .navigation {
                position: absolute;
                top: 50%;
                width: 100%;
                display: flex;
                justify-content: space-between;
                transform: translateY(-50%);
            }
            .navigation button {
                background-color: rgba(0, 0, 0, 0.5);
                color: white;
                border: none;
                padding: 10px 20px;
                cursor: pointer;
                border-radius: 5px;
                font-size: 16px; /* 文字サイズを16pxに設定 */
            }
            .navigation button:hover {
                background-color: rgba(0, 0, 0, 0.8);
            }
            .page-indicator {
                margin-top: 20px;
                font-size: 16px; /* ページ表示のフォントサイズ */
            }
        </style>
    </head>
    <body>
        <div class="gallery-container">
    """

    for i, image in enumerate(images):
        active_class = "active" if i == 0 else ""
        html_content += f"""
            <div class="slide {active_class}" id="slide{i}">
                <img src="{folder_path}/{image}" alt="Image {i+1}">
            </div>
        """

    html_content += """
            <div class="navigation">
                <button id="next">進む</button>
                <button id="prev">戻る</button>
            </div>
            <div class="page-indicator" id="page-indicator">
                1 / {total_pages}
            </div>
        </div>
        <script>
            const slides = document.querySelectorAll('.slide');
            const totalPages = slides.length;
            let currentSlide = 0;

            const pageIndicator = document.getElementById('page-indicator');

            document.getElementById('next').addEventListener('click', () => {
                slides[currentSlide].classList.remove('active');
                currentSlide = (currentSlide + 1) % slides.length;
                slides[currentSlide].classList.add('active');
                pageIndicator.textContent = `${currentSlide + 1} / ${totalPages}`;
            });

            document.getElementById('prev').addEventListener('click', () => {
                slides[currentSlide].classList.remove('active');
                currentSlide = (currentSlide - 1 + slides.length) % slides.length;
                slides[currentSlide].classList.add('active');
                pageIndicator.textContent = `${currentSlide + 1} / ${totalPages}`;
            });
        </script>
    </body>
    </html>
    """

    html_content = html_content.replace("{total_pages}", str(len(images)))

    with open(output_file, 'w', encoding='utf-8') as f:
        f.write(html_content)

# 実行部分
folder_path = "images"  # 画像フォルダのパスを指定
output_file = "gallery.html"       # 出力するHTMLファイル名
generate_html(folder_path, output_file)
print(f"HTMLファイル '{output_file}' が生成されました。ブラウザで開いて確認してください。")

```

## 蛇足
以下のスクリーンショットの通り質問して作った。質問のコツになるかわからないが、参考になれば幸いと思い質問の流れを以下に記載する。
結果のプログラムは上記の通りの為、途中のコードは公開せずスクショだけにしておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4044110/b214294d-b0b3-4fcf-8d4d-38ca94fa28a1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4044110/03fdd08b-7de4-47f3-b1d8-915bd3955980.png)


上記のままでは、結局サーバーに実行させるようになってしまう。
なので、以下の通り質問した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4044110/bc1c26b4-bb79-4978-afda-03df1ff8586b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4044110/f9857b30-62b6-4ddb-b93c-5f38b7006505.png)


なんかコードがバラバラで見ずらいので、まとめさせる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4044110/27411b74-cf91-4c41-a4b1-680871bb73d8.png)


実行してみると、ページをめくる動作をしなかったので、以下の通り指示。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4044110/9e04378f-33e4-481d-b256-7e680b2afefc.png)


ページをめくるボタンが英語になっていたので、日本語に修正させ、文字が小さすぎたのでCSSを修正させたい。
以下の通り指示した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4044110/37bd6854-83ea-4ac2-be18-ce42582e9e4f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4044110/53c8eb27-6049-4318-baec-d40a04fdf8c9.png)


ほぼ完成したが、ページ数が左上に有って変なので、直させたい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4044110/4c625969-b920-481b-b523-58ddc803253b.png)

結局、上手くページ数の位置は下に配置されなかった。残念。
プログラムは初心者に毛が生えた程度しかわからない為、これは諦める事とした。
ここまで質問した結果が当サイトでのプログラムである。

### 最後に

ご拝読ありがとうございました。
初めて作ったQiitaの記事なので拙く見ずらいかと思われる事、私はプログラムにわかなので中途半端な者だが、何か発見でもしたら共有します。

本当の本当に蛇足ですが、以下に私のイラストを投稿しているXのサイトを置いておきます。たまに絵を投稿しています。
[X　@tizumoti2525](URL "https://x.com/tizumoti2525")