Быстрый старт проектов, готовое решение! Ускоряем разработку с помощью OwnCode и методов расширения!

Решил основательно затестить предложенный проект. Но, почему-то выдает, что "Collection of Products not Found:". Начал копать глубже. Увидел вот это:
56956


Это повторяющиеся пути. Так и надо? Или причина "Collection of Products not Found:" именно в этом? XPath все рабочие. Кроме пагинации, в моем случае всего одна страница и этого элемента просто нет.
 
Последнее редактирование:
странно в перовм пишет коллекция , очевидно будут получать коллекцию тегов ,
во втором просто тег
там где урл пишети в коментах тег href очевидно будут получать ссылку , а выше имя , ну както так .
 
Это повторяющиеся пути. Так и надо?
Спасибо, что обратили внимание. При написании проекта, я по списку для каждой переменной с данными подбирал xPath. В нашем случае, для url мы собираем атрибут href. Что касается p_li, то можете её удалить, она не используется в проекте.

Но, почему-то выдает, что "Collection of Products not Found:"
Как предположение, выдача продуктов может зависеть от гео, либо может быть проблема с прокси. Проверил только что, все пять категорий из текстового файла спарсились.
 
Спасибо, что обратили внимание. При написании проекта, я по списку для каждой переменной с данными подбирал xPath. В нашем случае, для url мы собираем атрибут href. Что касается p_li, то можете её удалить, она не используется в проекте.


Как предположение, выдача продуктов может зависеть от гео, либо может быть проблема с прокси. Проверил только что, все пять категорий из текстового файла спарсились.
Без прокси есть выдача. Я включил еще режим дебаг. Парсит. Но выход по ошибке в результате и база не заполняется:
"Выполнение действия CSharp OwnCode. Значение не может быть неопределенным. Имя параметра: path". Мне не хватает отладочной информации. Место, где происходит сбой в общем коде не определить, так как нет ссылки даже на приблизительное место.
 
не не хватает отладочной информации.
Предположу, проблема в Proxy.Return. Я забыл отладить возврат, на случай, если не используются прокси. Можно пофиксить простой проверкой:
C#:
Развернуть Свернуть Копировать
if (t._is.b_useProxy) Files.Writer(t, Locker.FileProxy, t._is.FilePath_Proxy, t._ts.proxy);
 
  • Спасибо
Реакции: Nike59
Предположу, проблема в Proxy.Return. Я забыл отладить возврат, на случай, если не используются прокси. Можно пофиксить простой проверкой:
C#:
Развернуть Свернуть Копировать
if (t._is.b_useProxy) Files.Writer(t, Locker.FileProxy, t._is.FilePath_Proxy, t._ts.proxy);
А в какое место вставить этот код? Я попробовал поставить в метод public static void Writer, но результат не изменился. Потом обернул в if здесь:


Выполнение зависло. Хотя напарсило много. Таблица не щаполнена.
C#:
Развернуть Свернуть Копировать
public static void Return (z t)
        {
            if (t._is.b_useProxy) Files.Writer(t, Locker.FileProxy, t._is.FilePath_Proxy, t._ts.proxy);
            //Files.Writer(t, Locker.FileProxy, t._is.FilePath_Proxy, t._ts.proxy);
           
        }
 
Последнее редактирование:
Все сработало как надо. Просто нужно еще смотреть, чтобы файл task.txt на начало работы скрипта был в исходном состоянии со всеми категориями. Во время работы шаблона он удаляет строки. Спасибо! Попробую теперь запилить свой парсер другого ресурса, используя твой подход с обшим кодом!
 
  • Спасибо
Реакции: RoyalBank
Спасибо! Попробую теперь запилить свой парсер другого ресурса, используя твой подход с обшим кодом!
Отлично, пиши если нужна помощь или возникнут вопросы!
 
  • Спасибо
Реакции: Nike59
Отлично, пиши если нужна помощь или возникнут вопросы!

Не почтите за хамство, но местами вы строите лишние конструкции кода, вот к примеру:
Проверка существования элемента:
Развернуть Свернуть Копировать
public static bool IsVoid_e (this Tab tab, string xpath, int num = 0, bool b = false)
{
    if (!tab.FindElementByXPath(xpath,0).IsVoid) b = true;
    return b;
}

Зачем параметр по умолчанию, bool b = false ?

Это не пусто?:
Развернуть Свернуть Копировать
if (!tab.FindElementByXPath(xpath,0).IsVoid) b = true; // Нет, не пусто!
return false; // Пусто!

А еще не понятно, зачем в каждый метод дублировать текущий поток?

Главный поток:
Развернуть Свернуть Копировать
class Main
{
    MyClass myClass;
    public Main(Instance Instance, IZennoPosterProjectModel Project)
    {
        myClass = new MyClass(this);
    }
}

Композиция:
Развернуть Свернуть Копировать
class MyClass
{
    void Method(Main currThread, param args)
    {
        // какая то реализация
    }
    void Method2(Main currThread, param args)
    {
        // какая то реализация
    }

    public MyClass(Main currThread)
    {
        // присвоить по умолчанию
    }
}

Из статьи
МИФ: КОД БЫСТРЕЕ КУБИКОВ

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

Инстранцируя главный объект, он знает обо всей архитектуре, то есть все сразу загружается в память, но при этом, половина всего из, ему возможно не нужна.

Пример аналогии:
Человек, Гардероб, Одежда в гардеробе (головной убор, верхняя одежда, штаны, обувь).

Задача:
Нужно одеть человека, чтобы он пошел гулять. Когда он ушел гулять, зачем ему помнить, что у него еще в гардеробе? Если только не переодеться, но это нужно возвращаться домой, лесть в гардероб и пр., но этим управляет программист.

Алгоритм:
То есть, инстанцировали человека, инстанцировали те предметы, необходимых вещей (кепка, кофта, штаны, куртка, ботинки), отправили человека, возможно по пути стало жарко, он снял куртку (убили экземпляр) и продолжает идти уже без куртки.
 
Последнее редактирование:
  • Спасибо
Реакции: Metrix
Не почтите за хамство, но местами вы строите лишние конструкции кода
Я за обсуждение любых вопросов по шаблону, пишите :)

- Лишние конструкции в коде.
Этот шаблон не написан исключительно для конкурса, шаблон представляет развитие с течением времени, подходов и методов. Именно по этой причине в шаблоне можно встретить реализации оставшиеся с давних времен.

Безусловно, если подобный формат не приносит эстетического удовольствия при просмотре, то можно выкинуть объявление bool, и заменить на этот формат:

C#:
Развернуть Свернуть Копировать
public static bool IsVoid_e (this Tab tab, string xpath, int num = 0)
{
    if (!tab.FindElementByXPath(xpath,num).IsVoid) return true;
    return false;
}


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

Я буду признателен, если вы поделитесь более эффективным подходом.
 
  • Спасибо
Реакции: Маломальский
Автосвойства:
Развернуть Свернуть Копировать
class z
{
public Instance instance { get; set; }
public IZennoPosterProjectModel project { get; set; }

public Tab tab { get; set; } // Объявляем Tab

// Объявляем HtmlDocument, Stopwatch, Random
public HtmlDocument node { get; set; }
public Stopwatch timer { get; set; }
public RNG rnd { get; set; }

// Объявляем Классы
public _pm _pm { get; set; }
public _is _is { get; set; }
public _ts _ts { get; set; }
public _pd _pd { get; set; }

public Lists Lists { get; set; }
public log log { get; set; }

При объявление полей, таким образом, вы создали 24 полноценных метода.

Авто null:
Развернуть Свернуть Копировать
public Instance instance; // not { get; set; }
// т.д.
К прочтению: https://habr.com/ru/post/354046/
 
При объявление полей
Все верно, они объявлены, т.к. используются в работе проекта, если какой-то метод не требуется, к примеру tab или Stopwatch, то его можно не объявлять. Шаблон - это заготовка, которая подстраивается под каждый отдельно взятый проект, как кусок глины из которого вы лепите вазы любой формы.

Спасибо за статью, и рекомендации, ознакомлюсь и протестирую.
 
Если вам не лень, посмотрите, я чуть подправил и пояснил логику.
П.С. Надеюсь, моя рекомендация, не изменит теплые отношения)) Я сам еще учусь :-)
 

Вложения

  • 13.xmlz
    13.xmlz
    108,3 KB · Просмотры: 256
Последнее редактирование:
  • Спасибо
Реакции: Nike59 и RoyalBank
не изменит теплые отношения
Не изменит, тут каждый делится своим опытом, внося вклад в развитие сообщества :) Принял на вооружение первый метод, когда есть из чего выбирать - это хорошо для всех.
 
  • Спасибо
Реакции: Маломальский
Огромное спасибо за пример и пояснение работы общего кода. Как раз была идея сделать примерно тоже самое на временных списках, с проверками по наличию элементов на страницах, а так же дебагом в OwnCode, только здесь на % 30 реализация шире. Свои переменные, которые можно генерить и править пачками, новые варианты написания более короткого кода, много чего дошло по ходу изучения вашего кода, что никак не мог понять сам при изучении C#. В общем 10й раз захотел дочитать книжку) Без нормальных знаний C# такие шаблоны на 1500 строк нормально и быстро администрировать и масштабировать просто не получится. Однозначно проголосовал, надеюсь статья займет первое место. Фундаментально переоценить значимость такого материала для роста в C# и написании универсальных шаблонов просто невозможно, ИМХО навряд ли что-то будет глобально полезней в статьях.

На будущее хотелось бы видеть статьи по работе с БД, например сохранение и загрузка профилей ЗП из/в БД, а не стандартные архивы.

И есть пара вопросов:

1. Как правильно подключать HtmlAgilityPack + System.Xml? В Using и OwnCode подключен только HtmlAgilityPack. В GAC => видно, что подключен так же System.Xml, хотя в GAC можно подключать только .dll судя по единственно возможному варианту расширения при подключении библиотек GAC. Что это за System.Xml, откуда он берется и как подключается?

2. Почему все типы данных в таблице БД TEXT, а Url_Image и Stock INTEGER?

Ещё раз огромное спасибо за работу, которой поделились с новичками)
 
Последнее редактирование:
Что это за System.Xml, откуда он берется и как подключается?
Добавляете dll в GAC - через поиск, верхняя колонка Название, пишите xml, и выбираете версию 4.0.0.0
Добавить ссылку на сборку 2020-05-29 14.12.14.png

2. Почему все типы данных в таблице БД TEXT, а Url_Image и Stock INTEGER?
Это пример, как можно присваивать формат данных text/integer, для запроса к базе, через String.Format, чтобы не прописывать в самом запросе "Url_Image INTEGER, Status TEXT".
 
  • Спасибо
Реакции: GarryVeles
Это пример, как можно присваивать формат данных text/integer, для запроса к базе, через String.Format, чтобы не прописывать в самом запросе "Url_Image INTEGER, Status TEXT".

Супер, понял про System.Xml, спасибо!

Про String.Format я сразу понял, да это действительно удобно, просто там в колонке Url_Image тоже вроде как текст должен быть по логике как и в Url_Product, а не целочисленные данные, а в Stock возможно правильней BOOLEAN, т.к. возможны только 2 значения Out of Stock и (-).
Но, если там просто типы данных для примера, то ясно.
 
Но, если там просто типы данных для примера, то ясно.
Я просто не придал этому значения, когда составлял шаблон :) Спасибо за ваш отзыв и пожелания, пожалуйста, спрашивайте, любые вопросы.
 
Шаблон обновлён по просьбе автора, архив перезалит.
 
  • Спасибо
Реакции: RoyalBank
Отличная статья! Правда не поняла много чего, буду к ней возвращаться, думаю, еще не раз. Спасибо. Вот только, музыка в фоне, в таком видео - лишнее, мешает сосредоточиться.
 
  • Спасибо
Реакции: RoyalBank
@RoyalBank подскажи как внедрить в общий код чужую библиотеку ... я сейчас в каждый метод, где она нужна, пишу приблизительно следующее Lib.Helper helper = new Lib.Helper(t.instance, t.project) ... как ее проще в методы передавать?

и еще, когда я отлаживаю код пошагово, и при этом, у меня свернуты регионы выше точки останова, то при заходе в общий код меня кидает в самый низ страницы ... я подымаюсь к точке останова, делаю следующий шаг и меня опять перебрасывает вниз страницы ... как с этим бороться?
 
как ее проще в методы передавать?
Должно быть достаточно в using прописать и объявить в главном классе "z", дальше работаешь с ней из любой точки кода. Это позволит обращаться к хелперу из потока t.helper.

C#:
Развернуть Свернуть Копировать
public class z
{
    public Lib.Helper helper;
}
public z
{
    helper = new Lib.Helper();
}

По точкам останова не подскажу, не пользуюсь ими, отлаживаю через запуск потока в кубике. Он покажет все ошибки в коде. Если явных ошибок нет, то отлавливаю во время работы, основные методы завернуты в try/catch.
C#:
Развернуть Свернуть Копировать
z t = new z(instance,project);
 
  • Спасибо
Реакции: intagens
@RoyalBank , подскажи в чем может быть проблема с БД.

В логе: [FastSqliteHelper.DeInit]: 'Соединение уже закрыто/ещё не открыто'. Last query: ''
В Bug Reports:
Exception Message :: SQLite.Insert() Exception: [[FastSqliteHelper.Init]: 'Ошибка подключения к БД: Была сделана попытка загрузить программу, имеющую неверный формат. (Исключение из HRESULT: 0x8007000B)'. Last query: ''. Строка подключения: Data Source=C:\13\db\Warehouse.sqlite3;Version=3;Journal Mode=WAL;];
 
Проверь, если все библиотеки скопировались с заменой.
Да, существующие библиотеки заменил твоими. Пробовал на разных версиях 5.41.1.0, 5.43.0.0, 7.1.4.0 - всё тоже.
Ладно, буду разбираться. Отпишусь по результатам.
 
Ладно, буду разбираться. Отпишусь по результатам.
Проверь если установлены C++ 86/64 за 2008, 2010, 2012, 2013, 2015-2019 и фреймворк 3,5 если включен.
Возможно, автор библиотеки @Lord_Alfred, сталкивался с подобной ошибкой и подскажет решение.
 

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