XXШ. - А что, так можно было? - Каждый прозаик жел
[ подробнее см. proza.ru/avtor/yarmosh ]
2. КАЖДЫЙ ПРОЗАИК ЖЕЛАЕТ ЗНАТЬ, ЧТО ВЫБИРАЮТ ЧИТАТЕЛИ
Спешим уточнить, что речь пойдет не о прозаиках как классе. В контексте этой истории прозаиками будем называть авторов, активно пользующихся сайтом proza.ru для поиска и расширения своей читательской аудитории.
Платформа явно заслуживает внимания многих из тех, кому есть что сказать в литературном творчестве, выходящем за рамки блогерства. Несмотря на аскетичный интерфейс, ею легко пользоваться читателям, да и самому автору удобно работать в личном кабинете. Можно ставить как отдельные произведения, так и сборники, по сути имитируя формат книги. Не будем останавливаться на том, почему это важно, ибо вопрос уже подробно разобран нами в учебнике "Таланты являются в книгах". А вот, пожалуй, единственное, чего не хватает платформе - это как-раз инструментов для анализа читательского интереса. Данные, хоть и ограниченные рамками двух недель, есть, но обработать, сделать из них выводы бывает трудновато. Хотя это дело поправимое. Им и займемся.
Для начала посмотрим, как накопленную за две недели информацию о читательских обращениях к творчеству автора взять и, если надо, присоединить к предыдущей, а затем компактно представить в числовом виде, удобном для построения графиков.
Воспользуемся условным примером, поскольку реальные данные обновляются с каждым днем, и увидеть их "завтра" при всем желании невозможно. Зато, с другой стороны, задуманный нами инструмент способен делать анализ всех работ - как своих, так и, к слову, любого из трехсот с лишним тысяч авторов на платформе, благо сбор данных не требует регистрации и постоянно доступен.
Вначале выходим на страницу автора по адресу: proza.ru/avtor/имя_автора . Копируем оттуда полный список произведений вместе с датой постановки и приводим его к формату, показанному ниже. Записываем в файле all.js . Эти данные нужны лишь для того, чтобы правильно группировать публикации, разбитые на главы, а также оценивать интерес к сборникам и книгам в целом.
В нашем примере соберем пять известных книг знаменитого автора, включающие соответственно 12, 11, 13, 16 (плюс Предисловие), 4 рассказа (либо главы), и добавим к ним рассказ "Полосатый сундук", не входящий в сборники:
all=[
['', 'Полосатый сундук', '01.01.2023'],
['Приключения Шерлока Холмса (12 рассказов)',
'Скандал в Богемии', '01.02.2023',
'Союз рыжих', '02.02.2023',
. . .
'Медные буки', '12.02.2023'],
['Записки о Шерлоке Холмсе (11 рассказов)',
'Серебряный', '01.03.2023',
'Жёлтое лицо', '02.03.2023',
. . .
'Последнее дело Холмса', '11.03.2023'],
['Возвращение Шерлока Холмса (13 рассказов)',
'Пустой дом', '01.04.2023',
'Подрядчик из Норвуда', '02.04.2023',
. . .
'Второе пятно', '13.04.2023'],
['Затерянный мир',
'Затерянный мир. Предисловие', '01.05.2023',
'Затерянный мир. Гл. I Всегда есть возможность совершить подвиг',
. . . '02.05.2023',
'Затерянный мир. Гл. XVI Процессия! Процессия!', '17.05.2023'],
['Капитан Шарки',
'Как губернатор Сент-Китта вернулся на родину', '01.06.2023',
'Как капитан Шарки и Стивен Крэддок перехитрили друг друга', '02.06.2023',
'Как Копли Бэнкс прикончил капитана Шарки', '03.06.2023',
'Ошибка капитана Шарки', '04.06.2023']
]
На месте троеточий следует добавить пропущенные ради компактности строки. Обращаем особое внимание, чтобы все кавычки, запятые и квадратные скобки были на местах.
Последний подготовительный шаг - собрать статистику обращений за неделю. Находим ее там же, по ссылке "Читатели". Список разбит на страницы по 20 строк такого вида:
неизвестный читатель 1 Союз рыжих 27.08.2025 15:56 не определен
Просто копируем их блоками по порядку и без изменений в один файл. Добавляем вверху короткую строчку s=` , внизу вторую, с одним только значком ` , и записываем всё это под именем readers.js .
А мы, продолжая свой пример, возьмем некие реальные данные за две недели и просто подставим в них перечисленные выше 58 произведений по дням, для последующего анализа. [...]
Теперь можем приступать собственно к программе. Начнем с того, что приведем всё обилие информации из readers.js к компактной форме, используя данные из файла all.js, чтобы дальше с ними можно было удобно работать. Задача на этом шаге - собрать по каждому дню перечень всех читательских запросов на книги и конкретно рассказы или главы в них, в виде ссылок на их порядковые номера, разделенные точкой. Например, рассказ "Последнее дело Холмса" получает ссылку 2.11, так как это 11-й рассказ из второй книги. Для рассказов, не входящих в сборники, номером книги служит 0, как в случае с "Полосатым сундуком", ссылка на который - 0.1.
Решение задачи, длиной по сути в десяток строк, запишем в файле proza.html:
<script src='readers.js'></script>
<script src='all.js'></script>
<script>
let a=s.split('\n').filter(Boolean), d=[];
for (let i=0; i<a.length; i++) a[i]=[a[i].split(' \t')[1],a[i].split(' \t')[2]];
for (let i=0; i<a.length; i++) if (d.indexOf(a[i][1])<0) d.push(a[i][1]);
for (let day=0; day<d.length; day++) {
let dd=d[day].slice(-2)+d[day].slice(3,5)+d[day].slice(0,2);
let dy=new Date(dd); dd=dy.getDay()+' '+dd;
for (let i=0; i<a.length; i++)
for (let n=0; n<all.length; n++)
if ((all[n]).indexOf(a[i][0].slice(0,-1))>-1 && a[i][1]==d[day])
dd+=' '+n+'.'+((all[n].indexOf(a[i][0].slice(0,-1)))/2+0.5);
d[day]=dd;
} console.log(d);
</script>
Открыв файл в браузере, вызываем консоль клавишей F12: [...].
Легко убедиться, что здесь плотно упакованы все данные, которые нужны для изучения. По каждой дате собран перечень произведений и книг, к которым обращались, и даже порядковый день недели, который приходится на эту дату.
А дальше начинается самое интересное. Пусть теперь программа ответит на те вопросы, ради которых всё это и затевалось. Мы хотим знать для начала:
- распределение частоты обращений ко всем произведениям по дням недели;
- рейтинг произведений по количеству просмотров;
- график изменений читательских интересов со временем.
Воспользуемся пакетом chart.js, который предназначен как раз для построения всевозможных графиков. Загрузим его с адреса: cdnjs.com/libraries/chart.js, и подключим к программе на самом верху одной строкой:
<script src='chart.js'></script>
Сразу под ней разместим три холста для намеченных графиков:
<div style="width: 100%">
<p><canvas id="chart1"></canvas><hr>
<p><canvas id="chart2"></canvas><hr>
<p><canvas id="chart3" height="200"></canvas><br>
</div>
Построение каждого графика состоит из двух шагов - подготовки данных и затем их отображения на холсте. Всё это просто добавляем последовательно к программе.
Не станем уделять внимания оптимизации, поскольку нас сейчас интересует не компактность и эффективность кода (об этом можно позаботиться позже), а стремление скорее увидеть, как будет выглядеть первый результат на экране. Набираем текст:
<script>
//--- Данные первого графика
let wk=[[],[],[],[],[],[],[]], ww=[[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]];
for (let i=0; i<d.length; i++) {
[a,b, ...rest]=d[i].split(' ');
wk[a]=wk[a].concat(rest);
ww[0][a]+=rest.length;
ww[1][a]+=1;
} for (let i=0; i<7; i++) ww[0][i]=ww[0][i]/ww[1][i];
//--- Отображение первого графика
lbl=['Вс','Пн','Вт','Ср','Чт','Пт','Сб'];
let r=[lbl[d[0].split(' ')[0]],lbl[d[d.length-1].split(' ')[0]]];
new Chart(document.getElementById('chart1'), {
type: 'bar',
data: { labels: lbl, datasets: [{ data: ww[0] }] },
options: {
plugins: {
legend: {display: false},
title: {
display: true,
text: "Прочтений в неделю, с "+
r[1]+' '+d[d.length-1].split(' ')[1]+' по '+
r[0]+' '+d[0].split(' ')[1]+' (мм/дд/гг):',
font: {size:16}
}
}
}
});
</script>
Открываем программу в браузере. Вот и график. Анализ оставим на потом, чтобы пока перейти к следующему:
<script>
//--- Данные второго графикa
let v0=[],v1,v2=[],titles=[];
for (let i=0; i<d.length; i++) {
[,, ...rest2]=d[i].split(' ');
v0.push(rest2);
} v0=v0.flat(); v1=[...new Set(v0)].sort();
for (let i=0; i<v1.length; i++) {
v2.push(0); for (let j=0; j<v0.length; j++) if (v1[i]==v0[j]) v2[i]+=1;
}
for (let i=0; i<v1.length; i++) {
let t=v1[i].split('.'); titles.push(all[t[0]][t[1]*2-1]);
}
//--- Отображение второго графикa
new Chart(document.getElementById('chart2'), {
type: 'doughnut',
data: {
labels: titles,
datasets: [{label: 'Прочтений', data: v2, borderWidth: 1}]
},
options: {
cutout: '30%',
plugins: {
legend: {display:true},
title: {
display: true,
text: "Доля каждого произведения из всех прочтений:",
font: {size:16}
}
}
}
});
</script>
Новый яркий и красочный график совсем не похож на предыдущий. Если, взглянув на тот, узнаешь что-то новое о читателях, а именно, какие дни недели они чаще выбирают для знакомства с твоими произведениями, то этот показывает, насколько сами произведения привлекают внимание читательской аудитории. Потому и формат графика другой. Круговая диаграмма отражает долю каждого произведения в суммарном количестве читательских обращений. Чем шире сектор, тем больше прочтений. Притом, несмотря на кажущуюся сложность уловить, где кто и какова их доля, график предельно легко читать. Достаточно навести мышь на любой сектор, чтобы увидеть название работы и сколько прочтений за рассматриваемый период она собрала. Одновременно по размеру сектора сразу понимаешь, как он выглядит на фоне других. Кроме того, щелкая мышью на любом произведении из полного списка над графиком, можно временно убирать его из рассмотрения, оставляя только интересующие, или возвращать обратно. Словом, есть что исследовать.
Третий график - чуть сложнее по структуре данных, и тоже совсем не похож на предыдущие. Здесь меньше обобщений и больше информации, которую нужно подать. Суть в том, чтобы показать, как накапливалось количество просмотров по каждому произведению день за днем. Строим график так:
<script>
//--- Данные третьего графикa
let v3=[], v4=[], v5=[], v6=[], data3=[];
for (let i=0; i<d.length; i++) {
[,dx, ...rest3]=d[i].split(' ');
v3.push(dx); v4.push(rest3);
}
let v3r=v3.reverse(), v4r=v4.reverse();
for (let i=0; i<v4r.length; i++) {
v5.push([]); for (let k=0; k<v1.length; k++) v5[i].push(0);
for (let k=0; k<v4r[i].length; k++) v5[i][v1.indexOf(v4[i][k])]+=1;
if (i>0) for (let k=0; k<v1.length; k++) v5[i][k]+=v5[i-1][k];
}
for (let i=0; i<v1.length; i++) {
v6.push([]); for (let k=0; k<v5.length; k++) v6[i].push(v5[k][i])
}
for (let i=0; i<v1.length; i++)
data3.push({label:titles[i], data:v6[i], borderWidth:1});
//--- Отображение третьего графика
new Chart(document.getElementById('chart3'), {
type: 'line', data: {labels: v3r, datasets: data3},
options: {
plugins: {
legend: {display:true},
title: {
display: true,
text: "Рост числа просмотров произведений по дням:",
font: {size:16}
}
}
}
});
</script>
Тут в нашем примере - пока только 52 произведения из 58, и 14 дней их пребывания на читательской полке. Это 728 точек, которые нужно показать и еще снабдить ярлыками, чтобы при наведении на любую указателя мыши видеть заглавие и числовое значение просмотров. Потому и блок подготовки данных в программе оказался на несколько строк длиннее. Хотя, конечно, его можно существенно оптимизировать.
Как и в случае с предыдущим, на этом графике любое из произведений тоже можно по желанию вычеркивать, то есть убирать из рассмотрения, упрощая таким образом картину для большей наглядности.
Программа на этом закончена, но впереди еще один этап - проверки ее в условиях практического использования.
Спустя почти неделю, мы сняли свежие данные в продолжение статистики прочтений. Специально не стали дожидаться полной недели, а остановились на шести днях, дабы убедиться, что первый график будет верно реагировать на неполные сведения при расчете средних значений. Причем напомним, что всё это не случайные числа, а реальные данные, просто с другими заглавиями и существенно сокращенным количеством произведений, а также со сдвинутой датой начала.
В целом, предыдущие данные были дополнены новым перечнем, тоже в формате, представленном выше, сразу после слов "по 20 строк такого вида" [...].
Результат оказался ожидаемо информативным. Уже первый график заставил присмотреться к изменениям:
- они никак не коснулись Среды; разной величины рост показали ПН (+100%), ВТ (+65%), ВС (+40%), СБ (+25%) и ЧТ (+10%), а вот у Пятницы - даже небольшой спад (-6%)
- в итоге Понедельник стал продуктивней Вторника, а Суббота оказалась с лучшей активностью, чем Пятница;
- хотя Воскресенье сохранило лидерство, его отрыв от ближайших конкурентов заметно сократился.
Особенно наглядно проявляются эти тенденции, если поставить старые и новые данные для сравнения рядом.
Следующий график тоже приготовил сюрпризы. Во-первых, нашлись читатели, которые обратили наконец внимание на оставшиеся шесть произведений, к которым в первые две недели совсем никто не интересовался [...]. Вот почему их не было на предыдущих графиках, но появились сейчас, доведя количество произведений до полных 58.
Во-вторых, сменилась тройка лидеров. Если неделю назад за "Одинокой велосипедисткой" (17 прочтений) с большим отрывом следовали "Случай в интернате" (9) и "Скандал в Богемии" (7), то теперь ее 19 прочтений догоняет "Подрядчик из Норвуда" (11), оставляя позади "Случай в интернате" (10). Эту динамику наглядно отражает третий из графиков, который состоит теперь уже из 58 произведений по 20 датам, то есть имеет 1160 информационных точек.
Конечно, это всего лишь пример. Но взят он из реальности. И такой инструмент любому прозаику (в том значении слова, которое сформулировано в начале рассказа) может оказаться полезным для анализа собственных работ.
Как будут менять складывающуюся картину приходящие свежие данные, какие выводы всякий раз делать дальше, и какие действия предпринимать - каждый будет решать сам.
Свидетельство о публикации №226100800177