Простейший генератор креативного текста
vk f t

Простейший генератор креативного текста

Без ней­ро­се­тей, реги­стра­ции и СМС

Наста­ло вре­мя кру­тых про­ек­тов!

Пред­ставь­те, что вы запус­ка­е­те рас­сыл­ку в круп­ной ком­па­нии, полу­чи­ли уже за это мно­го денег и вам хочет­ся как-то её раз­но­об­ра­зить. И вы реша­е­те сде­лать так, что­бы чело­ве­ку в ответ при­хо­ди­ло письмо-благодарность. Но не одно пись­мо на всех, а несколь­ко раз­ных, чем боль­ше — тем луч­ше.

Мож­но их все напи­сать вруч­ную и потра­тить на это несколь­ко дней. А мож­но напи­сать код, кото­рый сам напи­шет все эти пись­ма. Мы все­гда выби­ра­ем вто­рой путь, даже если это не нуж­но, поэто­му сего­дня мы запро­грам­ми­ру­ем гене­ра­тор тек­ста на JavaScript.

Сра­зу ого­во­рим­ся: вам может пока­зать­ся, что этот гене­ра­тор пло­хо рабо­та­ет и выда­ёт дурац­кие тек­сты. Всё дело в том, что в этом алго­рит­ме важ­но преду­смот­реть все вари­ан­ты состав­ле­ния струк­ту­ры тек­ста и самих пред­ло­же­ний, а потом про­ве­рить, как это всё согла­со­вы­ва­ет­ся меж­ду собой. Чем длин­нее и «живее» нужен текст, тем боль­ше вари­ан­тов под­ста­нов­ки слов нуж­но преду­смот­реть.

Алго­ритм рабо­ты гене­ра­то­ра тек­ста будет такой:

  1. Гото­вим HTML-страницу, где это всё будет рабо­тать и запус­кать­ся.
  2. Зада­ём струк­ту­ру тек­ста на уровне абза­цев: при­вет­ствие, само пись­мо, заклю­че­ние.
  3. Пишем шаб­ло­ны для каж­до­го из этих эле­мен­тов.
  4. Слу­чай­ным обра­зом выби­ра­ем, каким тоном будем общать­ся — офи­ци­аль­ным или нет.
  5. Соби­ра­ем всё пись­мо в одно целое.
  6. Заме­ня­ем шаб­лон­ные сло­ва на нуж­ные фра­зы и сло­во­со­че­та­ния.
  7. Пока­зы­ва­ем резуль­тат.

Делаем HTML-страницу

Берём за осно­ву стан­дарт­ный шаб­лон и добав­ля­ем в него:

Всё это мы уже уме­ем делать, поэто­му про­сто соби­ра­ем код:

    
language: HTML

<!DOCTYPE html>

<html>

 

<!-- служебная часть -->

<head>

 

  <!-- заголовок страницы -->

  <title>Генератор писем</title>

 

  <!-- настраиваем служебную информацию для браузеров -->

  <meta charset="utf-8">

  <meta http-equiv="X-UA-Compatible" content="IE=edge">

  <meta name="viewport" content="width=device-width, initial-scale=1">

 

  <!-- подключаем jQuery -->

  <script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js'></script>

 

  <!-- подключаем наш скрипт -->

  <script  src="mail.js"> </script>

 

  <!-- настраиваем внешний вид блока для готового письма и кнопки -->

  <style type="text/css">

 

    .text{font-size: 20px; width:80%; margin:30px; }

 

    .controls button {font-size: 20px; margin-left: 30px;}

  </style>

 

<!-- закрываем служебную часть страницы -->

</head>

 

<body>

 

  <!-- в этом блоке будем выводить готовое письмо -->

  <div class="text" id="text_here"></div>

 

  <!-- блок с кнопкой, по нажатию на которую запускается нужная функция в скрипте -->

  <div class="controls">

    <button value="Получить новый текст" onclick="get_text();">Получить новый текст</button>

  </div>

 

</body>

 

<!-- конец всей страницы -->

</html>


Ско­пи­ро­вать код
Код ско­пи­ро­ван
Гото­вая стра­ни­ца с кноп­кой. Текст появит­ся на сле­ду­ю­щем эта­пе.

Готовим структуру письма и шаблоны для текста

Теперь нам пона­до­бит­ся отдель­ный файл для скрип­та, кото­рый и будет отве­чать за гене­ра­цию писем — mail.js. Созда­ём его в той же пап­ке, что и HTML-документ, и начи­на­ем про­грам­ми­ро­вать.

Смысл наше­го алго­рит­ма в том, что мы зара­нее опре­де­ля­ем бло­ки тек­ста и поря­док фраз, но слу­чай­ным обра­зом выби­ра­ем, что же будет под­став­лять­ся на место этих бло­ков.

Для это­го мы будем исполь­зо­вать шаб­лон­ные сло­ва, у кото­рых с обе­их сто­рон сто­ят зна­ки дол­ла­ра, напри­мер, $somebody$. Эти шаб­лон­ные сло­ва будут озна­чать для наше­го алго­рит­ма, что на их месте появит­ся какое-то кон­крет­ное сло­во или целое пред­ло­же­ние. Это мы сами реши­ли, что шаб­ло­ны будут рабо­тать со зна­ка­ми дол­ла­ра — мож­но было выбрать и дру­гие зна­ки.

При­мер: зада­дим по шаб­ло­ну пред­ло­же­ние «Я $love$ $you$». Что­бы полу­чи­лась осмыс­лен­ная фра­за, мы долж­ны задать зна­че­ния для обо­их шаб­лон­ных слов. Сде­ла­ем это так:

Если мы попро­сим алго­ритм слу­чай­но заме­нить шаб­лон­ные сло­ва на кон­крет­ные зна­че­ния из спис­ка, то можем полу­чить такие пред­ло­же­ния:

Смот­ри­те, боль­шин­ство пред­ло­же­ний зву­чит нор­маль­но, а послед­нее — не очень. Это не зна­чит, что алго­ритм пло­хой, про­сто мы, когда под­би­ра­ли сло­ва, не слиш­ком поду­ма­ли над их соче­та­ни­ем. Поэто­му основ­ная про­бле­ма таких алго­рит­мов — руч­ная про­вер­ка и согла­со­ва­ние всех слов и кон­струк­ций, кото­рые исполь­зу­ют­ся для под­ста­нов­ки. Чем боль­ше вре­ме­ни это­му посвя­тить, тем более осмыс­лен­ные тек­сты полу­чат­ся у алго­рит­ма.

Что­бы тек­сты полу­ча­лись раз­но­об­раз­ны­ми, мож­но сде­лать так, что­бы шаб­лон выби­рал­ся в зави­си­мо­сти от какой-то пере­мен­ной. Имен­но так мы сде­ла­ем выбор инто­на­ции пись­ма, офи­ци­аль­ную или нефор­маль­ную.

Начало

Вот код, с кото­ро­го начи­на­ет­ся наш скрипт. В нём мы зада­ём шаб­ло­ны нача­ла, тела и кон­цов­ки пись­ма, при­чём каж­дый шаб­лон — в двух вари­ан­тах. Пер­вый отве­ча­ет за фор­маль­ный стиль отве­та, а вто­рой — за нефор­маль­ный. Всё это оформ­ля­ет­ся как мас­си­вы. Если вы не зна­е­те, как с ними рабо­тать — реши­те зада­чу про сейф.

Инте­рес­ный момент — внут­ри мас­си­вов a_text и b_text мы исполь­зо­ва­ли шаб­лон­ное сло­во $somebody$. Алго­ритм сна­ча­ла под­ста­вит пред­ло­же­ние вме­сте с этим шаб­лон­ным сло­вом, а вто­рым про­хо­дом — заме­нит его на кон­крет­ное зна­че­ние.

Все наши мас­си­вы мы объ­еди­ни­ли в один объ­ект с помо­щью фигур­ных ско­бок, что­бы даль­ше с ним рабо­тать как с еди­ным целым. Это поз­во­лит алго­рит­му най­ти всё в одном месте и после­до­ва­тель­но заме­нить все шаб­лон­ные сло­ва на нуж­ные зна­че­ния.

    
language: JavaScript

// шаблон начала письма

var intro = ['$a_intro$','$b_intro$ '];

 

// шаблон тела письма

var text = ['$a_text$','$b_text$'];

 

// шаблон концовки письма

var outro = ['$a_outro$','$b_outro$']; 

 

// задаём набор фраз и слов для всех шаблонов сразу

var text_obj={

 

      //структуру письма пока оставляем пустой

      structure:[

          ''

          ],

 

      // текст для начала

      a_intro:['Здравствуйте.','Добрый день!'],

      b_intro:['Привет!','Хэллоу!','Бонжур!'],

 

      // варианты основного текста

      a_text:['Перед вами — первое письмо в рассылке. Наш $somebody$ рад тому, что вы не прошли мимо подписки, и приглашает вас на нашу выставку, адрес — во вложении.','Меня зовут Михаил Максимов, и я — $somebody$ в этой компании. От лица всех сотрудников я рад приветствовать вас в рядах наших единомышленников.'],

      b_text:['Если ты видишь это письмо, знай — наш $somebody$ здорово постарался для этого. Зато ты теперь сможешь прийти к нам на выставку и убедиться своими глазами в том, о чём мы тебе говорили!','Ты сделал это, а значит, твой $somebody$ будет в восторге! Если нет — дай нам знать, и мы это исправим.'],

 

      // должность 

      somebody:['директор','руководитель','начальник отдела'],

 

      // текст для концовки

      a_outro:['Спасибо, что подписались на нашу рассылку!','Если будут вопросы — пишите.','Если письмо попало к вам по ошибке — проигнорируйте его.'],

      b_outro:['Теперь ты один из нас!','Здорово, что мы теперь — команда!','Рады, что ты с нами! Пиши, если есть что спросить.'],

 

    };


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Теперь мож­но собрать пись­мо в одно целое. Для это­го берём нача­ло, сере­ди­ну и кон­цов­ку, добав­ля­ем HTML-теги и соеди­ня­ем всё в одну стро­ку. Не сто­ит опа­сать­ся того, что всё будет выгля­деть некра­си­во — для это­го мы как раз и добав­ля­ем теги, что­бы они раз­ме­ти­ли наш текст пра­виль­но и кра­си­во.

Мы гово­ри­ли, что сде­ла­ем так, что­бы алго­ритм сам выби­рал, в каком сти­ле сде­лать пись­мо. За это отве­ча­ет пере­мен­ная mood: если она рав­на 0, то стиль будет офи­ци­аль­ным, а если она рав­на 1 — нефор­маль­ным. Что­бы каж­дый раз это чис­ло опре­де­ля­лось слу­чай­ным обра­зом, доба­вим функ­цию, кото­рая воз­вра­ща­ет слу­чай­ное чис­ло в задан­ном диа­па­зоне.

    
language: JavaScript

// генератор случайных чисел в диапазоне от минимального до максимального

function randz(min, max){

  return Math.floor(Math.random() * (max - min + 1)) + min;

}  

 

/ собираем письмо в одно целое

function generate_structure(){ 

 

  // случайным образом определяем тон письма — официальный (0) или неформальный (1)

  var mood = randz(0,1);

 

  // результат помещаем в переменную вместе с тегами

  result = '<h2>' + intro[mood] + '</h1>\n';

  result += '<p>' + text[mood] + '</p>\n';

  result += '<p>' + outro[mood] + '</p>\n';

 

  // возвращаем результат — одну строку с HTML-разметкой

  return result;   

}


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Что­бы было понят­но, что будет про­ис­хо­дить даль­ше в коде, загля­нем немно­го впе­рёд. Алго­ритм будет дей­ство­вать так: возь­мёт струк­ту­ру пись­ма и раз за разом будет нахо­дить все шаб­лон­ные сло­ва со зна­ком дол­ла­ра, нахо­дить нуж­ный мас­сив, отку­да они берут­ся, и под­став­лять их. Так алго­ритм будет рабо­тать до тех пор, пока не закон­чат­ся все шаб­лон­ные сло­ва. Вот как, напри­мер, может выгля­деть наше пись­мо с тега­ми на каж­дом про­хо­де алго­рит­ма.

1-й про­ход:

<h2>$a_intro$</h2> <p>$a_text$</p> <p>$a_outro$</p>

2-й про­ход:

<h2>Здравствуйте.</h2> <p>Перед вами — пер­вое пись­мо в рас­сыл­ке. Наш $somebody$ рад тому, что вы не про­шли мимо под­пис­ки, и при­гла­ша­ет вас на нашу выстав­ку, адрес — во вложении.</p> <p>Спасибо, что под­пи­са­лись на нашу рассылку!</p>

3-й про­ход:

<h2>Здравствуйте.</h2> <p>Перед вами — пер­вое пись­мо в рас­сыл­ке. Наш дирек­тор рад тому, что вы не про­шли мимо под­пис­ки, и при­гла­ша­ет вас на нашу выстав­ку, адрес — во вложении.</p> <p>Спасибо, что под­пи­са­лись на нашу рассылку!</p>

Как видим, алго­ритм сна­ча­ла заме­нил все шаб­лон­ные сло­ва пер­во­го уров­ня, а затем — вто­ро­го уров­ня. Мож­но делать сколь­ко угод­но вло­же­ний — алго­ритм заме­нит их все на нор­маль­ные сло­ва.

Меня­ем шаб­лон­ные сло­ва на текст

Здесь прин­цип рабо­ты такой:

    
language: JavaScript

// убираем знаки доллара после замены шаблонного слова на реальный текст

function parse_keywords(string){

 

    // задаём шаблон поиска таких слов

    pattern = /\$\w+\$/g;

 

    // проверяем, есть ли в строке нужные нам слова

    keyword = string.match(pattern);

 

    // если есть

    if(keyword){

 

        // пока не закончатся все такие слова в строке…

        for (var i = keyword.length - 1; i >= 0; i--) {

 

            // убираем значок доллара

            keyword[i]=keyword[i].replace(/\$/g,'');

        }   

    }   

 

    // возвращаем слово без знаков доллара

    return keyword;

}   

 

// выбираем случайный элемент массива

function randomize (arr){

    return arr[Math.floor(Math.random()*arr.length)];

}   

 

// меняем одно слово на другое

function replace_keyword(source,keyword,variant){

    return(source.replace('$'+keyword+'$',variant));

}   

 

//подставляем случайным образом готовые слова вместо шаблонных слов со знаком доллара

function bake(object){

 

    // переменная, в которой на выходе получится готовый текст

    var result=randomize(object['structure']);

 

    // пока есть шаблонные слова со знаком доллара

    do{

        // выбираем их

        keywords=parse_keywords(result);

 

        // если они точно есть, то

        if(keywords){

 

            // пока они не закончатся

            for (var i = keywords.length - 1; i >= 0; i--) {

 

                // случайным образом подставляем вместо шаблонных слов с долларом слова из наборов

                if(object.hasOwnProperty(keywords[i])){

                    result = replace_keyword(result,keywords[i],randomize(object[keywords[i]]));

                }   

            }   

        }   

    }    while(keywords);

 

  // возвращаем готовый результат

  return result;

}  


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Привязываем скрипт к кнопке и выводим результат

Мы уже про­пи­са­ли в HTML-документе, что по кли­ку будет вызы­вать­ся функ­ция get_text(). Давай­те это запро­грам­ми­ру­ем так, что­бы текст пись­ма сра­зу после сбор­ки появ­лял­ся на экране. Что­бы это сде­лать, исполь­зу­ем jQuery, най­дём блок для выво­да тек­ста text_here и отпра­вим наш текст с HTML-тегами в этот блок.

Бра­у­зер сам рас­по­зна­ет все теги и отфор­ма­ти­ру­ет пись­мо так, как нуж­но нам. Если вы хоти­те дру­гое фор­ма­ти­ро­ва­ние — поме­няй­те теги или про­пи­ши­те в них нуж­ные сти­ли.

    
language: JavaScript

// подставляем текст с тегами в нужне место на странице

function send(text){

    document.getElementById('text_here').innerHTML=text;

}   

 

// что мы делаем по нажатию на кнопку

  function get_text(){

 

    // заводим переменную для структуры текста

    var currentObject = text_obj;

 

    // наполняем структуру текстом с шаблонными словами

    currentObject.structure[0] = generate_structure();

 

    // меняем шаблонные слова на нормальный текст

    result=bake(currentObject);

 

    // выводим результат

    send(result);

}  


Ско­пи­ро­вать код
Код ско­пи­ро­ван
Резуль­тат рабо­ты скрип­та. Похо­же на ответ живо­го чело­ве­ка.
Гото­вый код скрип­та

    
language: JavaScript

// шаблон начала письма

var intro = ['$a_intro$','$b_intro$ '];

 

// шаблон тела письма

var text = ['$a_text$','$b_text$'];

 

// шаблон концовки письма

var outro = ['$a_outro$','$b_outro$']; 

 

// задаём набор фраз и слов для всех шаблонов сразу

var text_obj={

 

      //структуру письма пока оставляем пустой

      structure:[

          ''

          ],

 

      // текст для начала

      a_intro:['Здравствуйте.','Добрый день!'],

      b_intro:['Привет!','Хэллоу!','Бонжур!'],

 

      // варианты основного текста

      a_text:['Перед вами — первое письмо в рассылке. Наш $somebody$ рад тому, что вы не прошли мимо подписки, и приглашает вас на нашу выставку, адрес — во вложении.','Меня зовут Михаил Максимов, и я — $somebody$ в этой компании. От лица всех сотрудников я рад приветствовать вас в рядах наших единомышленников.'],

      b_text:['Если ты видишь это письмо, знай — наш $somebody$ здорово постарался для этого. Зато ты теперь сможешь прийти к нам на выставку и убедиться своими глазами в том, о чём мы тебе говорили!','Ты сделал это, а значит, твой $somebody$ будет в восторге! Если нет — дай нам знать, и мы это исправим.'],

 

      // должность 

      somebody:['директор','руководитель','начальник отдела'],

 

      // текст для концовки

      a_outro:['Спасибо, что подписались на нашу рассылку!','Если будут вопросы — пишите.','Если письмо попало к вам по ошибке — проигнорируйте его.'],

      b_outro:['Теперь ты один из нас!','Здорово, что мы теперь — команда!','Рады, что ты с нами! Пиши, если есть что спросить.'],

 

    }   ;

 

// убираем знаки доллара после замены шаблонного слова на реальный текст

function parse_keywords(string){

 

    // задаём шаблон поиска таких слов

    pattern = /\$\w+\$/g;

 

    // проверяем, есть ли в строке нужные нам слова

    keyword = string.match(pattern);

 

    // если есть

    if(keyword){

 

        // пока не закончатся все такие слова в строке…

        for (var i = keyword.length - 1; i >= 0; i--) {

 

            // убираем значок доллара

            keyword[i]=keyword[i].replace(/\$/g,'');

        }   

    }   

 

    // возвращаем слово без знаков доллара

    return keyword;

}   

 

// генератор случайных чисел в диапазоне от минимального до максимального

function randz(min, max){

  return Math.floor(Math.random() * (max - min + 1)) + min;

}   

 

// выбираем случайный элемент массива

function randomize (arr){

    return arr[Math.floor(Math.random()*arr.length)];

}   

 

// меняем одно слово на другое

function replace_keyword(source,keyword,variant){

    return(source.replace('$'+keyword+'$',variant));

}   

 

//подставляем случайным образом готовые слова вместо шаблонных слов со знаком доллара

function bake(object){

 

    // переменная, в которой на выходе получится готовый текст

    var result=randomize(object['structure']);

 

    // пока есть шаблонные слова со знаком доллара

    do{

        // выбираем их

        keywords=parse_keywords(result);

 

        // если они точно есть, то

        if(keywords){

 

            // пока они не закончатся

            for (var i = keywords.length - 1; i >= 0; i--) {

 

                // случайным образом подставляем вместо шаблонных слов с долларом слова из наборов

                if(object.hasOwnProperty(keywords[i])){

                    result = replace_keyword(result,keywords[i],randomize(object[keywords[i]]));

                }   

            }   

        }   

    }    while(keywords);

 

  // возвращаем готовый результат

  return result;

}   

 

// собираем письмо в одно целое

function generate_structure(){

 

  // случайным образом определяем тон письма — официальный (0) или неформальный (1)

  var mood = randz(0,1);

 

  // результат помещаем в переменную вместе с тегами

  result = '<h2>' + intro[mood] + '</h1>\n';

  result += '<p>' + text[mood] + '</p>\n';

  result += '<p>' + outro[mood] + '</p>\n';

 

  // возвращаем результат — одну строку с HTML-разметкой

  return result;   

}   

 

// подставляем текст с тегами в нужне место на странице

function send(text){

    document.getElementById('text_here').innerHTML=text;

}   

 

// что мы делаем по нажатию на кнопку

  function get_text(){

 

    // заводим переменную для структуры текста

    var currentObject = text_obj;

 

    // наполняем структуру текстом с шаблонными словами

    currentObject.structure[0] = generate_structure();

 

    // меняем шаблонные слова на нормальный текст

    result=bake(currentObject);

 

    // выводим результат

    send(result);

}  


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Что дальше

На самом деле воз­мож­но­сти это­го скрип­та почти без­гра­нич­ны: при долж­ной усид­чи­во­сти и зна­нии рус­ско­го язы­ка мож­но заста­вить этот скрипт выда­вать осмыс­лен­ный текст любой дли­ны.

Напри­мер, мож­но гене­ри­ро­вать отве­ты служ­бы под­держ­ки, сооб­ще­ния в чат-ботах, под­вод­ки для ста­тей или созда­вать резю­ме. Этот скрипт — убий­ца копи­рай­те­ров, пото­му что он дела­ет за них всю основ­ную рабо­ту. Вам оста­ёт­ся толь­ко прой­ти по тек­сту и убрать шеро­хо­ва­то­сти.

Кста­ти, в одной редак­ции (не в нашей) такой алго­ритм несколь­ко меся­цев гене­ри­ро­вал ста­тьи, и никто ниче­го не заме­тил. Чита­те­лям нра­ви­лось. Сов­па­де­ние?

Ещё по теме