Traffic Cardinal Traffic Cardinal написал 27.02.2023

Анализ конкурентов в Telegram Ads: автоматизируем рутину (ч. 2)

Traffic Cardinal Traffic Cardinal написал 27.02.2023
18 мин
0
1916
Содержание

Две недели назад овнер Profit Agency, CEO GXT и ведущая собственных авторских подкастов «Будет хуже»Маша Дорвей, поделилась с комьюнити крутым лайфхаком, позволяющим подсмотреть рекламу конкурентов в Telegram Ads. Учитывая, что каких-либо публичных спай-сервисов для Телеги до этого не существовало — предложенная идея существенно упрощает жизнь.

banner banner

Но есть одно «но»

Однако используемый в лайфхаке Маши сервис tgstat.ru изначально не задумывался как спай, а потому при его использовании очень много времени уходит на «работу ручками». Мы связались с представителями tgstat.ru и расспросили их о про сбор интересующей нас информации по API. К сожалению, ответ нас не удовлетворил.

Поэтому мы решили «изобрести велосипед» и автоматизировать сбор инфы о креативах конкурентов самостоятельно. Сразу предупреждаем: «колеса у велосипеда кривые», но мы и не программисты. Главное — «ехать можно». Скрипт автоматизирует действия «ручками», а значит — экономит время. А что еще нужно-то?

Для лучшего понимания процесса, ниже мы в деталях расписали алгоритм скрипта. Тем, кто «может в код», по большому счету это ни к чему — там ничего сложного. Можете прокрутить до раздела «исходный код». Но если же вы такой же «не программист», как и мы — советуем ознакомиться, чтобы понимать принцип работы.

Принцип работы скрипта

Каких-либо специальных методов API для вывода инфы о креативах у tgstat.ru нет. Во всяком случае в публичном доступе (даже для самых крутых тарифов). Однако сама информация на их сайте выводится. Минимальный диапазон времени — час. Проще говоря, tgstat.ru позволяет видеть ежечасный ответ о закупах рекламы.

Каждый «час» нужно «открывать ручками», что не очень удобно
Каждый «час» нужно «открывать ручками», что не очень удобно

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

Дальше все просто:

  1. Мы берем общий url.
  2. Подставляем в него исследуемый канал.
  3. Подставляем «стартовое» время.
  4. Подставляем «конечное» время.
  5. Засовываем все это в цикл, изменяющий «цифры ссылки» (время и дату) с шагом 1 час.
  6. Записываем собранную инфу на каждом шаге.
  7. Ждем завершения цикла.
  8. Фильтруем совпадения.
  9. Выводим собранную инфу.

Если вы совсем далеки от темы, но очень хотите автоматизировать спаинг, — покажите это ТЗ любому фрилансеру-программисту. Это простейший скрипт, с которым справится даже школьник, если он обладает базовыми знаниями программирования. Спросите тех, кто в теме, — они не дадут соврать. Впрочем, перейдем к коду.

Все уникальные креативы за период 20.02.23–23.02.23 включительно
Все уникальные креативы за период 20.02.23–23.02.23 включительно

Исходный код

Так как наши читатели обладают разными уровнями знаний и разными финансовыми возможностями, — мы решили написать наиболее универсальный вариант, не требующий затрат на аренду сервера. Увы, большинство бесплатных хостингов не подойдут для этой задачи, так как у них лимитировано процессорное время.

Поэтому сделаем сервер на своем ПК! Да-да, ребят, — Denwer :) Почему он? Потому что те, кто в теме, все равно сделают по-своему, им главное — понять алгоритм. А тем, кто не в теме, разобраться с Denwer будет значительно проще, чем с любым другим сервером.

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

  1. Переходим в C:\WebServers\home\localhost\www\
  2. Создаем папку с любым название на английском (желательно без символов). Например — tgstats.
  1. Открываем директорию C:\WebServers\home\localhost\www\tgstats (либо ваше название папки вместо tgstats).
  2. Создаем в ней файл index.php (убедитесь, что у вас отображаются расширения файлов).
  1. Открываем его блокнотом.
  2. Вводим в него следующий код:

<?php

$channel = $_POST['channel'];

$date_start = $_POST['date_start'];

$date_end = $_POST['date_end'];

$timezone = $_POST['timezone'];

$logdate1 = strtotime($date_start);

$logdate2 = strtotime($date_end);

$logdate1=date("d.m.y", $logdate1);

$logdate2=date("d.m.y", $logdate2);

$filename=$channel."-".$logdate1."-".$logdate2.".txt";

$filename = str_replace(' ', '', $filename);

if (!file_exists("logs")) {

mkdir("logs");

}

if (file_exists("logs/-01.01.70-01.01.70.txt")) {

unlink("logs/01.01.70-01.01.70.txt");

}

if (!file_exists("test.bat")) {

$fp = fopen("test.bat", "w");

fwrite($fp, '"C:\Program Files\Google\Chrome\Application\chrome.exe" "http://127.0.0.1/tgstats/index.php"');

fclose($fp);}

if($_POST["clear"]=="clear") {

$fp = fopen("status.txt", "w");

fwrite($fp, "2");

fclose($fp);}

echo iconv("utf-8", "windows-1251", '

<form action="index.php" method="post">


<p><input type="submit" value="Сбросить кэш"></p>

</form>')

;

if (file_exists("status.txt")) {

if($_POST['logclear']=="go") {

$fp = fopen("status.txt", "w");

fwrite($fp, "3");

fclose($fp);

$file3 = fopen("logs/$filename","w");

fwrite($file3,"");

fclose($file3);

}

$status = file("status.txt");

$status = str_replace(' ', '', $status);

if ($status[0] != 3) {

$file = fopen("cache.txt","w");

fwrite($file,"$channel\n$date_start\n$date_end\n$timezone");

fclose($file);

$date_new = $date_start;

$date_new = strtotime($date_new);

$timezonestamp = $timezone*3600;

$date_new = $date_new+$timezonestamp;

$file2 = fopen("test.txt","w");

fwrite($file2,"$date_new");

fclose($file2);

$arr = file("cache.txt");

$channel = $arr[0];

$date_start = $arr[1];

$date_end = $arr[2];

$timezone = $arr[3];

$start="Задать";

$start_text="Задать параметры";

echo iconv("utf-8", "windows-1251", '

<form action="index.php" method="post">

<p><red><b>*Обратите внимание! Для корректной работы скрипта необходимо придерживаться установленного формата ввода данных.</b></red></p>

<p>Название канала:<input name="channel" placeholder="trafficcardinal" value="'.$channel.'"/></p>

<p>Начальная дата:<input name="date_start" placeholder="2023-02-20 00:00:00" value="'.$date_start.'"/></p>

<p>Конечная дата:<input name="date_end" placeholder="2023-02-23 23:00:00" value="'.$date_end.'"/></p>

<p>Часовой пояс:<input name="timezone" placeholder="+3" value="'.$timezone.'"/></p>


');

if ($logdate1 != "01.01.70" and $logdate2 != "01.01.70"){

if (file_exists("logs/$filename")) {

echo iconv("utf-8", "windows-1251", 'Анализ по такому запросу уже производился: ');

echo '<br>';

echo '<a href="index.php?someValue='.$filename.'">'.$filename.'</a>';

echo '<br>';

}

$start="Начать сканирование";

$start_text="Начать";

echo iconv("utf-8", "windows-1251", '

<p><b>Подтвердить (*обязательно для начала сканирования):</b> <input type="checkbox" name="logclear" value="go">

');

} echo iconv("utf-8", "windows-1251", '

<p>'.$start_text.': <input type="submit" value="'.$start.'"></p>

</form>');

echo iconv("utf-8", "windows-1251", '

<form action="index.php" method="post">

<p><b>Показать историю сканирования:</b> <input type="checkbox" name="show" value="show">

<p><input type="submit" value="Показать"></p>

</form>

');

if($_POST["show"]=="show") {

$logs = scandir('logs/');

echo iconv("utf-8", "windows-1251", '<b>История сканирования:</b>');

echo '<br>';

foreach ($logs as $log) {

echo '<a href="index.php?someValue='.$log.'">'.$log.'</a>';

echo '<br>';

}

}

$someValue = $_GET['someValue'];

if (isset($someValue)) {

$filename=$someValue;

$arr = file("logs/$filename");

$arr = preg_replace('/\s+/', ' ', $arr);

$arr = preg_replace('/Пост[[:digit:]][[:digit:]] /', '', $arr);

$arr = preg_replace('/Пост[[:digit:]] /', '', $arr);

$arr = str_replace('------------------------------------', '', $arr);

while (in_array(' ',$arr)) {

$arr = str_replace(' ', ' ', $arr);

}

$count = count($arr);

$arr2=array_unique($arr,SORT_REGULAR);

$count2 = count($arr2);

$creo_log=substr($filename,0,-4);

array_unshift($arr2,"Креативы $creo_log\r\n");

$arr3=array_unique($arr2,SORT_REGULAR);

$count3 = count($arr3);

print "\r\n";

for ($i=0; $i<=$count3;){

echo nl2br(urldecode(iconv("utf-8", "windows-1251", $arr3[$i])));

echo "<br>";

print "\r\n";

$i=$i+1;

}

$fp = fopen("status.txt", "w");

fwrite($fp, "2");

fclose($fp);

}

}

elseif ($status[0] == 3) {

$arrz = file("cache.txt");

$arrz = preg_replace('/\s+/', '', $arrz);

$channel = $arrz[0];

$channel = str_replace(' ', '', $channel);

$date_start = $arrz[1];

$date_start = str_replace(' ', '', $date_start);

$date_end = $arrz[2];

$date_end = str_replace(' ', '', $date_end);

$timezone = $arrz[3];

$timezone = str_replace(' ', '', $timezone);

$microtime = microtime(true);

$date_start = strtotime($date_start);

$date_end = strtotime($date_end);

$date_new = htmlentities(file_get_contents("test.txt"));

$logdate1=date("d.m.y", $date_start);

$logdate2=date("d.m.y", $date_end);

$filename=$channel."-".$logdate1."-".$logdate2.".txt";

$filename = str_replace(' ', '', $filename);

if ($date_new<=$date_end){

$fp = fopen("logs/$filename", "a");

$datestamp2=date("d.m.y", $date_new);

fwrite($fp, " \r\n [".$datestamp2."] \r\n ");

fclose($fp);

$pattern = '/\s*<div class="font-14 mt-1 text-dark">\s*<\/div>\s*/im';

$date1 = htmlentities(file_get_contents("test.txt"));

$date1 = $date1+(-1*$timezone);

$date2 = $date1+82800;

sleep(1);

$i=0;

for ($date = $date1; $date<=$date2;){

$fp = fopen("logs/$filename", "a");

fwrite($fp,"Пост".$i);

fclose($fp);

$datestamp=date("ymdHs", $date);

$data = file_get_contents("http://tgstatsat.ru/channel/".$channel."/stat/sp-messages-details?timecode=".$datestamp);

preg_match_all('#<div class="font-14 mt-1 text-dark">(.+?)</div>#is', $data, $arr);

$count = count($arr[0]);

$j=0;

for ($j = 0; $j <= $count; $j++) {

$arr[0][$j]=strip_tags($arr[0][$j]);

$arr[0][$j] = str_replace(' ', "", $arr[0][$j]);

$fp = fopen("logs/$filename", "a");

fwrite($fp, $arr[0][$j]);

fclose($fp);

}

$fp = fopen("logs/$filename", "a");

fwrite($fp, "\r\n ------------------------------------ \r\n");

fclose($fp);

$date=$date+3600;

$i=$i+1;

}

$date_new=$date_new+86400;

$fp2 = fopen("test.txt", "w");

fwrite($fp2, $date_new);

fclose($fp2);

}

sleep(5);

if ($date_new<$date_end){

exec('cmd /c C:\WebServers\home\localhost\www\tgstats\test.bat');

echo '<script>window.close()</script>';

}

else {

$arr = file("logs/$filename");

$arr = preg_replace('/\s+/', ' ', $arr);

$arr = preg_replace('/Пост[[:digit:]][[:digit:]] /', '', $arr);

$arr = preg_replace('/Пост[[:digit:]] /', '', $arr);

$arr = str_replace('------------------------------------', '', $arr);

while (in_array(' ',$arr)) {

$arr = str_replace(' ', ' ', $arr);

}

$count = count($arr);

$arr2=array_unique($arr,SORT_REGULAR);

print "\r\n";

$count2 = count($arr2);

print "\r\n";

$creo_log=substr($filename,0,-4);

array_unshift($arr2,"Креативы $creo_log\r\n");

$arr3=array_unique($arr2,SORT_REGULAR);

$count3 = count($arr3);

print "\r\n";

for ($i=0; $i<=$count3;){

echo nl2br(urldecode(iconv("utf-8", "windows-1251", $arr3[$i])));

echo "<br>";

print "\r\n";

$i=$i+1;

}

$fp = fopen("status.txt", "w");

fwrite($fp, "2");

fclose($fp);

}

}

}

else{

$fp = fopen("status.txt", "w");

fwrite($fp, "2");

fclose($fp);

;

}

?>

  1. Сохраняем файл.
  2. Запускаем Denwer с ярлыка на рабочем столе.
  1. Открываем браузер.
  2. Вводим в адресную строку http://127.0.0.1/tgstats/ (либо ваше название папки вместо tgstats).
  3. Жмем «Сбросить кеш».
  1. Указываем интересующий нас канал.
  2. Указываем «стартовую» дату исследования.
  3. Указываем «конечное» время исследования.
  4. Указываем часовой пояс.
  1. Запускаем скрипт.
  1. Изучаем чужие креативы :)

Как это работает — наглядная инструкция

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

В рабочей директории будут созданы следующие файлы
В рабочей директории будут созданы следующие файлы

После сброса кеша появится форма для ввода данных
После сброса кеша появится форма для ввода данных

В рабочей директории появится еще несколько файлов
В рабочей директории появится еще несколько файлов

Убедитесь, что поля заполнены реальным текстом, а не демонстрационным
Убедитесь, что поля заполнены реальным текстом, а не демонстрационным

Проверьте правильность ввода данных и нажмите «Задать»
Проверьте правильность ввода данных и нажмите «Задать»

Если все данные введены корректно, после нажатия «Задать» у вас появится чекбокс «Подтвердить» и кнопка «Начать сканирование»
Если все данные введены корректно, после нажатия «Задать» у вас появится чекбокс «Подтвердить» и кнопка «Начать сканирование»

Пример: через «30 сек х кол-во анализируемых дней» скрипт завершит работу.  Если все отработало корректно — у вас останутся открытыми две вкладки
Пример: через «30 сек х кол-во анализируемых дней» скрипт завершит работу. Если все отработало корректно — у вас останутся открытыми две вкладки

Вы можете просмотреть все, когда-либо отсканированные вами диапазоны дат. Названия каналов перечисляются по алфавиту
Вы можете просмотреть все, когда-либо отсканированные вами диапазоны дат. Названия каналов перечисляются по алфавиту

На момент создания скриншота — было проведено лишь одно исследование
На момент создания скриншота — было проведено лишь одно исследование

Нажав на ссылку из скрина выше, — мы инициируем вывод отчета
Нажав на ссылку из скрина выше, — мы инициируем вывод отчета

После проведения еще одного исследования оно также стало отображаться в истории
После проведения еще одного исследования оно также стало отображаться в истории

Так как второе исследование включает в себя более ранний временной период — креативов в отчете меньше (на тот момент мы использовали лишь 2)
Так как второе исследование включает в себя более ранний временной период — креативов в отчете меньше (на тот момент мы использовали лишь 2)

При вводе параметров, которые использовались ранее, скрип оповестит вас о наличии соответствующего отчета. При этом «проанализировать еще раз» никто не запрещает. Правда смысл в этом есть лишь в том случае, если при работе скрипта возникла ошибка. В противном случае вы получите тот же результат, что и ранее
При вводе параметров, которые использовались ранее, скрип оповестит вас о наличии соответствующего отчета. При этом «проанализировать еще раз» никто не запрещает. Правда смысл в этом есть лишь в том случае, если при работе скрипта возникла ошибка. В противном случае вы получите тот же результат, что и ранее

Почему «колеса кривые» и чем это чревато

Будет правильно заранее расписать возможные проблемы для тех, кто не особо понимает, что только что сделал. Итак:

  • Во-первых, раз у TGStat нет API под эту задачу, значит, они не хотят, чтобы пользователи могли так делать. Не хотят — это не обязательно «против», это может быть и «вообще не думали об этом». Но, может, и «против». В последнем случае, если фича станет использоваться массово — ее могут прикрыть и придется искать другой способ автоматизации. Так что критически важные процессы на этом лайфхаке не завязывайте.

  • Во-вторых, мы не тестили работоспособность скрипта под реально высокой нагрузкой. Но в этом и нет нужды — при высокой нагрузке (если вы будете мониторить несколько десятков или сотен каналов одновременно) сервер TGStat гарантированно «отключит вас» от себя. Соответственно, использование VPN — неизбежно.

  • Ну и в-третьих, очевидно, что скрипту не хватает «ситуативной функциональности». Скорее всего, кто-то захочет вывести инфу в других диапазонах, кому-то будет достаточно ежедневного отчета, а не ежечасного, а кому-то может банально хотеться «красоты». В общем, предложенное нами решение — это база. А уж «навесы» на все случаи жизни — сами :)

Немного полезной инфы

При работе со скриптом учитывайте следующие нюансы:

  • 1 день — это ~30 сек. работы скрипта. Соответственно, стата за год будет собираться около трех часов (это излечимо).

  • Для удобства лимит обработки сервера был увеличен с 30 до 300 сек.

  • Скрипт не зависит от лимитов обработки сервера и/или браузера.

  • TGStat обязательно вас забанит — используйте VPN при работе.

  • В скрипте заложена возможность использования нового ip-адреса на каждый анализируемый день.

  • Используемая папка — tgstats. Если решите поместить скрипт в другую — замените ее в коде.

  • Используемый браузер — Google Chrome. Если решите поместить скрипт в другой — замените его в коде.

  • Используемые кодировки для вывода данных — "utf-8", "windows-1251". Если видите «кракозябры», — измените кодировки.

  • Даты в истории сканирования привязаны к первому использованию креатива. Однако если он использовался до указанного вами диапазона времени, — скрипт этого не узнает.

  • В скрипте не используются функции, т. к. он создавался с расчетом на «ковыряние» в нем далеких от программирования пользователей. Но никто не запрещает вам «загнать быдлокод» в функции для удобства.

  • Редактировать исходный код удобнее в notepad++ либо соответствующей среде разработки на php.

Ссылка на исходный код

Скачать исходный код скрипта.

Подводя итоги

Надеемся, наш скрипт поможет вам автоматизировать монотонное «тыканье» мышкой и вы сможете анализировать креативы конкурентов без пустой траты времени. Будем рады фидбэку по реализации от тех, кто «в теме», и пожеланиям по функциональности от тех, кто «не в теме». Тратьте свое время с умом, друзья!

Здравствуйте! У вас включен блокировщик рекламы, часть сайта не будет работать!