LoginSignup
2
1

More than 3 years have passed since last update.

【Vue.js, Express, Python】HTMLからテキストとWordファイルを自動生成する

Last updated at Posted at 2020-07-27

課題、目的

今まで毎週Wordで書いてきたレポートを、最後に一つのWordファイルにまとめて提出する、という謎の課題が期末に出された。
しかし私は、Wordファイルが増えるのが嫌なので、Wordファイルで作成したレポートを、はてなブログにまとめて保存していた。
はてなブログからWordにコピペしようとしたのだが、Wordファイルの表示がaタグなどがじゃまできれいにならない。
スクリーンショット 2020-07-24 18.59.13.png
これらを手作業で直すのはあまりに億劫である。
そこで、HTMLファイルをテキストに変換すればうまくいきそう、と思い、変換サイトを見つけたが、せっかくなので自分で作ってみることにした。
ついでに、勉強と経験のために変換されたテキストを元にWordファイルを自動生成することにした。

文章が長すぎると404エラーになったり、他にもまだバグがあるかもしれないが、コードの整理をする前に頭の整理をするため、記事を書いていく。

完成形

スクリーンショット 2020-07-27 14.06.45.png

1 デザイン

スクリーンショット 2020-07-27 12.21.14.png

2 HTML => TEXT 変換

スクリーンショット 2020-07-27 12.22.36.png

3 TEXT保存

スクリーンショット 2020-07-27 12.24.13.png

4 Wordファイル作成

スクリーンショット 2020-07-27 12.25.12.png

実装

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

App.vue
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)
    })
},
server.js
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を連携してデータを表示してみた

App.vue
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)
      })
},
server.js
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ポリシーを無効にしなければならないので注意。

server.js
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を操作する

App.vue
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)
      })
}
server.js

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);
    });
})
createWord.py
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に出会えただけで大きな収穫だった。
応用が効きそうなので気が向いたら色々試していきたい。

2
1
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
2
1