0
0

More than 3 years have passed since last update.

PythonでHTMLテンプレートにJSONデータを流し込んで複数のHTMLファイルを一括生成する

Last updated at Posted at 2021-01-20

共通フォーマットのHTMLテンプレートファイルに対して、別で管理しているデータを流し込んで複数のHTMLファイルを一括で生成してみたいと思います。

実行環境

・Node.js 14.15
・Python 3.8
・Jinja

手順

  1. JSONデータの作成
  2. テンプレートHTMLの作成
  3. Pythonスクリプトの作成
  4. 実行

JSONデータの作成

JSONのデータは外部APIなどで取得してもよいのですが、今回はローカルで作成し、管理・運用がしやすいようにTypeScriptのオブジェクトから作成したいと思います。

types/index.ts
// データの型定義ファイル

type Post = {
  id: string;
  date: string;
  title: string;
  author: string;
  body: string;
};

export interface PageData {
  filename: string;
  meta: {
    title: string;
    description: string;
  }
  posts: Post[];
}

/data/pages ディレクトリにそれぞれのページごとにデータを管理します。

sample-a.html を管理するデータ

/data/pages/sample-a.ts
import { PageData } from '../../types';

export const sampleA: PageData = {
  filename: 'sample-a.html',
  meta: {
    title: 'サンプルA',
    description: 'サンプルAの説明文',
  },
  posts: [
    {
     id: '001',
     date: '2021/01/01',
     title: '初めての投稿',
     author: 'いぬ',
     body: 'hoge',
    },
    {
     id: '002',
     date: '2021/01/02',
     title: '面白いタイトル!',
     author: 'ねこ',
     body: 'hogehoge',
    }
  ]
}

sample-b.html を管理するデータ

/data/pages/sample-b.ts
import { PageData } from '../../types';

export const sampleB: PageData = {
  filename: 'sample-b.html',
  meta: {
    title: 'サンプルB',
    description: 'サンプルBの説明文',
  },
  posts: [
    {
     id: '003',
     date: '2021/01/05',
     title: '心に残る映画',
     author: 'いぬ',
     body: '〇〇〇〇〇〇〇〇〇〇',
    },
  ]
}

これらのTypeScriptオブジェクトを結合してJSONデータを生成します。

JSONデータを生成するためのスクリプトを書きます。

script.ts
import { writeFile } from "fs"; // <- 事前に "yarn add -D fs" でモジュールをインストール
import { PageData } from "./types";
// データのインポート
import { sampleA } from "./data/pages/sample-a";
import { sampleB } from "./data/pages/sample-b";

// 配列に入れる
const data: PageData[] = [sampleA, sampleB];

// JSONデータのファイルとして書き出し
writeFile('data.json', JSON.stringify(data, null, "  "), () => {});

これをJSにコンパイルしてNode.jsで実行します。

tsc script.ts
node script.js

これで data.json が生成されます。

data.json
[
  {
    "filename": "sample-a.html",
    "meta": {
      "title": "サンプルA",
      "description": "サンプルAの説明文"
    },
    "posts": [
      {
        "id": "001",
        "date": "2021/01/01",
        "title": "初めての投稿",
        "author": "いぬ",
        "body": "hoge"
      },
      {
        "id": "002",
        "date": "2021/01/02",
        "title": "面白いタイトル!",
        "author": "ねこ",
        "body": "hogehoge"
      }
    ]
  },
  {
    "filename": "sample-b.html",
    "meta": {
      "title": "サンプルB",
      "description": "サンプルBの説明文"
    },
    "posts": [
      {
        "id": "003",
        "date": "2021/01/05",
        "title": "心に残る映画",
        "author": "いぬ",
        "body": "〇〇〇〇〇〇〇〇〇〇"
      }
    ]
  }
]

テンプレートHTMLの作成

共通フォーマットのテンプレートHTMLを作成します。
テンプレートは Python のライブラリ Jinja2 で使用するので、Jinja2 の構文に従って作成します。

templates/page.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{{ meta.title }}</title>
  <meta name="description" content="{{ meta.description }}">
</head>
<body>
  <h1>{{ meta.title }}</h1>
  <div class="posts">
    {% for post in posts %}
      <div class="post" data-id="{{ post.id }}">
        <div class="date">{{ post.date}}</div>
        <h2 class="title">{{ post.title }}</h2>
        <div class="author">{{ post.author }}</div>
        <div class="body">{{ post.body }}</div>
      </div>
    {% endfor %}
  </div>
</body>
</html>

作成した PageData の型に従って、JSONから受け取ったデータを入れる変数を {{ }} の中に記述します。

forループやif文などの制御構文は {% %} の中に記述して使うことができます。
詳細については Jinja2 のページをご参照ください。

Pythonスクリプトの作成

データとテンプレートは出来上がったので、いよいよビルドするためのスクリプトをPythonで書いていきます。

まずは Jinja2 ライブラリをインストールします。

pip install jinja2
generate.py
from jinja2 import Environment, FileSystemLoader
import json
import os

# 1.JSONからデータの読み込み
json_open = open('./data.json', 'r')
# データの格納された配列
items = json.load(json_open)

# 2.テンプレートファイルの読み込み
env = Environment(loader = FileSystemLoader('./templates'), autoescape = True)
template = env.get_template('page.html')

# 3.テンプレートにデータの流し込み
build_dir = 'dist'
# distディレクトリの存在を確認。なければ作成する
if not os.path.isdir(build_dir):
  os.mkdir(build_dir)

# データ配列の数だけ実行
for item in items:
  # テンプレートにデータを流し込んでHTMLを作成
  parse_html = template.render(item)

  # 保存先のパスを作成
  path = f"{build_dir}/{item['filename']}"

  # HTMLファイルの生成と保存
  with open(path, 'w') as file:
    file.write(parse_html)

ビルドの実行

python generate.py

これで、dist/ ディレクトリに目的のHTMLファイル(ここでは sample-a.htmlsample-b.html )が生成されていれば完了です!

ソースコードはGitHubに載せています。
https://github.com/hiropy0123/python-html-generate

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0