👆Иногда есть необходимость получить данные, которые находятся довольно глубоко. Для этого лучше использовать XPath запросы.
#ZennoPoster,#Xpath
#ZennoPoster,#Xpath
👆 Одна из ситуаций, когда при парсинге Json , получили ❗️исключение❗️. Поэтому, как выход, скрипт пытается найти необходимое значение и заменить его самостоятельно.
#ZennoPoster,#Xpath,#Json
#ZennoPoster,#Xpath,#Json
В группе будут публиковаться различные посты, которые будут связаны с программным комплексом ZennoPoster.
Он используется мною очень часто т.к. помогает решить, большое кол-во задач связанных с автоматизацией, которые ведутся через браузер.
Самое главное его преимущество, что у него очень большое сообщество и его постоянно совершенствуют.
#ZennoPoster
Он используется мною очень часто т.к. помогает решить, большое кол-во задач связанных с автоматизацией, которые ведутся через браузер.
Самое главное его преимущество, что у него очень большое сообщество и его постоянно совершенствуют.
#ZennoPoster
После того, как нашли необходимый тег, получаем более детальную информацию в свойствах элемента.
В своей практике использую очень часто Xpath и Linq запросы, которые помогают более точно найти и обработать необходимые элементы.
#ZennoPoster
В своей практике использую очень часто Xpath и Linq запросы, которые помогают более точно найти и обработать необходимые элементы.
#ZennoPoster
Продолжаем знакомство с программным комплексом ZennoPoster.
В примере показано:
- работа в многопоточном режиме
- чтение *.txt файлов
- сохранение содержимого *.txt файла в таблицу
- чтение и запись данных в таблицу
- конвертирование таблицы в список
- сохранение списка в *.txt файл
1. Получаем таблицу по имени созданную в проекте ZennoProject используя интерфейс IZennoTable
2. Инициализируем новый список класса List<T>
3. Сохраняем в переменную "путь нашего файла", с которым работаем
4. FileLocker - это созданный нами объект синхронизации в общем коде ZennoProject, расположенный в классе CommonCode.
4.1. Обязательно лочим наш поток(для того, чтобы другие
потоки не имели доступа к файлу),
4.2. Проверяем существование нашего файла, чистим таблицу
и инициализируем переменные.
4.3. Читаем файл используя класс StreamReader,который
позволяет работать с файлом как хранилищем символов, и
такой подход более эффективен.
4.4. Добавляем наши строки из файла в таблицу.
4.5. В цикле проверяем строки из таблицы и если выполняются необходимые условия, то сохраняем значения в переменные проекта.
4.6. Переносим строки из таблицы в список, для того, чтобы
сохранить их в файл(использую Linq запрос).
4.7. Сохраняем строки списка в файл используя класс
StreamWriter
Скриншот кода в проекте.
#ZennoPoster, #Сниппеты
В примере показано:
- работа в многопоточном режиме
- чтение *.txt файлов
- сохранение содержимого *.txt файла в таблицу
- чтение и запись данных в таблицу
- конвертирование таблицы в список
- сохранение списка в *.txt файл
1. Получаем таблицу по имени созданную в проекте ZennoProject используя интерфейс IZennoTable
var sourceTable = project.Tables["Accounts"];
2. Инициализируем новый список класса List<T>
var sourceListFromTask = new List<string>();
3. Сохраняем в переменную "путь нашего файла", с которым работаем
string pathFile = Path.Combine(project.Directory, "account.txt");
4. FileLocker - это созданный нами объект синхронизации в общем коде ZennoProject, расположенный в классе CommonCode.
public static object FileLocker = new object();
4.1. Обязательно лочим наш поток(для того, чтобы другие
потоки не имели доступа к файлу),
lock (CommonCode.FileLocker)
{
4.2. Проверяем существование нашего файла, чистим таблицу
и инициализируем переменные.
if (File.Exists(pathFile))
{
sourceTable.Clear();
String line;
bool insertLine = true;
4.3. Читаем файл используя класс StreamReader,который
позволяет работать с файлом как хранилищем символов, и
такой подход более эффективен.
using (StreamReader sr = new StreamReader(@pathFile, Encoding.UTF8))
while ((line = sr.ReadLine()) != null)
4.4. Добавляем наши строки из файла в таблицу.
sourceTable.AddRow(line);
4.5. В цикле проверяем строки из таблицы и если выполняются необходимые условия, то сохраняем значения в переменные проекта.
for (int indexOfRow = 0; indexOfRow < sourceTable.RowCount; indexOfRow++)
{
string value = sourceTable.GetCell("C", indexOfRow).Trim();
if (string.IsNullOrEmpty(value) && insertLine)
{
project.Variables["emailAcc"].Value = sourceTable.GetCell("A", indexOfRow).Trim();
project.Variables["passAcc"].Value = sourceTable.GetCell("B", indexOfRow).Trim();
sourceTable.SetCell("C", indexOfRow, "Checking");
insertLine = false;
}
}
4.6. Переносим строки из таблицы в список, для того, чтобы
сохранить их в файл(использую Linq запрос).
int column = 0;
Enumerable.Range(0, sourceTable.RowCount).ToList().ForEach(i => sourceListFromTask.Add(String.Join(":", sourceTable.GetRow(i))));
4.7. Сохраняем строки списка в файл используя класс
StreamWriter
using (StreamWriter sw = new StreamWriter(pathFile, false, Encoding.UTF8))
{
sw.WriteLine(string.Join("\r\n", sourceListFromTask));
}
}
}
Скриншот кода в проекте.
#ZennoPoster, #Сниппеты
Работа со временем и датами - это одна из тех задач, которую необходимо делать в программирование очень часто. Ведь актуальность данных это, то на чём держится современный мир(ушёл от темы).
Мы также не будем отставать и будем работать со временем.
Задача: рассчитать среднее кол-во времени размещение постов в группе(наш случай) согласно сервиса telemetr.me .
Работаем в программном комплексе ZennoPoster, который отлично справляется с анализом структурой страницы.
1. Для того, чтобы получить все "времена длительности"(назовём это так), то мы должны понять в каком из тегов они находятся т.е. подготовить предварительные данные.
Из структуры страница сайта, мы понимаем, что вся нужная информация находится в одном главном для нас теге "tr". Находим его.
1.1. Обращаемся к свойству('ActiveTab') объекта('instance') и передаём полученную информацию в класс('Tab').
instance - это объект, который позволяет получать информацию, которая находится в запущенном браузере(это очень грубое сравнение), но можно рассматривать и так.
Tab - это класс, который имеет свойства для работы с текущей вкладкой нашего браузера.
1.2. Получаем Все необходимые элементы, которые находятся в текущей вкладке нашего браузера, с помощью XPath запроса и передаём в класс('HtmlElementCollection' - который работает с группой элементов).
1.3. Если кол-во найденных элементов ('tr'), больше 0, то идём дальше.
1.4. Инициализируем переменные.
1.5. Проходим в цикле по всем свойствам('InnerHtml'), полученных тегов tr, в которых и расположена нужная информация.
1.6. ОБЯЗАТЕЛЬНО весь наш последующий
код должен быть расположен в
конструкции(try..catch), для того, чтобы при
возникновение ошибок, код понимал,
что делать в этом случае.
1.7. Получаем информацию с необходимого тега('span' с названием класса 'kt-font-brand'), с помощью XPath запроса, используя метод ParseByXpath и сохраняем полученные данные в список.
1.8. Отправляем ошибку в лог ZennoPoster.
Продолжение следует...
#ZennoPoster, #Дата
Мы также не будем отставать и будем работать со временем.
Задача: рассчитать среднее кол-во времени размещение постов в группе(наш случай) согласно сервиса telemetr.me .
Работаем в программном комплексе ZennoPoster, который отлично справляется с анализом структурой страницы.
1. Для того, чтобы получить все "времена длительности"(назовём это так), то мы должны понять в каком из тегов они находятся т.е. подготовить предварительные данные.
Из структуры страница сайта, мы понимаем, что вся нужная информация находится в одном главном для нас теге "tr". Находим его.
1.1. Обращаемся к свойству('ActiveTab') объекта('instance') и передаём полученную информацию в класс('Tab').
Tab tab = instance.ActiveTab;
instance - это объект, который позволяет получать информацию, которая находится в запущенном браузере(это очень грубое сравнение), но можно рассматривать и так.
Tab - это класс, который имеет свойства для работы с текущей вкладкой нашего браузера.
1.2. Получаем Все необходимые элементы, которые находятся в текущей вкладке нашего браузера, с помощью XPath запроса и передаём в класс('HtmlElementCollection' - который работает с группой элементов).
HtmlElementCollection entries = tab.FindElementsByXPath("//tr");
1.3. Если кол-во найденных элементов ('tr'), больше 0, то идём дальше.
1.4. Инициализируем переменные.
var lstTemp = new List<string>();
var totalTimePublicPostAdvertise = string.Empty;
var content = string.Empty;
if (entries.Count > 0)
{
1.5. Проходим в цикле по всем свойствам('InnerHtml'), полученных тегов tr, в которых и расположена нужная информация.
for (int x = 0; x < entries.Count; x++)
{
content = entries.Elements[x].InnerHtml;
1.6. ОБЯЗАТЕЛЬНО весь наш последующий
код должен быть расположен в
конструкции(try..catch), для того, чтобы при
возникновение ошибок, код понимал,
что делать в этом случае.
try{
1.7. Получаем информацию с необходимого тега('span' с названием класса 'kt-font-brand'), с помощью XPath запроса, используя метод ParseByXpath и сохраняем полученные данные в список.
lstTemp =
ZennoPoster.Parser.ParseByXpath(content,
"//span[contains(@class,'kt-font-brand')]",
"innerText").ToList();
totalTimePublicPostAdvertise =
lstTemp[0].Trim().Replace("'", @"''");
}catch (Exception ex){
1.8. Отправляем ошибку в лог ZennoPoster.
project.SendErrorToLog(ex.Message, true);
}
}
Продолжение следует...
#ZennoPoster, #Дата
This media is not supported in your browser
VIEW IN TELEGRAM
Вот пример одного из скриптов, который помогает анализировать группы из ТГ и сокращает большое кол-во ручного труда.
Преимущества:
- Многопоточность.
- Работа с СУБД - SQLite(как писал выше, один файл, путь к Б.Д. и всё).
- Выборка групп(из сервиса и нашей Б.Д.), согласно критериям, которые были заданы в настройках программы.
- Сохранения данных в docs.google.com
- Подсчёт средней величины размещения рекламных постов в днях и по времени на площадке.
- Создание скриншотов, тех постов, которые принесли больше всего кол-во подписчиков, согласно выбранной тематике.
- Кол-во новых подписчиков(минимум, максимум, среднее) от тех рекламных постов, которые были размещены на площадке раньше.
- и др. фишки, которые помогают делать анализ площадки.
Недостатки:
- Плата за использования программного комплекса ZennoPoster.
- Плата за использование сервиса с которого берутся данные.
- Ограниченное кол-во потоков.
Часть вещей, которые реализовал в этом скрипте, буду описывать в дальнейших постах.
#ZennoPoster
Преимущества:
- Многопоточность.
- Работа с СУБД - SQLite(как писал выше, один файл, путь к Б.Д. и всё).
- Выборка групп(из сервиса и нашей Б.Д.), согласно критериям, которые были заданы в настройках программы.
- Сохранения данных в docs.google.com
- Подсчёт средней величины размещения рекламных постов в днях и по времени на площадке.
- Создание скриншотов, тех постов, которые принесли больше всего кол-во подписчиков, согласно выбранной тематике.
- Кол-во новых подписчиков(минимум, максимум, среднее) от тех рекламных постов, которые были размещены на площадке раньше.
- и др. фишки, которые помогают делать анализ площадки.
Недостатки:
- Плата за использования программного комплекса ZennoPoster.
- Плата за использование сервиса с которого берутся данные.
- Ограниченное кол-во потоков.
Часть вещей, которые реализовал в этом скрипте, буду описывать в дальнейших постах.
#ZennoPoster
Как и обещал ранее, буду рассматривать некоторые примеры, которые были реализованы мною в этом скрипте (если будет интересна одноразовая услуга по сбору площадок, используя этот скрипт, пишите).
Очень часто при вёрстки макетов сайта, похожая информация находится в в одинаковых тегах(div,tr,td,span и т.д.), которые для удобства отображения находятся в отдельных классах. Для того, чтобы получить всю эту информацию, необходимо это учесть.
Поэтому в данном примере это учту и покажу xPath запрос, который помог справится с этим.
Работаю с программным комплексом ZennoPoster
1. Обращаемся к свойству('ActiveTab') объекта('instance') и передаём полученную информацию в класс('Tab') (более подробнее писал выше).
2. С помощью XPath запроса передаём найденные элементы в класс 'HtmlElementCollection'.
Интересный момент, на который стоит обратить внимание.
а) Тело самого запроса использует логический оператор "или (|)", это позволяет нам собирать информацию с одинаковых тегов, но у которых разное оформление( "class")
3. Основную информацию об элементах получил, дальше необходимо её обрабатывать.
#ZennoPoster, #Xpath
Очень часто при вёрстки макетов сайта, похожая информация находится в в одинаковых тегах(div,tr,td,span и т.д.), которые для удобства отображения находятся в отдельных классах. Для того, чтобы получить всю эту информацию, необходимо это учесть.
Поэтому в данном примере это учту и покажу xPath запрос, который помог справится с этим.
Работаю с программным комплексом ZennoPoster
1. Обращаемся к свойству('ActiveTab') объекта('instance') и передаём полученную информацию в класс('Tab') (более подробнее писал выше).
Tab tab = instance.ActiveTab;
2. С помощью XPath запроса передаём найденные элементы в класс 'HtmlElementCollection'.
HtmlElementCollection entries = tab.FindElementsByXPath("//tr[starts-with(@class,'tr_even')] | //tr[starts-with(@class,'tr_odd')]");
Интересный момент, на который стоит обратить внимание.
а) Тело самого запроса использует логический оператор "или (|)", это позволяет нам собирать информацию с одинаковых тегов, но у которых разное оформление( "class")
"//tr[starts-with(@class,'tr_even')] | //tr[starts-with(@class,'tr_odd')]"
3. Основную информацию об элементах получил, дальше необходимо её обрабатывать.
#ZennoPoster, #Xpath
Продолжаю работать с ZennoPoster - ом. На этот раз задача состоит в том, чтобы отсылать сообщения в Telegram используя бота.
В начале, для того чтобы пользоваться им, необходимо получить токен доступа для него в telegram.
Наши действия:
1. Находим и добавляем в телеграм контакт @BotFather.
2. Заходим к нему в чат. Вызываем команду: /start
далее: /newbot.
3. Печатаем имя нашего бота(например имя моего бота "vkbotanswer").
4. Далее username(обязательно с окончанием "bot")
5. В ответном сообщение получаем токен нашего бота.
6. Дальше добавляем нашего бота(как "администратора") в необходимый канал и одновременно получаем id этого канала, перейдя по ссылке.
https://api.telegram.org/bot1351987:AAGvMM26veDkzXyV72L1PU_7L0jjkO/getUpdates
где: 1351987:AAGvMM26veDkzXyV72L1PU_7L0jjkO(полученный токен доступа).
Внимание: id канала имеет всегда знак "-" т.е. такой вид: -1005758311 .
7. На этом бот наш готов и мы можем отсылать наше сообщение(пример запроса):
https://api.telegram.org/bot1351987:AAGvMM26veDkzXyV72L1PU_7L0jjkO/sendMessage?chat_id=-1005758311&text=Приветствую!Меня зовут vkbotanswer и я готов к вашим командам.
Продолжение следует.....
#ZennoPoster
В начале, для того чтобы пользоваться им, необходимо получить токен доступа для него в telegram.
Наши действия:
1. Находим и добавляем в телеграм контакт @BotFather.
2. Заходим к нему в чат. Вызываем команду: /start
далее: /newbot.
3. Печатаем имя нашего бота(например имя моего бота "vkbotanswer").
4. Далее username(обязательно с окончанием "bot")
5. В ответном сообщение получаем токен нашего бота.
6. Дальше добавляем нашего бота(как "администратора") в необходимый канал и одновременно получаем id этого канала, перейдя по ссылке.
https://api.telegram.org/bot1351987:AAGvMM26veDkzXyV72L1PU_7L0jjkO/getUpdates
где: 1351987:AAGvMM26veDkzXyV72L1PU_7L0jjkO(полученный токен доступа).
Внимание: id канала имеет всегда знак "-" т.е. такой вид: -1005758311 .
7. На этом бот наш готов и мы можем отсылать наше сообщение(пример запроса):
https://api.telegram.org/bot1351987:AAGvMM26veDkzXyV72L1PU_7L0jjkO/sendMessage?chat_id=-1005758311&text=Приветствую!Меня зовут vkbotanswer и я готов к вашим командам.
Продолжение следует.....
#ZennoPoster
Forwarded from vladimir
Сегодня продолжю работать с ZennoPoster и Telegram, но уже в видео формате.
Основные шаги.
1. Создание проекта.
2. Создание переменных.
3. Отправка сообщения в ТГ, 2-мя способами.
#ZennoPoster, #Telegram
Основные шаги.
1. Создание проекта.
2. Создание переменных.
3. Отправка сообщения в ТГ, 2-мя способами.
#ZennoPoster, #Telegram
Media is too big
VIEW IN TELEGRAM
Отправление фото и видео в Telegram используя ZennoPoster и библиотеку "Telegram.Bot"
#ZennoPoster, #Telegram
#ZennoPoster, #Telegram
// Получаем время из переменной с указанием часовго пояса: 15.02.2022 12:00 +00:00
/* 1. Вариат с использованием struct DateTimeOffset .*/
// Парсим и сохраняем значение времени в struct DateTimeOffset.
// Преобразуем struct DateTimeOffset в struct DateTime(для дальнейшей работы).
// Выводим сообщение в лог.
/* 2. Вариат без использования struct DateTimeOffset .*/
// Конвертируем в struct DateTime.
// Выводим сообщение в лог.
/* 3. Получение кол-во времени до события исходя из текущего согласно нашего часового пояса и времени начало самого события.*/
// Получение текущего времени согласно нашего часового пояса.
// Выводим сообщение в лог.
// Преобразование текущего времени согласно нашего часового пояса в UTC.
// Выводим сообщение в лог.
// Подсчёт кол-во времени до события.
// Выводим сообщение в лог.
#ZennoPoster, #DateTime
string capDateAndTimeRunRegistrationInSeil = project.Variables["capDateAndTimeRunRegistrationInSeil"].Value;
/* 1. Вариат с использованием struct DateTimeOffset .*/
// Парсим и сохраняем значение времени в struct DateTimeOffset.
var dtOffset_forSeil = DateTimeOffset.Parse(capDateAndTimeRunRegistrationInSeil);
// Преобразуем struct DateTimeOffset в struct DateTime(для дальнейшей работы).
var time_forSeil_DtOff = dtOffset_forSeil.DateTime;
// Выводим сообщение в лог.
project.SendToLog("ВРЕМЯ РЕГИСТРАЦИИ С ПОМОЩЬЮ DateTimeOffset: " + time_forSeil_DtOff.ToString("dd.MM.yyyy HH:mm:ss"), ZennoLab.InterfacesLibrary.Enums.Log.LogType.Info, true, ZennoLab.InterfacesLibrary.Enums.Log.LogColor.Yellow);
/* 2. Вариат без использования struct DateTimeOffset .*/
// Конвертируем в struct DateTime.
var time_forSeil_Dt = Convert.ToDateTime(capDateAndTimeRunRegistrationInSeil);
// Выводим сообщение в лог.
project.SendToLog("ВРЕМЯ РЕГИСТРАЦИИ С ПОМОЩЬЮ БЕЗ DateTimeOffset: " + time_forSeil_Dt.ToString("dd.MM.yyyy HH:mm:ss"), ZennoLab.InterfacesLibrary.Enums.Log.LogType.Info, true, ZennoLab.InterfacesLibrary.Enums.Log.LogColor.Yellow);
/* 3. Получение кол-во времени до события исходя из текущего согласно нашего часового пояса и времени начало самого события.*/
// Получение текущего времени согласно нашего часового пояса.
DateTime dtNow = DateTime.Now;
// Выводим сообщение в лог.
project.SendToLog("ТЕКУЩЕЕ ВРЕМЯ СОГЛАСНО НАШЕГО ЧАСОВОГО ПОЯСА: " + dtNow.ToString("dd.MM.yyyy HH:mm:ss"), ZennoLab.InterfacesLibrary.Enums.Log.LogType.Info, true, ZennoLab.InterfacesLibrary.Enums.Log.LogColor.Green);
// Преобразование текущего времени согласно нашего часового пояса в UTC.
var utcTime_forNow = dtNow.ToUniversalTime();
// Выводим сообщение в лог.
project.SendToLog("ТЕКУЩЕЕ ВРЕМЯ СОГЛАСНО UTC: " + utcTime_forNow.ToString("dd.MM.yyyy HH:mm:ss"), ZennoLab.InterfacesLibrary.Enums.Log.LogType.Info, true, ZennoLab.InterfacesLibrary.Enums.Log.LogColor.Green);
// Подсчёт кол-во времени до события.
TimeSpan diff = time_forSeil_DtOff.Subtract(utcTime_forNow);
// Выводим сообщение в лог.
project.SendToLog("ОСТАЛОСЬ ВРЕМЕНИ ДО РЕГИСТРАЦИИ СОГЛАСНО UTC(ЗАДАННОГО ВРЕМЕНИ) И НАШЕГО ВРЕМЕНИ(СКОНВЕРТИРОВАННОЕ В UTC): " + diff.Days.ToString("0") + " дн. " + diff.Hours.ToString("0") + " час. " + diff.Minutes.ToString("0") + " мин.", ZennoLab.InterfacesLibrary.Enums.Log.LogType.Info, true, ZennoLab.InterfacesLibrary.Enums.Log.LogColor.Orange);
#ZennoPoster, #DateTime
Рассматриваю интересные моменты для получения информации используя метод из API Zennoposter: GetChildren.
1. Кол-во блоков с которых необходимо получить информацию из списка.
Итог: Метод
#ZennoPoster, #Xpath
1. Кол-во блоков с которых необходимо получить информацию из списка.
HtmlElementCollection entries = instance.ActiveTab.FindElementsByXPath("//div[contains(@class,'postlist') and contains(@id,'postsList')]/div");
int countBlocks = entries.Count;
2. Получение блоков в которых содержаться две необходимые части(текст и фото).HtmlElement entry = instance.ActiveTab.FindElementByXPath("//div[contains(@class,'postlist') and contains(@id,'postsList')]/div", numRow);
numRow
- номер блока для парсинга.HtmlElementCollection entries_m = entry.GetChildren(false);
Рекомендую посмотреть на этот метод: GetChildren(false);
Позволяет получить элементы(детей) от главного элемента(родителя). С ним можно "творить" настоящие чудеса т.к. идёт упрощение кода и нет необходимости писать доп.-ые xpath запросы, чтобы обратиться к нужному элементу.for (p = 0; p < entries_m.Count; p++)
{
HtmlElementCollection entries = entries_m.Elements[p].GetChildren(false);
for (s = 0; s < entries.Count; s++)
{
HtmlElementCollection entries_ = entries.Elements[s].GetChildren(false);
for (m = 0; m < entries_.Count; m++)
{
if (string.IsNullOrEmpty(postTitle))
{
postTitle = entries_.Elements[m].InnerHtml;
project.SendInfoToLog(postTitle);
break;
}
}
}
}
entries_m.Count
- полученное кол-во блоков, которое равно 2(т.е. текстовая и фото).HtmlElementCollection entries = entries_m.Elements[p].GetChildren(false);
entries_m.Elements[p].GetChildren(false)
- здесь обращаемся к нужному элементу согласно индекса(т.е. 0), из которого также получаем "детей" элемента.Итог: Метод
GetChildren
очень мощный метод, который даёт возможность обращаться к нижестоящим элементам без Xpath запросов.#ZennoPoster, #Xpath