moodleで提出された課題を自動で集計するスクリプトを作成した

2024/05/15

moodle

はじめに

moodleで学生がテキスト形式の課題を提出した際に、教師が採点のために課題を一括ダウンロードすると、
学生毎に謎の名前のディレクトリが生成され、ディレクトリの中に「onlinetext.html」というHTMLファイルが1つ生成されるという仕様になっていることが分かりました。
コース数や1コース当たりの課題数、ユーザー数が増えると、採点が大変になるのが明白なので、提出された課題の中身を自動で集計するスクリプトを作成しました。

ディレクトリ構成

ディレクトリ構成は以下のとおりです。

.
├── Dockerfile
├── data
│   └── kadai01
│       ├── user01_xxxxxx
│       │   └── onlinetext.html
│       └── user02_xxxxxx
│           └── onlinetext.html
├── docker-compose.yml
├── main.py
└── output

スクリプト

スクリプトの中身は以下の通りです。

main.py
import os
import csv
import datetime
from bs4 import BeautifulSoup

# 現在の作業ディレクトリ
current_dir = os.getcwd()
target_dir = os.path.join(current_dir, 'data')

# 出力CSVファイルのパス(タイムスタンプ付き)
timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
output_csv_path = os.path.join(current_dir, 'output', f'extracted_paragraphs_{timestamp}.csv')

# 出力ディレクトリが存在しない場合、作成する
os.makedirs(os.path.dirname(output_csv_path), exist_ok=True)

# CSVファイルの準備
with open(output_csv_path, 'w', newline='', encoding='shift-jis') as csvfile:
    csvwriter = csv.writer(csvfile)
    csvwriter.writerow(['Directory', 'Paragraphs'])

    # 全てのディレクトリを走査
    for root, dirs, files in os.walk(target_dir):
        for directory in dirs:
            dir_path = os.path.join(root, directory)
            file_path = os.path.join(dir_path, 'onlinetext.html')

            # onlinetext.htmlファイルが存在する場合
            if os.path.isfile(file_path):
                # ディレクトリ名の最初の「_」までの文字列を取得
                directory_prefix = directory.split('_')[0]

                # onlinetext.htmlを読み込む
                with open(file_path, 'r', encoding='utf-8') as file:
                    soup = BeautifulSoup(file, 'html.parser')

                # <p>タグの中身を抽出し、<br>タグを改行に置換して結合
                paragraphs = '\n'.join(p.get_text(separator="\n") for p in soup.find_all('p'))

                # CSVに書き込む
                csvwriter.writerow([directory_prefix, paragraphs])

                print(f"Extracted paragraphs from {file_path} and added to {output_csv_path}")

print(f"All paragraphs extracted and saved to {output_csv_path}")

スクリプトを実行するとoutputディレクトリ配下にCSVファイルが作成されます

# python main.py
Extracted paragraphs from /app/data/kadai01/user02_xxxxxx/onlinetext.html and added to /app/output/extracted_paragraphs_20240527155753.csv
Extracted paragraphs from /app/data/kadai01/user01_xxxxxx/onlinetext.html and added to /app/output/extracted_paragraphs_20240527155753.csv
All paragraphs extracted and saved to /app/output/extracted_paragraphs_20240527155753.csv
.
├── Dockerfile
├── data
│   └── kadai01
│       ├── user01_xxxxxx
│       │   └── onlinetext.html
│       └── user02_xxxxxx
│           └── onlinetext.html
├── docker-compose.yml
├── main.py
└── output
    └── extracted_paragraphs_20240527142352.csv

CSVファイルの中身を確認して正しく出力されていればOKです。

今回はここまでです。