LoginSignup
2
3

More than 3 years have passed since last update.

キャッチコピー自動生成のWEBアプリケーションを開発した話【MeCab】

Last updated at Posted at 2020-11-20

サービスサイト

MakeLike
https://melikeke.sakura.ne.jp/malike/intro

概要

PythonのMecabを使用して、様々な教師データから「っぽい文章」を生成します
・カテゴリから生成
・ファイルから生成
・直接入力から生成
の3パターンから教師データを指定できます。

機能

キャッチコピー自動生成

・カテゴリから生成
・ファイルから生成
・直接入力から生成

ログイン機能

会員登録
ログイン
会員登録通知
パスワード再設定

お気に入り機能

実装

環境

さくらサーバー

フロントエンド

Laravel

基本部分

テンプレートの活用

LaravelのBladeテンプレートでレイアウト部分を共通にする
http://cly7796.net/wp/php/to-a-common-layout-in-blade-template-of-laravel/


ログイン認証系

Laravelでサクッとログイン機能を実装する方法
https://php-junkie.net/framework/laravel/login/

「Command "make:auth" is not defined.」が出たら
https://qiita.com/daisu_yamazaki/items/a914a16ca1640334d7a5

【Laravel7でユーザー認証_8】メールアドレス変更時にメール認証を行う
https://qiita.com/crosawassant/items/018b29ab770c0a373bc9

Laravelの標準Authentication(Auth)の動きを調べてみる
https://qiita.com/zaburo/items/9fcf0f4c771e011a4d35


会員登録時の自動通知

下記のどちらかの方法で、メール通知やSlack通知が可能

Laravel

これを読めばLaravelのイベントとリスナーが設定できる
https://reffect.co.jp/laravel/laravel-event-listener#i-8

Google Analytics

Google アナリティクスからのアラートを受信しよう
https://www.ad-market.jp/column/2020/04/20200420.html


メール機能

パスワードリセットメールを送信するため、Laravelのメール機能を設定します。

ローカル開発時には「mailTrap」
本番環境では「さくらサーバ」のSMTPを設定し、疎通確認をしました。

Laravel mailTrapでメール送信テスト 備忘録
https://qiita.com/ryomaDsakamoto/items/e9d3a2c258dbfc66c524

LaravelのSMTPサーバにさくらサーバのSMTPを設定
https://laraweb.net/tutorial/1265/

洗練された『Laravel』のメール送信機能を使ってみる
https://liginc.co.jp/369690

Laravel5.7: 日本語のパスワードリセット用のメールを送信する
https://qiita.com/sutara79/items/0ea48847f5565aacceea


日本語設定

Laravelで日本語設定をする場合は、
ja.jsonへ記述することで設定を適応することができます。

/resources/lang/ja.json
{
    "Click link below and reset password.": "下記のURLにアクセスして、パスワードを再設定してください。",
    "If you did not request a password reset, no further action is required.": "このメールに心当たりがない場合は、このまま削除してください。",
}
blade.php
<p>
    {{ __('Click link below and reset password.') }}<br>
    {{ __('If you did not request a password reset, no further action is required.') }}
</p>

実際の表示
image.png


生成部分

「カテゴリから生成」表示部分の実装

カテゴリプルダウンは「カテゴリ1」に紐づいて「カテゴリ2」の選択肢が変動するようにします。


・カテゴリ1が「歌詞」の場合


・カテゴリ1が「小説」の場合


リレーション

category1.id = category2.parent_id


categori1


categori2


参考

laravel5.1で、カテゴリー・サブカテゴリーのような親子セレクトボックスを作る方法
https://www.messiahworks.com/archives/12202


「カテゴリから生成」処理部分の実装

カテゴリで指定した値を元にStorageで読み込む教師データのパスを設定します。

contoloer.php
$input = $request->input();
$category1  = Arr::get($input, 'category1');
$category2  = Arr::get($input, 'category2');
$path = 'public/constText/';
$path .= $category1 . '/';
$path .= $category2 . '.txt';

constTextの構成
image.png


「ファイルから生成」部分の実装

LaravelのStorage機能を使用し、アップロード処理を実装します。
今回はテキストデータのみに制限するため拡張子を以下のように設定します。
・txt
・csv
・xls
・xlsx

参考
Laravelでファイルをアップロードする方法を詳細解説
https://reffect.co.jp/laravel/how_to_upload_file_in_laravel

LaravelでStorageを使ったファイルおよびディレクトリの操作をまとめてみた
https://qiita.com/t1k2a/items/50081988363cf2fa1bca


「直接入力から生成」部分の実装

「ファイルから生成」は上記のようなフローで実行していますが、
「直接入力から生成」もStorage機能を活用して実行しています。

直接入力から生成フロー
textareaの値をテキストファイルでStorage保存
以下、「ファイルから生成」と同様の処理

サーバエンド

Python

MeCabによる自動生成部分については以下の記事にまとめています。

参考
自動生成キャッチコピー【Python】
https://qiita.com/SyogoSuganoya/items/ba542f686104811e2d6b


PHPからPython実行

Laravelで実装したinput button等の発火イベントで
Pythonを実装できるようにします。

PHPのexec関数を使用し、Pythonを実行します。

参考
ゼロから作るPHPとPythonの連携 on Laravel
https://qiita.com/SwitchBlade/items/96ed4ea425ef2d758f71

PHP - exec()のエラーハンドリングと標準エラー出力の関係をまとめる
https://qiita.com/smd8122/items/65b552f1d53bfb7fad9a


Ajax

基本

Laravel、Ajaxを用いて動的なコメント閲覧画面の作成
https://www.merges.co.jp/archives/1980

LaravelでAjax(jQuery)を使用する
https://pointsandlines.jp/server-side/php/laravel-ajax

Laravel と Ajax で値の受け渡して非同期処理。
https://niwacan.com/1619-laravel-ajax/


生成文章の表示

image.png


生成ボタン押下後の「生成文章」エリアの表示にはAjaxを使用します。
PHPのexec関数の「\$outputs」を生成文章に表示します。
$outputsにはPython実行中のprintした文字列が格納されています

controller.php
exec($command , $outputs, $return_var);

$data = [
    'outputs' => $outputs,
    'return_var' => $return_var,
];
return response()->json($data);
pythonCall.js
var params = {
    headers: {  
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    },
    url: url,
    method: 'post',
    dataType: 'json',
    data: paramData,
    //リクエストが完了するまで実行される
    beforeSend: function(){
        $('h3').text('読み込み中');
        $("input").attr("disabled","true"); 
        $('.wrapper .button').addClass('pushed');
        $('.heart-check').prop('checked', false); //アイテムを全部checkedはずす
    }
};

$.ajax(
    params
).done(function( data ) {
    // 生成文章の初期化
    $('input.sentence').val('');

    // 生成文章の入力
    for(var i = 0; i < data.outputs.length && i < 5; i++){
        $('input.sentence').eq(i).val(data.outputs[i]);
    }
}

お気に入り機能

生成文章のお気に入り登録および
マイページのお気に入り文章の管理
image.png


お気に入り機能はAjaxを使用し、非同期で処理します。

controller.php
// 一覧画面の表示
public function index(Request $request) {

    $posts = Favorite_sentence::where('user_id', $request->user()->id) //$userによる投稿を取得
        ->orderBy('created_at', 'desc') // 投稿作成日が新しい順に並べる
        ->paginate(10); // ページネーション; 

    return view('user.mypage', [
        'posts' => $posts, // $userの書いた記事をviewへ渡す
    ]);
}

// ハートマークのクリック(登録 or 削除)
public function ajaxlike(Request $request) {

    // $user_id = $request->user()->id;
    $user_id = Auth::user()->id;
    $post_id = $request->post_id;
    $sentence = $request->sentence;

    $like = new Favorite_sentence;
    $exist = Favorite_sentence::where('id', $post_id)->get();
    $isExist = $exist->isEmpty();

    if ($isExist) {
        // 空(まだ「いいね」していない)ならlikesテーブルに新しいレコードを作成する
        $like = new Favorite_sentence;
        $like->user_id = $user_id;
        $like->sentence = $sentence;
        $like->save();

        $post_id = $like->id;
        $command = 'insert';

    } else {
        // お気に入りフレーズの存在確認
        Favorite_sentence::findOrFail($post_id);
        // likesテーブルのレコードを削除
        $like = Favorite_sentence::where('id', $post_id)
        ->delete();

        $command = 'delete';
    }

    $data = [
        'user_id' => $user_id,
        'post_id' => $post_id,
        'sentence' => $sentence,
        'command' => $command,
    ];
    //下記の記述でajaxに引数の値を返す
    return response()->json($data);
}
likeSentence.js
var like = $('.heart-label');
var likePostId;
var sentence;

like.on('click', function () {

    var $this = $(this);
    // お気に入り文章ID
    likePostId = $this.parent().parent().find(".sentence").attr('data-postid');
    // お気に入り文章
    sentence = $this.parent().parent().find(".sentence").val();

    // お気に入り文章が空白
    if (!sentence) {
        return;
    }

    $.ajax({
        headers: {
            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        },
        url: '/ajaxlike',
        type: 'POST',
        data: {
            'post_id': likePostId ,
            'sentence': sentence , 
        },
    }).done(function (data) {            
        if(data.command = 'insert') {
            $this.parent().parent().find(".sentence").attr('data-postid', data.post_id);
        }
});

リリース

本番環境では「さくらサーバー」を使用

Python/MeCab環境構築

さくらサーバ・UTF-8に対応したWEBブラウザにMecabで形態素解析した結果を出力する
https://qiita.com/Jshirius/items/ac3ca66a2d5262b98b58

さくら共有サーバーにmecabをインストールしてpythonから呼び出してみる
https://qiita.com/Jshirius/items/3a067486e2a693544c32


MeCabがターミナルからは実行できるが、PHP呼び出しから使えない時…

まずはPythonをフルパスで呼び出してみる

エックスサーバーでphpからexec関数でpythonを呼び出そうとして苦労した話
https://hazukei.com/1259/


site-packagesを追加指定

それでもうまくいかない時は、「site-packages」をターミナル実行とPHP実行で比較

import site
site.USER_SITE

差分を追加し、インストール済みパッケージを実行可能な状態にする

import sys
sys.path.append('vendor\Lib\site-packages')

参考
さくらのレンタルサーバに Python モジュールをインストール
https://emptypage.jp/notes/sakura-python.html

Pythonモジュールのインストール先の確認方法や設定方法を現役エンジニアが解説【初心者向け】
https://techacademy.jp/magazine/46510

Laravel

[0001]さくらのレンタルサーバーにSSHで入りLaravelをインストール
https://www.failibere.com/development_memo/lalavel/0001

さくらサーバでstorageへのシンボリックリンクを張る
https://blog.hiroyuki90.com/articles/laravelで作成したwebアプリをレンタルサーバに公開する/

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