課題、目的
今まで毎週Wordで書いてきたレポートを、最後に一つのWordファイルにまとめて提出する、という謎の課題が期末に出された。
しかし私は、Wordファイルが増えるのが嫌なので、Wordファイルで作成したレポートを、はてなブログにまとめて保存していた。
はてなブログからWordにコピペしようとしたのだが、Wordファイルの表示がaタグなどがじゃまできれいにならない。
これらを手作業で直すのはあまりに億劫である。
そこで、HTMLファイルをテキストに変換すればうまくいきそう、と思い、変換サイトを見つけたが、せっかくなので自分で作ってみることにした。
ついでに、勉強と経験のために変換されたテキストを元にWordファイルを自動生成することにした。
文章が長すぎると404エラーになったり、他にもまだバグがあるかもしれないが、コードの整理をする前に頭の整理をするため、記事を書いていく。
完成形

1 デザイン

2 HTML => TEXT 変換

3 TEXT保存

4 Wordファイル作成

実装
1 デザイン
Vuetifyを用いた。
2 HTML => TEXT 変換
JavaScriptでHTMLタグを削除する正規表現 を実装した。
3 TEXT保存
保存すべきカラムは、名前(name)とテキスト(text)である。
axiosを使ってVueからExpressにクエリパラメータとして両者を送信し、ExpressからMySQLに保存することにした。
Node.jsでMySQLに接続する方法は
Node.jsアプリケーションとMySQLを接続しよう!
を参考にした。
公式はこれ。
https://github.com/mysqljs/mysql
clickSaveBtn () {
console.log('pushed save button')
this.saveDialog = false
axios
.get('http://localhost:3000/' + this.saveFilename + '/' + this.text)
.then(res => console.log(res))
.catch(error => {
console.log('error occurs in axios ' + error)
})
},
app.get('/:name/:text', (req, res) => {
console.log('from frontend params: name => ' + req.params.name)
console.log('from frontend params: text => ' + req.params.text)
connection.query({
sql: 'INSERT INTO documents (name, text) values (?, ?)',
values: [req.params.name, req.params.text]
}, (error, results) => {
console.log('↓ results from db')
console.log(results)
})
})
4 Wordファイル作成
まずは、MySQLにある名前(name)のデータを選択肢としてブラウザに表示させる。
この記事が参考になった。
Nuxt.jsとmysqlを連携してデータを表示してみた
clickCreateBtn () {
console.log('pushed create button')
axios
.get('http://localhost:3000/filenames')
.then(res => {
console.log('↓response from server')
console.log(res.data)
for (let i = 0; i < res.data.length; i++) {
this.filenames.push(res.data[i].name)
}
})
.catch(error => {
console.log('error occurs in axions ' + error)
})
},
app.get('/filenames', (req, res) => {
let filenames = []
connection.query('SELECT name from documents', (error, row, fields) => {
if (error) {
console.log('error occured in db: '+ error)
}
let files = []
for (let i = 0; i < row.length; i++) {
files.push(row[i])
}
filenames = JSON.stringify(files)
res.header('Content-Type', 'application/json; charset=utf-8')
res.send(filenames)
})
})
なお、Node.js側でCORSポリシーを無効にしなければならないので注意。
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
最後に、選択された名前のファイルを元に、そのファイル名とテキストをDBから取り出してWordファイルを作成していく。
PythonとMySQLを連携させるのにはmysqlclientを用いた。
この記事が参考になった。
Python3でMySQLを使う – 基本操作からエラー処理まで
公式はこれ。
https://pypi.org/project/mysqlclient/
Node.jsとPythonを連携させるのにはPython-shellを用いた。
この記事が参考になった。
Python-shellの使い方
公式はこれ。
https://www.npmjs.com/package/python-shell
PythonからWordファイルを作成する方法はこの記事が参考になった。
【python-docx】PythonでWordを操作する
clickStartCreateBtn () {
this.createDialog = false
axios
.get('http://localhost:3000/word/' + this.createFilename)
.then(res => console.log(res))
.catch(error => {
console.log('error occurs in axios ' + error)
})
}
app.get('/word/:filename', (req, res) => {
let filename = req.params.filename
console.log('from frontend params: filename => ' + filename)
let { PythonShell } = require('python-shell')
let pyshell = new PythonShell('createWord.py')
pyshell.send(filename)
pyshell.on('message', function (data) {
console.log(data);
});
})
filename = sys.stdin.readline()
print('filename =>', filename.strip())
con = MySQLdb.connect(
host = os.environ.get("DB_HOST"),
user = os.environ.get("DB_USER"),
passwd = os.environ.get("DB_PASSWORD"),
db = os.environ.get("DB_NAME"),
)
cur = con.cursor()
sql = "select text from documents where name = %s"
cur.execute(sql, (filename.strip(),))
rows = cur.fetchall()
document = Document()
print('text =>', rows[0][0])
text = rows[0][0]
document.add_paragraph(text)
document.save(filename.strip()+'.docx')
print('success')
まとめ
役に立つものを作りたいわけじゃなかったので、Python-shellに出会えただけで大きな収穫だった。
応用が効きそうなので気が向いたら色々試していきたい。