King of Parsing - Начало. Часть 1

Регистрация
05.06.2019
Сообщения
170
Благодарностей
98
Баллы
28
Я рад приветствовать тебя, читатель, хочу поделиться с тобой своим успехом в использование программы ZennoPoster.
Не отчаивайся, совсем скоро она начнет приносить свои плоды, возвращать те инвестиции, что ты вложил. Конечно, кнопки бабла не существует, но ты сможешь её сделать для себя сам!

Я понимаю, что уровень знаний у нас разный, поэтому давай начнем по порядку, если ты знаешь больше, я только рад (значит свайпай вверх и получай бонусы), мой посыл для тех, кто не знает с чего начать, где копать и куда двигаться. Я дам механики успешного парсинга, поделюсь своим опытом, который уже сейчас начнет приносить тебе заветные $$$

1. Начало
Вначале мы все начинаем с малого (level 1), постепенно продвигаясь (level UP). Кто-то начинает с регистраций популярных почтовых сервисов, соц. сетей, но в основе этого лежит базис, и это анализ данных. В нашем случае, по большей степени это HTML (внутренняя часть страницы), попробуй нажать F12, вызвалось окно DevTools (окно разработчика). Уверен, ты хоть чуть, но с этим знаком. Если нет, то великий и могучий гугл тебе на помощь!

Первая ступень
Найти элемент на странице (тег). Разберем пример, главной страницы yandex.ru.

Задача:
1. Перейти на страницу.
2. Найти поисковую строку.
3. Вставить в неё значение.
4. Найти кнопку: Найти.
5. Нажать на кнопку: Найти.

Задача 1.jpg


Это банальная задача и чаще всего это так, парсинг однотипное занятие, но если ты не сумеешь понять принцип Code Reuse, тебе постоянно будет очень трудно, тебе будет скучно, ты перегоришь и бросишь все к чертям.

Я тебе покажу, как можно писать шаблоны (болванки), которые гуляют из проекта в проект, лишь пути меняются, которые можно собрать за 30 минут. Но! Здесь есть свои нюансы, которые я тебе покажу!

Объект (тег, элемент), который искомый на странице, имеет опознавательные знаки (атрибуты) и свойства, такие как InnetHtml, InnetText и пр. (можно посмотреть в конструкторе действий).

Конструктор действий

Конструктор действий.png


Set - установить значение атрибуту элемента

set.png


Объекты - Признаки элеменета (тега):
class - Название селекторов CSS, по классам.
style - Свойство и значение стиля CSS, для предания визуала элементу.
id - CSS-селектор по ID.
name - Имя тега.
innerhtml - Полное содержимое тега (включительно) в исходном html.
innertext - Внутренне содержимое элемента (между открытым и закрытым тегом).
RiseEvent - событие над выбранным элементом
rise.png


События, которые можно выполнить:
click - Устанавливает обработчик "клика" мышью по элементу, либо, запускает это событие.
blur - Устанавливает обработчик потери фокуса, либо, запускает это событие.
focus - Устанавливает обработчик получения фокуса на элементе, либо, запускает это событие.
onblur - Потеря фокуса.
onchange - Изменение значения элемента формы.
onclick - Щелчок левой кнопкой мыши на элементе.
oncontextmenu - Вывод контекстного меню, щелчок правой кнопкой мыши.
ondblclick - Двойной щелчок левой кнопкой мыши на элементе.
onfocus - Получение фокуса
onkeydown - Клавиша нажата, но не отпущена.
onkeypress - Клавиша нажата и отпущена.
onkeyup - Клавиша отпущена.
onmousedown - Нажата левая кнопка мыши.
onmousemove - Перемещение курсора мыши.
onmouseout - Курсор покидает элемент.
onmouseover - Курсор наводится на элемент.
onmouseup - Левая кнопка мыши отпущена.
onselect - Выделен текст в поле формы.
onsubmit - Форма отправлена.
drag - Запускается при перемещении элемента или выделенного текста.
drop - Событие drop вызывается для элемента, над которым произошло "сбрасывание" перемещаемого элемента. Событие отвечает за извлечение "сброшенных" данных и их вставку. Событие будет срабатывать только при завершении операции перетаскивания, например, событие не сработает, если пользователь отменит перетаскивание нажатием Esc, или не донесет элемент, до цели.
Два метода которые нам сейчас понадобятся.

В общем если ты с этим не знаком, не бойся, у тебя все получится! Удели должное внимание и терпение!
А сейчас я перейду к уровню (Level 2) и покажу как делать менее отказоустойчивое приложение.

2. Боль - любого парсинга
Сделал сейчас, не значит что будет работать вечно, уже завтра может песенка спеть!

Болезнь:
1. Изменение тега
2. Изменение значений атрибута
3. Долгое появление элемента (из-за соединения интернета или большого кол-во скриптов)
4. Отсутствие тега

Рекомендация №1
Чтобы процесс работы программы была более устойчива к мелким изменениям,
необходимо предвидеть обстоятельства, которые могут возникнуть в процессе.
Пункт 1-2:
Создавая пути, продумывай несколько вариантов.

Несколько вариантов индификации элемента.jpg


Пример:
Кнопка: Найти:
<button class="button mini-suggest__button button_theme_websearch button_size_ws-head i-bem button_js_inited button_hovered_yes" data-bem="{&quot;button&quot;:{}}" tabindex="-1" role="button" type="submit"><span class="button__text">Найти</span></button>
1. Тэг имеет много атрибутов, за которые можно ухватиться, если 1 из них будет изменен, то другие смогут выровнять ситуацию.
2. Есть несколько вариантов типа поиска, к примеру:
Сlass атрибут тега button:
class="button mini-suggest__button button_theme_websearch button_size_ws-head i-bem button_js_inited button_hovered_yes"
совершенно нет смысла искать по нему, в нем 1 буква может измениться, где-то в середине и все, путь не работает.
В программе ZennoPoster, есть замечательный штатный функционал, вызвав F3 (конструктор регулярных выражений). И тип поиска стал более стабилен, пример: button.*inited = button(начало) .*(пропустить все) inited (конец). Еasy!!!

Примечание:
1. Тег имеет много атрибутов, за которые можно ухватиться, если 1 будет изменен, то другие смогут выровнять ситуацию.
2. Заметь, я не выбрал тег, я попросил программу найти любой * тэг, у которого атрибуты и значения равны, указанные мною.

Пункт 3:
Очень часто, то прокся, то сервер слабый и пр. бывает и наоборот, но мы можем этим управлять.

Ожидание элемента.jpg

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

Примечание:
То есть, можно не ждать догрузки, а ловить, то что нужно и сразу работать с элементом на странице.

Пункт 4:
От этого никто не застрахован, но проявляй смекалку, в шаблоне (2. Начало), который я приложу будут показаны механики. Надеюсь ты поймешь или задавай вопросы, в теме.

Задача 1 - Полный пример.png


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

Необязательное.jpg


Это все конечно здорово, но возможно кому-то стало скучно, я перехожу на новый уровень (Level 3), а тебе мой друг, я рекомендую!

Рекомендация №2
А. Освоить тщательно интерфейс программы
Б. Не плети паутины, в которых никто не сможет разобраться, когда тебе нужна будет помощь! Помни: 1 страница (задача) = 1 колонка.
В. Не лепи лишнего. Паузы, ожидание уже вшиты в кубик.
Г. Вначале, продумывай логику программы, нужно увидеть начало и конец (вход и выход), а не в процессе строить дом. Запомни, невозможно на фундаменте избушки построить небоскреб.

Рефакторинг-Пауза.jpg

Ну что, маслятки, level UP to 4

Все тоже самое, только на C# + механики от Маломальского кодера и сладкие бонусы.

3. Пример на C#
Задача 1:
    Tab tab = instance.ActiveTab;
    HtmlElement he = null;

    #region 1. Перейти на страницу

            string url = "https://yandex.ru/", referrer = "";
            int counter = 3;

            for (int i = 0; i < counter; i++) // Цикл для счетчика (переменная: counter)
            {
              if ((tab.IsVoid) || (tab.IsNull)) return -1;
              if (tab.IsBusy) tab.WaitDownloading();

              tab.Navigate(url, referrer);

              if (tab.IsBusy) tab.WaitDownloading();

              if (tab.URL == url && tab.URL != "about:blank" && tab.URL != "about:startpage") break;
              if (counter == (i + 1)) throw new Exception(string.Format("Страница: {0} - не загрузилась!", url));

            }

            #endregion

    #region 2. Поисковая строка

            he = instance.ActiveTab.FindElementByAttribute("input:text", "aria-label", "Запрос", "text", 0);

            if (he.IsVoid) throw new Exception(project.Variables["query"].Comment + "; Переменная: he, стр. 18;"); // Выход по ошибке!

            instance.WaitFieldEmulationDelay();                // Задержка эмуляции
            he.SetValue(project.Variables["query"].Value, instance.EmulationLevel, false);

            #endregion

    #region 3. Нажать кнопку: Найти

            he = instance.ActiveTab.FindElementByAttribute("button", "type", "submit", "text", 0);
            if (he.IsVoid) throw new Exception("Не смог нажать кноку: \"Найти\"; Переменная: he, стр. 25;"); // Выход по ошибке!"

            instance.WaitFieldEmulationDelay();                // Задержка эмуляции
            he.RiseEvent("click", instance.EmulationLevel); // Вызвать событие "click"
            #endregion
   
             project.SendInfoToLog("Выполнил нажатие по кнопке \"Найти\", перехожу к следующему действию...");
Здесь я не учел многообразие вариаций, но и здесь мы видим, что 3 строчки кода повторяются, хотя методы разные.

Рефакторинг кода.jpg


П.с. -Это всего лишь 2 объекта, а таких может быть десятки.

Большую часть времени, я тратил на эти портянки (одно и тоже), то есть, на написание сборщика данных у меня уходило 5 часов, а собирал он, всего 30-60 мин. Получается, что работал на робота, а не он на меня!

-Хватит это терпеть! Поехали!

Создадим метод, который мы будем постоянно использовать, но для начала покажу, во что превратилась программа из примера указанного выше.
Задача 1 - Рефакторинг:
var entity = new CommonCode(instance, project);
entity.Navigate("https://yandex.ru/");
entity.SetValueByAttribute(project.Variables["query"].Value, "input:text", "aria-label", "Запрос", "text", 0, project.Variables["query"].Comment + "; Кубик: Рефакторинг кода, стр. 2;");
entity.RiseEventByAttribute("button", "type", "submit", "text", 0, "Не смог нажать кноку: \"Найти\"; Кубик: Рефакторинг кода, стр. 3;");

project.SendInfoToLog("Выполнил нажатие по кнопке \"Найти\", перехожу к следующему действию...");
Приступим к созданию своего класса и реализуем в нем метод:

П.С. КопиПаста
Директивы using и Общий код:
    public class CommonCode
    {
    //  Модификатор доступа | Тип переменной | Имя переменной                  
        private Instance                        instance;
        private IZennoPosterProjectModel        project;
        private Tab                            tab;
        private HtmlElement                       he;
        private Random                           rnd;
        List<string>                           listDB;

        /// <summary>
        /// Конструктор класса, устанавливает значение переменым/свойствам по-умолчанию, при создание экземпляра класса
        /// </summary>
        public CommonCode (Instance instance, IZennoPosterProjectModel project)
        {
            this.instance    = instance;
            this.project     = project;
            tab              = instance.ActiveTab;
            he                 = null;
            rnd                 = new Random();
            listDB             = null;
        }
        /// <summary>
        /// Перейти на страницу
        /// </summary>
        /// <param name="url">Ссылка на документ</param>
        /// <param name="referrer">Откуда пришли? По-умолчанию: Ниоткуда! *Необязательный параметр!</param>
        /// <param name="counter">Кол-во попыток загрузить страницу. По-умолчанию: 3; *Необязательный параметр!</param>
        /// <returns></returns>
        public string Navigate(string url, string referrer = "", int counter = 3)
        {
            for (int i = 0; i < counter; i++) // Цикл для счетчика (переменная: counter)
            {
              if ((tab.IsVoid) || (tab.IsNull)) return "-1";
              if (tab.IsBusy) tab.WaitDownloading();

              tab.Navigate(url, referrer);
              if (tab.IsBusy) tab.WaitDownloading();

              if (tab.URL == url && tab.URL != "about:blank" && tab.URL != "about:startpage") break;
              if (counter == (i + 1)) throw new Exception(string.Format("Страница: {0} - не загрузилась!", url));
            }
            return "-1";
        }

        /// <summary>
        /// Установить значение элементу по атрибуту тега
        /// </summary>
        /// <param name="setValue">Передаваемое значение</param>
        /// <param name="tags">Тег</param>
        /// <param name="attrName">Имя атрибута</param>
        /// <param name="attrValue">Значение атрибута</param>
        /// <param name="searchKind">Тип поиска. Этот параметр может принимать следующие значения: «text», «notext» и «regexp».</param>
        /// <param name="index">Позиция элемента в массиве</param>
        /// <param name="messageError">Сообщение на случай ошибки</param>
        public string SetValueByAttribute(string setValue, string tags, string attrName, string attrValue, string searchKind, int index, string messageError)
        {
            he = tab.FindElementByAttribute(tags, attrName, attrValue, searchKind, index);
            if (he.IsVoid) throw new Exception(messageError); // Выход по ошибке!

            instance.WaitFieldEmulationDelay();    // Задержка эмуляции
            he.SetValue(setValue, instance.EmulationLevel, false);
            return "ok";
        }

        /// <summary>
        /// Установить значение элементу по атрибуту тега + пауза перед выполнением
        /// </summary>
        /// <param name="setValue">Передаваемое значение</param>
        /// <param name="tags">Тег</param>
        /// <param name="attrName">Имя атрибута</param>
        /// <param name="attrValue">Значение атрибута</param>
        /// <param name="searchKind">Тип поиска. Этот параметр может принимать следующие значения: «text», «notext» и «regexp».</param>
        /// <param name="index">Позиция элемента в массиве</param>
        /// <param name="messageError">Сообщение на случай ошибки</param>
        /// <param name="pauseFrom">Случайная пауза перед выполнением, число от</param>
        /// <param name="pauseTo">Случайная пауза перед выполнением, число до</param>
        public string SetValueByAttribute(string setValue, string tags, string attrName, string attrValue, string searchKind, int index, string messageError, int pauseFrom, int pauseTo)
        {
            Thread.Sleep(rnd.Next(pauseFrom, pauseTo) * 1000); //без проверки (pauseFrom > pauseTo) false! Error!
            SetValueByAttribute(setValue, tags, attrName, attrValue, searchKind, index, messageError);
            return "ok";
        }

        /// <summary>
        /// Вызвать событие на элементе по атрибуту тега
        /// </summary>
        /// <param name="tags">Тег</param>
        /// <param name="attrName">Имя атрибута</param>
        /// <param name="attrValue">Значение атрибута</param>
        /// <param name="searchKind">Тип поиска. Этот параметр может принимать следующие значения: «text», «notext» и «regexp».</param>
        /// <param name="index">Позиция элемента в массиве</param>
        /// <param name="messageError">Сообщение на случай ошибки</param>
        /// <param name="riseEvent">Событие, по-умолчанию: click</param>
        public string RiseEventByAttribute(string tags, string attrName, string attrValue, string searchKind, int index, string messageError, string riseEvent = "click")
        {
            he = tab.FindElementByAttribute(tags, attrName, attrValue, searchKind, index);
            if (he.IsVoid) throw new Exception(messageError); // Выход по ошибке!"

            instance.WaitFieldEmulationDelay();                // Задержка эмуляции
            he.RiseEvent(riseEvent, instance.EmulationLevel);
            return "ok";
        }
        /// <summary>
        /// Добавить значение в список
        /// </summary>
        /// <param name="key">Имя характеристики</param>
        /// <param name="value">Значение характеристики</param>
        public void ToListDB(string value)
        {
            listDB = new List<string>();
            string PathFileParse = project.Directory + @"\tempDB.txt";
   
            listDB.Add(value);
   
            File.WriteAllLines(PathFileParse, listDB, Encoding.UTF8);
        }
        /// <summary>
        /// Форматировать выходные значения, для последующей упаковки в ListDB
        /// </summary>
        /// <param name="key">Имя характеристики</param>
        /// <param name="value">Значение характеристики</param>
        public string formatStrForListDB(string key, string value)
        {
            return string.Format("{0}|{1};", key, value);
        }
    }
Самая важная часть, это подключить исполняющий поток
Исполняющий поток в общий код:
        private Instance instance;
        private IZennoPosterProjectModel project;
        private Tab tab;
        private HtmlElement he;
        private Random rnd;
        List<string> listDB;

        /// <summary>
        /// Конструктор класса, устанавливает значение переменным/свойствам по-умолчанию, при создание экземпляра класса
        /// </summary>
        public CommonCode (Instance instance, IZennoPosterProjectModel project)
        {
            this.instance = instance;
            this.project = project;
            tab = instance.ActiveTab;
            he = null;
            rnd = new Random();
            listDB = null;
        }
Кубик (Экшен), является точкой входа в программу, подобно методу Main.


4. Методы класса
В файлах, которые приложены к статье, имею исчерпывающую информацию, но суть?!
Теперь необходимо сделать свои методы, которые ты часто используешь, чтобы разработка парсера, не отнимала у тебя время!
А в три строчки ты генерировал прайс.

Перегрузка методов, также включена в обзор, это очень мощная возможность, но и использовать её нужно с умом.

Перегрузка метода:
        public string SetValueByAttribute(string setValue, string tags, string attrName, string attrValue, string searchKind, int index, string messageError)
        {
            he = tab.FindElementByAttribute(tags, attrName, attrValue, searchKind, index);
            if (he.IsVoid) throw new Exception(messageError); // Выход по ошибке!

            instance.WaitFieldEmulationDelay();    // Задержка эмуляции
            he.SetValue(setValue, instance.EmulationLevel, false);
            return "ok";
        }

        public string SetValueByAttribute(string setValue, string tags, string attrName, string attrValue, string searchKind, int index, string messageError, int pauseFrom, int pauseTo)
        {
            Thread.Sleep(rnd.Next(pauseFrom, pauseTo) * 1000); //без проверки (pauseFrom > pauseTo) false! Error!
            SetValueByAttribute(setValue, tags, attrName, attrValue, searchKind, index, messageError);
            return "ok";
        }
По сути мы переиспользовали свой же метод, добавив только 1 строчку.
Я дам еще рекомендации, но сейчас пора заканчивать, многое, конечно хочется рассказать, но это история другой статьи...

5. Методы для поиска элемента/ов на странице
Методы поиска элемента (встроенные в ZennoPoster):
      // Поиск одного элемента
     instance.ActiveTab.FindElementByTag("Тег", 0);
     instance.ActiveTab.FindElementByAttribute("Тег", "Имя атрибута", "Значение атрибута", "Тип поиска", 0); // "Тип поиска" - Этот параметр может принимать следующие значения: «text», «notext» и «regexp».
     instance.ActiveTab.FindElementById("Значение атрибута id");
     instance.ActiveTab.FindElementByName("Значение атрибута name");
     instance.ActiveTab.FindElementByXPath("XML Path Language", 0); //XML Path Language, иначе XPath

     // Поиск множества (массив) элементов (кратко)
     FindElementsByTag
     FindElementsByAttribute
     FindElementsById
     FindElementsByName
     FindElementsByXPath
Рекомендация №3
Подробнее с каждым методом, вы можете ознакомиться в оф. документации ZennoPoster.

6. Управление исполняющим потоком

Управление потоком выполнения.jpg


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

Операция над списком.jpg Операция над таблицей.jpg


7. Пояснение механики парсинга в Таблицу.CSV
В завершение этой части, хочу добавить:
Из примера приложенных файлов: 2. Начало > Кубик: Карта путей

C#:
he = tab.FindElementByXPath("//h1", 0);
outString += entity.formatStrForListDB("Имя характеристики", he.InnerText); // формат: имя|значение;

entity.ToListDB(outString);
outString = string.Empty;
Примечание:
Это можно сделать в цикле, но предварительно собрав все ссылки.

Пояснение:
Собираем пути до элементов, указываем имя и значение в выходную строку. Все необходимые элементы, которые находятся в сформированной строке, добавляются в список ListDB (промежуточный файл, для последующей генерации прайса).

Рекомендация №4
Лично я не делаю работу по пути, я делаю это пошагово.

Алгоритм:
1. Собрать ссылки. ( 5-10 мин )
2. Сохранить все страницы, а потом работать с локальными копиями страниц.
3. Сбор данных в промежуточный файл. ( 30-60 мин )
4. Обработать промежуточный файл в таблицу CSV. ( 1 мин < )

Итог: ~1 час проделанной работы, это ок. 500 руб. по рынку.

Но, чтобы укладываться в час! Нужно сделать заготовки (болванки)! И для тебе мой друг, дочитавший это до конца, я сделал обработчик промежуточного файла из данных, которые в последующем генерируются в прайс (Таблица.CSV), не успеешь глазом моргнуть :-).

Генерация прайса в Таблицу CSV.jpg


Надеюсь, дал достаточно, чтобы ты сейчас уже начал зарабатывать! Мой друг, не отчаивайся, я желаю тебе удачи!
Регистрируйся на площадках бирж и уже сейчас долби хостинги)) помогай коммерсам (их очень много), я сам так зарабатываю, на дошик хватает. Со временем, когда набьешь руку и будешь на красоту выдавать прайсики, люди с благодарностью будут вновь и вновь обращаться!

Ну что, пора прощаться, до новых встреч! Если тебе понравилось, нажми: СПАСИБО, я этому буду очень рад, увидев обратную связь, возможно это меня за мотивирует еще больше) Удачи!

8. Книги
1. Справочники по C#
* Герберт Шилдт. C# 4.0. Полное руководство
* Язык программирования C# 7 и платформы .NET и .NET Core

2. ООП
* Приемы объектно-ориентированного проектирования. Паттерны проектирования | Джонсон Ральф, Хелм Ричард (комм. БИБЛИЯ ООП)
* Design Patterns via C# (комм. Интерпретация верхней книги на язык C#)
* Применение UML 2.0 и шаблонов проектирования.
 

Вложения

Последнее редактирование модератором:

FAQBILL

Client
Регистрация
28.09.2013
Сообщения
29
Благодарностей
16
Баллы
3
Супер, для новичков в самый раз. А продолжение когда ?
 
  • Спасибо
Реакции: Маломальский

Dexio

Client
Регистрация
09.05.2014
Сообщения
1 194
Благодарностей
203
Баллы
63
Наконец пояснили работу с тегами и онкликами. Местами справку дублируете, но совокупно очень полезно и стаканилов в голове моменты. Спасибо!
 

ulLite

Client
Регистрация
24.03.2019
Сообщения
26
Благодарностей
3
Баллы
3
И сколько ты поднимаешь на парсинге?)
 

sergio197675

Client
Регистрация
21.09.2019
Сообщения
88
Благодарностей
86
Баллы
18
статья вообще не про это ......
спасибо, всегда интересны нюансики от опытных! если будет возможность опишите опыт и наработки по ускорению работы с XPath , трафиком/запросами и др. рутиной
 
Регистрация
05.06.2019
Сообщения
170
Благодарностей
98
Баллы
28
Супер, для новичков в самый раз. А продолжение когда ?
Чтобы Вам было интересно?

Наконец пояснили работу с тегами и онкликами. Местами справку дублируете, но совокупно очень полезно и стаканилов в голове моменты. Спасибо!
Пожалуйста! Я сам помню, как трудно доставались мне эти первые шаги. По поводу дубля, честно не думал об этом, но сама идея публикации, заключалась не в авось прокатит, чтобы стать участником конкурса, а в концентрации знаний в одном посте, но и не переборщить, избытком и ссылаясь на разные источники. Мне кажется охват у этого раздела довольно большой, особенно у начинающих, ради них собственно это старание, рад поделиться опытом и для меня это тоже опыт.

спасибо, всегда интересны нюансики от опытных! если будет возможность опишите опыт и наработки по ускорению работы с XPath , трафиком/запросами и др. рутиной
Благодарю! XPath , работа с трафиком/запросами планируется. Если людям интересно и у них есть конкретные вопросы, по этой теме, то возможно в последующем, они увидят ответы в продолжение.
 
  • Спасибо
Реакции: userx, 606 и Dexio
Регистрация
05.06.2019
Сообщения
170
Благодарностей
98
Баллы
28
Подача материала очень доходчивая, у вас написано Начало. Часть 1 , хочется продолжения ....
Буду стараться, и долго не томить). Записал ваш контакт, проинформирую при публикации!
 

seregakot

Client
Регистрация
19.03.2016
Сообщения
89
Благодарностей
54
Баллы
18
  • Спасибо
Реакции: Маломальский

Dexio

Client
Регистрация
09.05.2014
Сообщения
1 194
Благодарностей
203
Баллы
63
  • Спасибо
Реакции: Маломальский

radv

Client
Регистрация
11.05.2015
Сообщения
870
Благодарностей
427
Баллы
63
Полезная статья для новичков, :ay: и не только по парсингу, но и по основам построения логики проекта и использованию общего кода. :-)Особенно рекомендации.
Б. Не плети паутины, в которых никто не сможет разобраться, когда тебе нужна будет помощь! Помни: 1 страница (задача) = 1 колонка.
В. Не лепи лишнего. Паузы, ожидание уже вшиты в кубик.
Г. Вначале, продумывай логику программы, нужно увидеть начало и конец (вход и выход), а не в процессе строить дом. Запомни, невозможно на фундаменте избушки построить небоскреб.
Правильная логика действий позволяет сделать более стабильную работу проекта или понять объем работы и написать ТЗ для заказа.
 
  • Спасибо
Реакции: Маломальский

Nike59

Client
Регистрация
05.08.2011
Сообщения
106
Благодарностей
91
Баллы
28
Для новичков и даже продвинутых самое то. Первым подробности, вторым нюансы.
 
  • Спасибо
Реакции: Маломальский

Advert31337

Client
Регистрация
18.12.2016
Сообщения
51
Благодарностей
36
Баллы
18
Уже поперли архитектурные вопросы, это радует. Сейчас тоже как раз ломаю голову надо созданием заготовок под типовые проекты для быстрого развертывания.
 
  • Спасибо
Реакции: Маломальский
Регистрация
05.06.2019
Сообщения
170
Благодарностей
98
Баллы
28
Roman48, Dexio, Nike59, Demiz,Advert31337

Благодарю вас, за ваш проявленный интерес и поддержу, мне очень приятно что последовало столько положительных отзывов! Значит это беЗсонная ночь не пролетела зря!

@radv и тебе) мне казалось ты сварлив и ужасен)

Отдельная благодарность за терпение @ZennoLab Team а также доброту, доверие, без которого бы, я не смог опубликовать начатый труд.
 

Dexio

Client
Регистрация
09.05.2014
Сообщения
1 194
Благодарностей
203
Баллы
63
Roman48, Dexio, Nike59, Demiz,Advert31337

Благодарю вас, за ваш проявленный интерес и поддержу, мне очень приятно что последовало столько положительных отзывов! Значит это беЗсонная ночь не пролетела зря!

@radv и тебе) мне казалось ты сварлив и ужасен)

Отдельная благодарность за терпение @ZennoLab Team а также доброту, доверие, без которого бы, я не смог опубликовать начатый труд.
Приятно читать такие теплые ламповые топики, на добром форуме, где искренне можно сказать, что это и есть настоящее комьюнити. Здорово быть его частью! Не встречал форумов, где друг друга так поддерживают, люди помогают друг другу и поддерживается такая атмосфера вокруг классного продукта.
 

radv

Client
Регистрация
11.05.2015
Сообщения
870
Благодарностей
427
Баллы
63
  • Спасибо
Реакции: Маломальский
Регистрация
05.06.2019
Сообщения
170
Благодарностей
98
Баллы
28
Для тех, у кого не открывается шаблон из 2. Начало и, пример Генератор прайс.
Для версии > 5.12.00
 

Вложения

Последнее редактирование:
  • Спасибо
Реакции: userx, Zedx и awm

awm

Client
Регистрация
02.11.2011
Сообщения
143
Благодарностей
28
Баллы
28
Генератор прайсов так же не открывается на версиях ниже 5.42. Было бы интересно заглянуть.
 
  • Спасибо
Реакции: Маломальский

Roman48

Client
Регистрация
28.02.2016
Сообщения
496
Благодарностей
106
Баллы
43
У тебя в подписи всплывающие подсказки, для самой последней версии не подходит, ProjectMaker V7 RU 7.1.4.0?
Как их использовать? Инфу нашел в папку ExternalAssemblies их переместить, нет подсказок
 

Вложения

Регистрация
05.06.2019
Сообщения
170
Благодарностей
98
Баллы
28
У тебя в подписи всплывающие подсказки, для самой последней версии не подходит, ProjectMaker V7 RU 7.1.4.0?
Как их использовать? Инфу нашел в папку ExternalAssemblies их переместить, нет подсказок
В директорию ExternalAssemblies, помещаются пользовательские библиотеки (зависимости проекта).
XML комментарии к dll библиотекам ZennoPoster, находятся в Диск:\\..\ZennoLab\..\Progs

За актуальными XML комментариями, можно обратиться к @radv
 
  • Спасибо
Реакции: radv и Roman48

radv

Client
Регистрация
11.05.2015
Сообщения
870
Благодарностей
427
Баллы
63

Roman48

Client
Регистрация
28.02.2016
Сообщения
496
Благодарностей
106
Баллы
43
По подсказкам смотрите информацию в этой теме Русские подсказки для C#
Так вы мне платные подсказки сватаете, не понимая ни чего в сишарпе, зачем мне платные нужны?
Я только начинаю проявлять интерес (пытаюсь вникнуть), что к чему, не известно как пойдет.
 

radv

Client
Регистрация
11.05.2015
Сообщения
870
Благодарностей
427
Баллы
63
Я только начинаю проявлять интерес (пытаюсь вникнуть), что к чему, не известно как пойдет.
Для того, чтобы вникнуть в процесс есть много бесплатных видеоуроков. Ссылки на видео есть на этом форуме и на ютуб тоже много видео в открытом доступе. Там можете понять как все делается.

Так вы мне платные подсказки сватаете, не понимая ни чего в сишарпе, зачем мне платные нужны?
Это шаблон для перевода любых подсказок C#. Эти подсказки появляются только при написании своего C# кода (в кубике C# или общем коде. Подробнее про подсказки описано в теме) Сам начинал с того, что пользовался такими подсказками при его изучении. Если Вы знаете английский, то этот шаблон конечно Вам не нужен.

Можете так же установить ту версию зенно, к которой есть бесплатные подсказки и пользоваться ими. Шаблон нужен только для обновления перевода таких подсказок к любой версии зеннопостер или используемым DLL. Перевести подсказки можно и самостоятельно, шаблон просто позволяет это сделать быстрее и в автоматическом режиме.
 
Последнее редактирование:

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)