はじめに
表の入ったpdfファイルを受け取ってcsvファイルに変換できるwebアプリをdjangoで作ってみました。
tabulaというpdfを読み取ってくれるライブラリを使用してみました。
参考にしたサイト
PythonでPDFファイルのテーブルデータを読み取る
Django 公式ドキュメント
完成したもの
ここにpdfファイルをアップロードしてボタンをクリックします。
今回は参考記事と同じくこちらのpdfを扱いました。
はい。手抜きなんです。成功が返ってきました。
保存先は自分の開発しているフォルダに入っています。そのcsvファイルをあけてみると、、、
取得することができました。こんな感じです。
コード
from django.shortcuts import render
from django.http import HttpResponseRedirect,HttpResponse
from .forms import UploadFileForm
import pandas as pd
#pdfからcsvに変換するためのライブラリ
from tabula import read_pdf
def fileUpload(request):
if request.method == 'POST':
# ファイルデータの受け取り
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
file_obj = request.FILES['file']
handle_uploaded_file(file_obj)
toCsv(file_obj)
context = {
'success': '成功!',
}
return render(request,'TableImageToCsv/result.html',context)
else:
form = UploadFileForm()
return render(request, 'TableImageToCsv/index.html', {'form': form})
# 受け取ったpdfファイルを保存する関数
def handle_uploaded_file(file_obj):
file_path = file_obj.name
with open(file_path, 'wb+') as destination:
for chunk in file_obj.chunks():
destination.write(chunk)
# 表pdfをcsvにする関数
def toCsv(file_obj):
file_name = file_obj.name.split('.')[0] + '.pdf'
# ここでtabulaを使ってpdfを読み取っている
df = read_pdf(file_name)
csv_file = file_obj.name.split('.')[0] + '.csv'
# 1つのページに複数の表があるときはdfの配列番号を指定すると良い
pd.DataFrame(df[0]).to_csv(csv_file, encoding='shift-jis')
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="CONTENT-TYPE"
content="text/html; charset=utf-8" />
<title>表の入ったpdfファイルをcsvに変換するアプリ</title>
</head>
<body>
<h3>表の入ったpdfファイルをアップロードしてください</h3>
<form method="POST"
enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">アップロード</button>
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="CONTENT-TYPE"
content="text/html; charset=utf-8" />
<title>表画像をcsvに変換するアプリ</title>
</head>
<body>
<h3>結果</h3>
<h2>{{success}}</h2>
</body>
</html>
from django import forms
class UploadFileForm(forms.Form):
title = forms.CharField(max_length=50)
file = forms.FileField()
おわりに
今回このアプリの実装は2日くらいかかったのですが、最初は表画像からcsvに変換するアプリを作るつもりでした。
そのために画像->pdf->csvとやろうとしていたのですが、結果上手くいきませんでした。
どうやら、pdfに変換する際に画像が荒くなってtabulaで読み取りきれてないように感じました。
同じ表でも画像とpdfでは読み込みの結果が異なってしまいました。
他のライブラリを使用したり、変換方法を変えたりすればよかったのかもしれませんが、ライブラリの仕組みについてもっと自分で勉強したいと思いました。
あと、作成したcsvファイルをユーザーがダウンロードできるような機能も実装すると使えるアプリになるのかなと思います。