Ежедневник IT-ка
130 subscribers
24 photos
4 videos
1 file
44 links
Программируем на практике!!
По вопросам по поводу проектов: @vladimir_dzen
Download Telegram
👆 Одна из ситуаций, когда при парсинге Json , получили ❗️исключение❗️. Поэтому, как выход, скрипт пытается найти необходимое значение и заменить его самостоятельно.

#ZennoPoster,#Xpath,#Json
​​Пример использования HttpClient для работы с запросами:

1. Подключаем пространство имён.

using Newtonsoft.Json;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.IO;

2. Создаём класс.

 public class Poster
 {
  public int Id { get; set; }
  public int MovieId { get; set; }
  public string Name { get; set; }
 }

3. Создаем новый экземпляр класса.

private static HttpClient _httpClient = new HttpClient();

4. Устанавливаем свойства текущ.-их методов.

_httpClient.BaseAddress = new Uri("http://localhost:987456");
_httpClient.Timeout = new TimeSpan(0, 0, 30);
_httpClient.DefaultRequestHeaders.Clear();

5. Создаём асинхронный метод(для того, чтобы не блокировать основной поток).

 private async Task<string> GetResourceThroughHttpRequestMessage()
{

   5.1. Создаем новый экземпляр класса.

   var request = new HttpRequestMessage(
    HttpMethod.Get,
    $"api/books/6e0drwqt/posters/{Guid.NewGuid()}");

   5.2. Добавляем тип контента(Content-Type) в   заголовок.

    request.Headers.Accept.Add(new  MediaTypeWithQualityHeaderValue("application/json"));

   5.3. Делаем асинхронный запрос к серверу.

   using (var response = await _httpClient.SendAsync(request))
   {

    5.4. Проверяем полученный код статуса запроса.

    response.EnsureSuccessStatusCode();

    5.5. Читаем полученный ответ.

    var stream = await response.Content.ReadAsStreamAsync();
    using (var streamReader = new StreamReader(stream))
    {
     using (var jsonTextReader = new JsonTextReader(streamReader))
     {
      var jsonSerializer = new JsonSerializer();

      5.6. Устанавливаем значения из Json в объект класса Poster.

      var poster = jsonSerializer.Deserialize<Poster>(jsonTextReader);

      5.7. Получаем значение одного из свойств объекта класса Poster.

      return poster.Name;
     }
    }
   }
}

#HttpClient, #Csharp
This media is not supported in your browser
VIEW IN TELEGRAM
Для того, чтобы использовать в пространстве имён библиотеку Newtonsoft.Json(как пример), необходимо её установить.
Установка пакета(ов) будем производить, через NuGet (систему управление пакетами).
Задача довольно простая и тривиальная, но многие новички теряются и не знают, что и как делать.

#Csharp,#видео
​​В группе будут публиковаться различные посты, которые будут связаны с программным комплексом ZennoPoster.
Он используется мною очень часто т.к. помогает решить, большое кол-во задач связанных с автоматизацией, которые ведутся через браузер.
Самое главное его преимущество, что у него очень большое сообщество и его постоянно совершенствуют.

#ZennoPoster
Указано то, на что стоит всегда обращать внимание.
С другими ответами при выполнение Http запросов, можно ознакомится здесь.

#HTTP
​​Необходимо помнить, что повторные Http запросы надо блокировать т.к. это может привести к ошибкам, а именно "могут исчерпаться все доступные TCP соединения"

1. Подключаем пространство имён.

using System.Net.Http;
using System.Threading.Tasks;

static async Task Main(string[] args)
{
  await ReuseQuery();
}

2. Создаём асинхронный метод(что это такое, очень хорошо написано, здесь).

    public static async Task<string> ReuseQuery()
    {
      string result = string.Empty;

2.1. Создаём экземпляра класса.

      using (var client = new HttpClient())
      {

2.2. Обязательно цикл делать внутри конструкции using(для
того, чтобы повторные запросы происходили, через 1 TCP
соединение)

        for (int i = 0; i < 5; i++)
        {
          var request = new HttpRequestMessage(HttpMethod.Get,
            "google.com");

2.3. Делаем запрос.

          using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead))
          {

2.4. Читаем полученные данные.

            result = await response.Content.ReadAsStringAsync();
            response.EnsureSuccessStatusCode();
          }
        }
      }
      return result;
    }
  }

#Csharp,#HTTP
​​Продолжаю работать с ZennoPoster - ом, который помогает решить различные задачи.
Рассмотрим часть примера, одного из моих заказов.
Необходимо получать рандомную информацию о человеке(его адрес), в качестве донора используется
этот сайт.
​​После того, как нашли необходимый тег, получаем более детальную информацию в свойствах элемента.
В своей практике использую очень часто Xpath и Linq запросы, которые помогают более точно найти и обработать необходимые элементы.

#ZennoPoster
​​Часто бывают случаи необходимо работать с Json, который представляет собой элемент с вложенной структурой.

Пример:

{
 "clientKey": "fdfggghhttyydshkahue26",
 "task": {
  "cookies": "",
  "type": "NoCaptchaTaskProxyless",
  "websiteURL": "https://www.somesite/ru/login",
  "websiteKey": "6LcMERGSGSGSHHHS-KcbYQMd-wcLt6ight7u"
  }
}

Рекомендую разбивать подготовительный этап на определённые шаги.

1. Подключение пространство имён.

using Newtonsoft.Json;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.IO;
using System.Text;

2. Создание объектов классов.

  public class CreateTaskRecaptcha
  {
    public string clientKey { get; set; }
    public DataForCreateTaskRecaptcha task { get; set; }
  }
  public class DataForCreateTaskRecaptcha
  {
    public string cookies { get; set; }
    public string type { get; set; }
    public string websiteURL { get; set; }
    public string websiteKey { get; set; }
  }
  public class ResultRecaptcha
  {
    public int errorId { get; set; }
    public string status { get; set; }
    public int taskId { get; set; }
    public string errorDescription { get; set; }
  }

3. Создаём метод, который возвращает экземпляр объект класса с необходимыми заголовками.

    public static HttpClient CreateHttpClient()
    {
      var client = new HttpClient();
      client.Timeout = new TimeSpan(0, 0, 30);
      client.DefaultRequestHeaders.Clear();
      client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36");
      client.DefaultRequestHeaders.Add("Accept", "*/*");
      client.DefaultRequestHeaders.Add("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7");
      client.DefaultRequestHeaders.Add("Connection", "keep-alive");
      return client;
    }

4. Создаём обязательно асинхронный метод, который возвращает метод класса.

    private async Task<int> GetPostThroughHttpRequest(HttpClient client)
    {

4.1. Переменные которые хотим передать.

      string websiteURL = "https://www.google.com/";
      string websiteKey = "6LcMERGSGSGSHHHS-KcbYQMd-wcLt6ight7u";
      string clientKey = "fdfggghhttyydshkahue26";
      string uri = "https://somesite.com/auth/login";

4.2. Передадим значения переменных в наш объект класса.

      var dict = new CreateTaskRecaptcha
      {
        task = new DataForCreateTaskRecaptcha
        {
          cookies = "",
          type = "NoCaptchaTaskProxyless",
          websiteURL = websiteURL,
          websiteKey = websiteKey
        },
        clientKey = clientKey
      };

4.3. Создадим Json из объекта класса.

      string bodyJson = JsonConvert.SerializeObject(dict);

4.4. Установим формат нашего тело запроса.

      var body = new StringContent(bodyJson, Encoding.UTF8, "application/json");

4.5. Делаем запрос.

      var response = await client.PostAsync(uri, body);

4.6. Читаем полученный ответ от сервера.

      string content = await response.Content.ReadAsStringAsync();

4.7. Конвертируем полученный ответ в Json и передаём его в наш объект класса.

      var jsonResult = JsonConvert.DeserializeObject<ResultRecaptcha>(content);
      if (jsonResult.errorId > 0) Console.WriteLine(jsonResult.errorDescription);

4.8. Получаем необходимый метод с нашего объекта класса.

      return jsonResult.taskId;
    }

Пример показывает работу с вложенной структурой Json и Http запросами, которые нам надо передать.

#Csharp,#HTTP
​​Хочу поделиться с одной из программ, которую использую для тестирования GET и POST запросов.
Более подробнее с ней можно ознакомится на postman.
Для меня она интересна тем, что в ней предоставляется только необходимые инструменты, для анализа данных + всё можно конвертировать в любой из предоставленных языков программирования.

#Postman
​​Рефлексия - это процесс, который позволяет программе изучать саму себя.
Звучит довольно интересно и интригующе, в практике позволяет:
- перечислять члены типа
- извлекать информацию о типе
- извлекать информацию о сборке
- исследовать пользовательские атрибуты
Надо понимать, что это всё применимо для общедоступных (public) методов из заданного типа.

Рассмотрим простой пример(реализован в WPF приложение):

1. Создаём объект класса(это отдельный файл с расширением .cs).

namespace HumanizerDemo
{
  public class Binance
  {
    public int BalanceUSD { get; set; }
    public int BalanceBTC { get; set; }
    public Binance(int n, int a)
    {
      BalanceUSD = n;
      BalanceBTC = a;
    }

    public int CalculateCount(int countUsd, int priceBtc)
    {
      return countUsd / priceBtc;
    }
  }
}

2. При создание проекта WPF автоматически создаётся файл MainWindow.xaml с разметкой(это, то что у меня):

<Window x:Class="HumanizerDemo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:HumanizerDemo"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
  <Grid>

  </Grid>
</Window>

2.1. В этот код добавляем:

- элемент компоновки "StackPanel",
- текстовый элемент "TextBlock",
- элемент кнопки "Button"

  <Grid>
    <StackPanel>
      <Button Name="GetHumanMethodNames" Click="GetHumanMethodNames_OnClick">Получение методов</Button>
      <TextBlock Name="Output"></TextBlock>
    </StackPanel>
  </Grid>

Продолжение следует...

#Рефлексия, #Csharp, #WPF
​​Продолжаем знакомство с программным комплексом 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, #Сниппеты
​​Продолжаем знакомство с рефлексией, и будем получать информацию о классе и о методах в нём.

Рассматриваем проект, который реализовали ранее.

1. Открываем файл "MainWindow.xaml.cs", который был создан автоматически.

2.Подключаем пространство имён.

using System;
using System.Reflection;
using System.Windows;

3. Метод который описывает действие, которое происходит при нажатие на кнопку(которую создали в прошлый раз).

    private void GetHumanMethodNames_OnClick(object sender, RoutedEventArgs e)
    {

3.1. Имя нашего текстового блока, который расположен в
нашей разметке.

      Output.Text = "";

3.2. Поучаем экземпляр класса Туре, в котором прописываем
"полное имя типа(нашего класса) в строковом
представлении".

var infoAboutClass = Type.GetType("HumanizerDemo.Binance",false,true);

3.3. Устанавливаем размер шрифта, для нашего текстового
блока.

      Output.FontSize = 16;

3.4. Получаем разную информацию о классе с помощью
методов класса Type.

      Output.Text += "Получаем разную информацию о классе с помощью методов класса Type";
      Output.Text += Environment.NewLine;
      Output.Text += Environment.NewLine;
      Output.Text += "Полное Имя: " + infoAboutClass.FullName;
      Output.Text += Environment.NewLine;
      Output.Text += "Базовый класс: " + infoAboutClass.BaseType.ToString();
      Output.Text += Environment.NewLine;
      Output.Text += "Абстрактный: " + infoAboutClass.IsAbstract.ToString();
      Output.Text += Environment.NewLine;
      Output.Text += "Запрещено наследование: " + infoAboutClass.IsSealed.ToString();
      Output.Text += Environment.NewLine;
      Output.Text += "class: " + infoAboutClass.IsClass.ToString();
      Output.Text += Environment.NewLine;
      Output.Text += "Публичный: " + infoAboutClass.IsPublic.ToString();
      Output.Text += Environment.NewLine;
      Output.Text += Environment.NewLine;

3.5. Получаем информацию о методах, которые существуют в
этом классе.

      MethodInfo[] mi = infoAboutClass.GetMethods(BindingFlags.Instance
          | BindingFlags.Static
          | BindingFlags.Public
          | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);

      Output.Text += "Получаем информацию о методах";
      Output.Text += Environment.NewLine;
      Output.Text += Environment.NewLine;
      foreach (MethodInfo imi in mi)
      {
        Output.Text += "Полное Имя: " + imi.Name.ToString();
        Output.Text += Environment.NewLine;
      }
    }

Рассмотрел простейшие примеры, но уже и они показывают возможности рефлексии, которые помогают нам узнать некоторые вещи.

#Рефлексия, #Csharp
​​Работа со временем и датами - это одна из тех задач, которую необходимо делать в программирование очень часто. Ведь актуальность данных это, то на чём держится современный мир(ушёл от темы).
Мы также не будем отставать и будем работать со временем.

Задача: рассчитать среднее кол-во времени размещение постов в группе(наш случай) согласно сервиса 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, #Дата
Продолжаем работать со временем.
В прошлом примере, был получен список 'lstTemp' с временем.
Список выглядит так:

23 часов 58 минут,
23 часов 53 минут,
19 часов 9 минут,
23 часов 57 минут,
и т.д.

Наша цель преобразовать время, которое сейчас является типом данных "string" в тип данных "DateTime".
В C# существуют 2 метода(самые популярные), которые пытаются конвертировать "string" => "DateTime". Рассмотрим их более подробно.

1. DateTime.ParseExact(string s, string format, IFormatProvider? provider) - этот метод в качестве аргументов, кроме строки с датой, принимает еще строку в которой указан формат представления даты, а так же строку с указанием культуры, в которой принято такое представление.
Пример:

string time = "2021 Четверг октябрь 28 16:01";
System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CreateSpecificCulture("ru-RU");
DateTime dt = DateTime.ParseExact(time, "yyyy dddd MMMM dd HH:mm", culture);

Результат: 23.06.2020 14:35:00

2.DateTime.Parse(string s) - этот метод в качестве аргумента принимает строку с датой.
Пример:

string time = "23:58";
DateTime dt = = DateTime.Parse(time);

Результат: 28.10.2021 23:58:00

Методы существуют, но в нашем случае они не подходят т.к. не смогут распознать формат такого времени: "23 часов 58 минут".

Поэтому будет разбивать на определённые этапы:
1. Создаёт список с типом данных 'DateTime':

var listTimeTemp = new List<DateTime>();

2. Подготовим время в нормальный формат с помощью регулярного выражения, который поймёт метод: DateTime.Parse(string s):

tmpData = Regex.Replace(tmpData, @"ча.*?\s", ":");
tmpData = Regex.Replace(tmpData, @"мин.*", "");

после чистки, время уже будет иметь вот такой формат: "23:58"

3. Конвертируем и сохраняем полученное время в ранее созданный список 'listTimeTemp':

listTimeTemp.Add(DateTime.Parse(tmpData));

4. Сортируем полученное время в порядке возрастания с помощью 'Linq':

listTimeTemp.Sort((a, b) => a.CompareTo(b));

5. Создаёт список с типом данных 'double':

var totalMinutes = new List<double>();

6. Создаём цикл для списка 'listTimeTemp'( для того, чтобы получить минуты из часов и минуты из минут, соответственно. Формат времени из которого берутся эти данные:'28.10.2021 23:58:00'(пример)):

foreach (var hours in listTimeTemp)
{
int minutesFromHours = hours.Hour * 60;
int minutesFromMinutes = hours.Minute;
totalMinutes.Add(minutesFromHours + minutesFromMinutes);
}

7. Получаем среднюю сумму значения всех полученных минут из списка 'totalMinutes'.

var sum = totalMinutes.Sum() / listTimeTemp.Count;

8. Создаём объект 'TimeSpan', для того, чтобы из средней суммы, которую получили выше, получить часы и минуты:

TimeSpan ts = TimeSpan.FromMinutes(sum);
int midHours = ts.Hours;
int midMinutes = ts.Minutes;

9. Пример результата:

string res = ts.Hours.Tostring() + ":" + ts.Minutes.Tostring();

"22:52" - наше полученное искомое среднее время.

10. Пример всего кода:

var tmpData = string.Empty;
var listTimeTemp = new List<DateTime>();
for (x = 0; x < lstTemp.Count; x++)
{
tmpData = lstTemp[x].Trim();
tmpData = Regex.Replace(tmpData, @"ча.*?\s", ":");
tmpData = Regex.Replace(tmpData, @"мин.*", "");
listTimeTemp.Add(DateTime.Parse(tmpData));
}
listTimeTemp.Sort((a, b) => a.CompareTo(b));

var totalMinutes = new List<double>();
foreach (var hours in listTimeTemp)
{
int minutesFromHours = hours.Hour * 60;
int minutesFromMinutes = hours.Minute;
totalMinutes.Add(minutesFromHours +
minutesFromMinutes);
}
var sum = totalMinutes.Sum() / listTimeTemp.Count;
TimeSpan ts = TimeSpan.FromMinutes(sum);
int midHours = ts.Hours;
int midMinutes = ts.Minutes;
string res = ts.Hours.Tostring() + ":" + ts.Minutes.Tostring();

В этом примере рассмотрел те вещи, которые можно делать используя 'DateTime' и 'TimeSpan'.

#Csharp, #Дата
Сегодня буду говорить о База Данных и СУБД, в дальнейшем буду рассматривать конкретные примеры.
Для меня База Данных - это то место, где хранятся необходимые сведения, которые необходимо использовать в проектах(делаю то разделение, которое использую в своей специализации).

Это могут быть:

1. Текстовые файлы - просто огромное кол-во проектов и заказчиков, обожают хранить информацию в *.txt файлах.

2. Excel таблицы - различные форматы таблиц, самые популярные: csv, xls,xlsx и т.д.

3. Json - это подвид текстового формата с расширением *json, он очень удобен из-за своей структуры. При работе с сайтами, этот формат очень популярен. К примеру многие сайты, которые имеют API - выводят информацию в этом формате.

4. Xml - ещё один формат напоминающий json, но есть отличия и очень серьёзные, имеет расширение *.xml. Очень часто используются при загрузки на сайты, каких либо товаров, продуктов, также используются сайтами недвижимости(Yandex,Cian,Avito и др.)

5. MySQL - система управления базами данных. В современном мире без элементарного понимания работы с MySql, могут начаться большие трудности. Многие скрипты, проекты, веб-приложения используют эту систему. Один жирный минус - для неё нужен сервер.

6. SQLite - компактная встраиваемая система управления базами данных. Очень удобно её использовать т.к. не требует "лишних телодвижений". Создал файл(к примеру: *.db), в нём таблицу и подключился к ней, просто указав путь, "красота".

7. Microsoft SQL Server - парадоксально, но не смотря на то, что мною проекты созданы в основном на C#, эту СУБД использую крайне редко т.к. многим надо "выход в мир" и быть более свободными и не зависеть от привязки к Windows. Хотя эта СУБД, также очень популярна.

8. Firebase.google.com - это облачный сервис, в котором также можно создать свою Б.Д. В чём её преимущество: просто подключиться, доступность из любой точки мира, бесплатно(платный вариант также есть, но в основном он не нужен), в какой-то степени замена MySQL(но, очень условно т.к. есть отличия при работе с ней).

Перечислил то, что использую в своих проектах в 90% случаях. Понятно, что это только часть из того, что есть, но этого вполне мне хватает.

Много из всего этого, я буду рассматривать с своих примерах т.к. работа с ними имеет свой подход.
This media is not supported in your browser
VIEW IN TELEGRAM
Вот пример одного из скриптов, который помогает анализировать группы из ТГ и сокращает большое кол-во ручного труда.

Преимущества:

- Многопоточность
.

- Работа с СУБД - SQLite(
как писал выше, один файл, путь к Б.Д. и всё).

- Выборка групп(из сервиса и нашей Б.Д.), согласно критериям, которые были заданы в настройках программы.

- Сохранения данных в
docs.google.com

-
Подсчёт
средней величины размещения рекламных постов в днях и по времени на площадке.

-
Создание скриншотов, тех постов, которые принесли больше всего кол-во подписчиков, согласно выбранной тематике.

- Кол-во новых подписчиков(минимум, максимум, среднее) от тех рекламных постов, которые были размещены на площадке раньше.

- и др. фишки, которые
помогают делать анализ площадки.

Недостатки:

- Плата за использования
программного комплекса ZennoPoster.

- Плата за использование сервиса с которого берутся данные.

- Ограниченное кол-во потоков.

Часть вещей, которые реализовал в этом скрипте, буду описывать в дальнейших постах.

#ZennoPoster