Имя: Пароль:
1C
 
.Net в 1С. Парсинг сайтов, multipart/form-data, gzip итд
0 Serginio1
 
10.03.16
14:55
Выложил статьи
.Net в 1С. Асинхронные HTTP запросы, отправка Post нескольких файлов multipart/form-data, сжатие трафика с использованием gzip, deflate, удобный парсинг сайтов и т.д.  http://catalog.mista.ru/public/466052/

.Net в 1С. На примере использования HTTPClient,AngleSharp. Удобный парсинг сайтов с помощью библиотеки AngleSharp, в том числе с авторизацией аля JQuery с использованием CSS селекторов. Динамическая компиляция  http://catalog.mista.ru/public/466196/

Предыдущие темы

Использование классов .Net в 1С для новичков
Динамическая компиляция для использования .Net событий в 1С
1C Messenger для отправки сообщений, файлов и обмена данными между пользователям
v8: v8: Использование сборок .NET в 1С 7.x и 8.x

Там же можно найти все необходимые ссылки.
1 Serginio1
 
10.03.16
15:44
Кто ни будь прочитал до конца?
2 spock
 
10.03.16
15:50
И iframe сможет?
3 Serginio1
 
10.03.16
16:02
Не знаю, но там есть HtmlFrameElement
[DomName("HTMLIFrameElement")]
    public interface IHtmlInlineFrameElement : IHtmlElement
    {
        /// <summary>
        /// Gets or sets the frame source.
        /// </summary>
        [DomName("src")]
        String Source { get; set; }

        /// <summary>
        /// Gets the content of the page that the nested browsing context is to contain.
        /// </summary>
        [DomName("srcdoc")]
        String ContentHtml { get; set; }

        /// <summary>
        /// Gets or sets the name of the frame.
        /// </summary>
        [DomName("name")]
        String Name { get; set; }

        /// <summary>
        /// Gets the tokens of the sandbox attribute.
        /// </summary>
        [DomName("sandbox")]
        ISettableTokenList Sandbox { get; }

        /// <summary>
        /// Gets or sets if the seamless attribute has been set.
        /// </summary>
        [DomName("seamless")]
        Boolean IsSeamless { get; set; }

        /// <summary>
        /// Gets or sets if the frame's content can trigger the fullscreen mode.
        /// </summary>
        [DomName("allowFullscreen")]
        Boolean IsFullscreenAllowed { get; set; }

        /// <summary>
        /// Gets or sets the display width of the frame.
        /// </summary>
        [DomName("width")]
        Int32 DisplayWidth { get; set; }

        /// <summary>
        /// Gets or sets the display height of the frame.
        /// </summary>
        [DomName("height")]
        Int32 DisplayHeight { get; set; }

        /// <summary>
        /// Gets the document this frame contains, if there is any.
        /// </summary>
        [DomName("contentDocument")]
        IDocument ContentDocument { get; }

        /// <summary>
        /// Gets the frame's parent's window context.
        /// </summary>
        [DomName("contentWindow")]
        IWindow ContentWindow { get; }
    }
4 spock
 
10.03.16
16:16
Интересно
5 Serginio1
 
10.03.16
16:25
(4) Сегодня уже устал. Завтра посмотрю
6 Serginio1
 
10.03.16
16:40
(4) Вот такой код
WebsiteUrl = ПолучитьСтрокуЗапроса("http://catalog.mista.ru/public/466052/";);
    Клиент = Врап.СоздатьОбъект(HttpClient);
    Клиент.BaseAddress = Врап.СоздатьОбъект("System.Uri",WebsiteUrl);
    // Стоит отметить, что по умолчанию  HttpClient использует Cookie
    //Загрузим основную страницу
    res = Клиент.GetStringAsync("").Result;
    document = parser.Parse(res);
    // Найдем адрес страницы для авторизации
    
    фрейм= document.QuerySelector("iframe");
    Сообщить(фрейм.Source);

выдает

http://pastebin.com/embed_iframe/1kyhAdai
7 Serginio1
 
11.03.16
10:21
Надо отметить, что  QuerySelectorAll и QuerySelector можно применять к контейнерам поддерживающих интерфейс




    public interface IParentNode
    {
      
        int ChildElementCount { get; }
        IHtmlCollection<IElement> Children { get; }
        IElement FirstElementChild { get; }
        IElement LastElementChild { get; }
        void Append(params INode[] nodes);
        void Prepend(params INode[] nodes);
        IElement QuerySelector(string selectors);
        [DomName("querySelectorAll")]
        IHtmlCollection<IElement> QuerySelectorAll(string selectors);
    }
}






Мы можем например задать селектор для строки. Например получить первый и третий элемент строки


Строки =document.QuerySelectorAll(СелекторСтроки);
    
               Для Каждого стр из Строки Цикл
                //Ячейки=стр.Cells;
                 Ячейки=стр.QuerySelectorAll("th:nth-child(1),td:nth-child(3)");
                Для каждого Ячейка из Ячейки Цикл
                
                стрТз[сч]=Ячейка.TextContent;
            КонецЦикла
        КонецЦикла;
8 Serginio1
 
11.03.16
10:22
Добавлю еще про коллекци.  
public interface IHtmlCollection<T> : IEnumerable<T>, IEnumerable where T : IElement
    {
    
        T this[int index] { get; }
        T this[string id] { get; }
        int Length { get; }
    }



К ним можно обращаться по номерк и по иде или атрибуту. Например


Строки =document.QuerySelectorAll(СелекторСтроки);
ВтораяСтрока=Строки.get_Item(1);
9 Serginio1
 
11.03.16
11:48
Еще один вариант ускорения это заполнения данных 1С в скрипте

str = "public class ВычислительAngleSharp
    |{
     |public  static void ЗаполнитьТз(dynamic ТЗ)
     |   {
     |
     |
     |       var config = Configuration.Default.WithDefaultLoader();
     |       // Устанавливаем адрес страницы сайта
     |       var address = ""https://en.wikipedia.org/wiki/List_of_The_Big_Bang_Theory_episodes"";;
     |       // загружаем страницу и разбираем её
     |       var document = BrowsingContext.New(config).OpenAsync(address).Result;
     |       // Используем CSS селектор для получения строк таблицы с классом  и выбрать из этой строки 3 колонку
     |       var rowSelector = ""tr.vevent"";
     |       var Строки = document.QuerySelectorAll<IHtmlTableRowElement>(rowSelector);
     |       foreach (var str in Строки)
     |       {
     |           dynamic стрТз = ТЗ.Добавить();
     |           var ячейки = str.Cells;
     |           for (int i = 0; i < Math.Min(ячейки.Length, 8); i++)
     |           {
     |
     |               стрТз.Установить(i, ячейки[i].TextContent);
     |
     |           }
     |
     |
     |       }
     |
     |   }
    |}
|
|return  new Action<dynamic>(ВычислительAngleSharp.ЗаполнитьТз);";

            Каталог=Врап.ПолучитьТип("System.AppDomain").CurrentDomain.BaseDirectory;
            КаталогGAC = Path.GetDirectoryName(Врап.ТипКакОбъект(string).Assembly.Location);
            
            ПутьКДлл="d:\Vs2015Programs\ScriptApiDlls\ScriptApiDlls\bin\Debug\";
            КлассДляВычесленияВыражений=Врап.ПолучитьТипИзСборки("ScriptApiDlls.КлассДляВычесленияВыражений",ПутьКДлл+"ScriptApiDlls.dll");
          
            Опции=КлассДляВычесленияВыражений.Опции;

              scr = Опции
                .WithReferences(Каталог + "\AngleSharp.dll", КаталогGAC + "\Microsoft.CSharp.dll")
                //  .WithReferences(typeof(Configuration).Assembly)
                .WithImports("System", "AngleSharp", "AngleSharp.Dom.Html", "AngleSharp.Extensions");

               result = КлассДляВычесленияВыражений.Вычислить(str, scr);
              Тз=новый ТаблицаЗначений;
    Колонки=Тз.Колонки;
    Колонки.Добавить("НомерСерии");
    Колонки.Добавить("НомерСерииВСезоне");
    Колонки.Добавить("Название");
    Колонки.Добавить("Режиссер");
    Колонки.Добавить("Автор");
    Колонки.Добавить("Дата");
    Колонки.Добавить("Код");
    Колонки.Добавить("Просмотров");

    врап.ВыполнитьДелегат(result,Тз);
    
    тз.ВыбратьСтроку();
10 Serginio1
 
11.03.16
11:56
11 Serginio1
 
11.03.16
13:50
Странно, я думал, что парсинг затронет людей. Аналогичная тема  http://catalog.mista.ru/public/314045/ собрала кучу просмотро, оценок комментариев. Здесь тишина. Или CSS сложен или название .Net в заголовке пугает лбдей. Или парсинг HTML нынче не актуален?
12 Garykom
 
гуру
11.03.16
13:58
(11) "лбдей" все сложное пугает ))

была бы статья по типу берем сайту мисту и парсим ее с целью получения самых интересных тем
13 Serginio1
 
11.03.16
14:09
(12) Прошу прощения за опечатку. В примерах есть все, что бы это сделать самому. Кстати заодно вэб программисты могут помочь. Но почему то никого это не затронуло
14 torgm
 
11.03.16
14:11
Сейчас упали задачи написать парсеры для сайтов клиентов, самому лень.
15 Garykom
 
гуру
11.03.16
14:15
(13) пофиг на опечатку просто прикольная получилась ))

люди они сильно ленивые и хотят почти готовое которое можно тупо скопировать/вставить и чуток поправить

а не писать с 0 используя инструмент
16 Serginio1
 
11.03.16
14:44
(15) Так в примерах есть, как мне кажется достаточно материала, что бы использовать. Так я не против взять конкретную задачу и её решить. Только пусть дадут.
(14) Я помогу если что
17 Serginio1
 
11.03.16
16:00
(15) Вот например парсинг мисты
    handler = врап.СоздатьОбъект(HttpClientHandler);
    
    cookieContainer = Врап.СоздатьОбъект("System.Net.CookieContainer");
  
   handler.AutomaticDecompression=Врап.OR(DecompressionMethods.GZip,DecompressionMethods.Deflate) ;
      handler.CookieContainer=cookieContainer;
      cookieContainer.Add(Врап.СоздатьОбъект("System.Net.Cookie","__DDOS_COOKIE", "6c950441aeaf13f026a3aa8c0fee6df2", "/", "http://www.forum.mista.ru";));
   handler.UseCookies=истина;
//Pragma: no-cache
   Клиент = Врап.СоздатьОбъект(HttpClient,handler);
   DefaultRequestHeaders=Клиент.DefaultRequestHeaders;
  
   DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,*/*");

   WebsiteUrl = ПолучитьСтрокуЗапроса("http://www.forum.mista.ru.fiddler/";);
   Клиент.BaseAddress = Врап.СоздатьОбъект("System.Uri",WebsiteUrl);

            
    res = Клиент.GetStringAsync("index.php").Result;
    document = parser.Parse(res);
    
    селектор="table#tm td.ct";
    

    Ячейки= document.QuerySelectorall(селектор);
    
    Для каждого Ячейка Из Ячейки Цикл
        
        Аннотации=Ячейка.QuerySelectorall("a");
    Сообщить("=============================");    
Для каждого Аннотация Из Аннотации Цикл

Сообщить(Аннотация.TextContent+"="+Аннотация.PathName+Аннотация.Search);    

КонецЦикла;
        
    
    КонецЦикла;
Врап.ЗакрытьРесурс(HttpClient);
18 Serginio1
 
12.03.16
10:45
В статье добавил описание

Аннотация= document.QuerySelector("a.log-in");
    //Полный относительный путь Аннотация.PathName+Аннотация.Search
    // Но в данном случае Аннотация.Search просто нет
    // Если использовать BrowsingContext то полный путь содержится в Href

    res= Клиент.GetStringAsync(Аннотация.PathName).Result;
19 Serginio1
 
13.03.16
14:26
Один из основных интерфейсов

[DomName("Node")]
    public interface INode : IEventTarget, IMarkupFormattable
    {
        /// <summary>
        /// Gets a string representing the base URL.
        /// </summary>
        [DomName("baseURI")]
        String BaseUri { get; }

        /// <summary>
        /// Gets the base url.
        /// </summary>
        Url BaseUrl { get; }

        /// <summary>
        /// Gets a string containing the name of the Node. The structure of the
        /// name will differ with the name type.
        /// </summary>
        [DomName("nodeName")]
        String NodeName { get; }

        /// <summary>
        /// Gets a live NodeList containing all the children of this node.
        /// Being live means that if the children of the node change, the
        /// NodeList object is automatically updated.
        /// </summary>
        [DomName("childNodes")]
        INodeList ChildNodes { get; }

        /// <summary>
        /// Clones the node, and optionally, all of its contents.
        /// By default, it clones the content of the node.
        /// </summary>
        /// <param name="deep">
        /// Optionally: Sets if all of the content should be cloned as well.
        /// </param>
        /// <returns>The cloned node.</returns>
        [DomName("cloneNode")]
        INode Clone(Boolean deep = true);

        /// <summary>
        /// Determines if two nodes are equal.
        /// </summary>
        /// <param name="otherNode">
        /// The node to be compared to the node that is executing the method.
        /// </param>
        /// <returns>
        /// True if the node specified in the otherNode parameter is equal to
        /// the current node.
        /// </returns>
        [DomName("isEqualNode")]
        Boolean Equals(INode otherNode);

        /// <summary>
        /// Compares the position of two nodes in a document.
        /// </summary>
        /// <param name="otherNode">
        /// The node to be compared to the reference node, which is the node
        /// executing the method.
        /// </param>
        /// <returns>The relation between the two nodes.</returns>
        [DomName("compareDocumentPosition")]
        DocumentPositions CompareDocumentPosition(INode otherNode);

        /// <summary>
        /// Cleans up all the text nodes under this element, i.e. merges
        /// adjacent and removes empty text nodes.
        /// </summary>
        [DomName("normalize")]
        void Normalize();

        /// <summary>
        /// Gets the Document that this node belongs to. If no document is
        /// associated with it, returns null.
        /// </summary>
        [DomName("ownerDocument")]
        IDocument Owner { get; }

        /// <summary>
        /// Gets an Element that is the parent of this node. If the node has no
        /// parent, or if that parent is not an Element, this property returns
        /// null.
        /// </summary>
        [DomName("parentElement")]
        IElement ParentElement { get; }

        /// <summary>
        /// Gets a node that is the parent of this node. If there is no such
        /// node, like if this node is the top of the tree or if doesn't
        /// participate in a tree, this property returns null.
        /// </summary>
        [DomName("parentNode")]
        INode Parent { get; }

        /// <summary>
        /// Returns true if other is an inclusive descendant of the context
        /// object, and false otherwise (including when other is null).
        /// </summary>
        /// <param name="otherNode">The Node to check the childs for.</param>
        /// <returns>
        /// True if the given node is contained within this Node, otherwise
        /// false.
        /// </returns>
        [DomName("contains")]
        Boolean Contains(INode otherNode);

        /// <summary>
        /// Gets a Node representing the first direct child node of the node,
        /// or null if the node has no child.
        /// </summary>
        [DomName("firstChild")]
        INode FirstChild { get; }

        /// <summary>
        /// Gets a node representing the last direct child node of the node,
        /// or null if the node has no child.
        /// </summary>
        [DomName("lastChild")]
        INode LastChild { get; }

        /// <summary>
        /// Gets a Node representing the next node in the tree, or null if
        /// there isn't such node.
        /// </summary>
        [DomName("nextSibling")]
        INode NextSibling { get; }

        /// <summary>
        /// Gets a Node representing the previous node in the tree, or null if
        /// there isn't such node.
        /// </summary>
        [DomName("previousSibling")]
        INode PreviousSibling { get; }

        /// <summary>
        /// Indicates whether or not a namespace is the default namespace for a
        /// document.
        /// </summary>
        /// <param name="namespaceUri">
        /// The namespace to be compared to the default namespace.
        /// </param>
        /// <returns>
        /// True if the given namespace URI is the default for the current
        /// document.
        /// </returns>
        [DomName("isDefaultNamespace")]
        Boolean IsDefaultNamespace(String namespaceUri);

        /// <summary>
        /// Gets the Uniform Resource Identifier (URI) of the namespace
        /// associated with a namespace prefix, if any.
        /// </summary>
        /// <param name="prefix">The namespace prefix.</param>
        /// <returns>The URI of the namespace.</returns>
        [DomName("lookupNamespaceURI")]
        String LookupNamespaceUri(String prefix);

        /// <summary>
        /// Gets the namespace prefix associated with a Uniform
        /// Resource Identifier (URI), if any.
        /// </summary>
        /// <param name="namespaceUri">The URI.</param>
        /// <returns>The namespace prefix associated with the URI.</returns>
        [DomName("lookupPrefix")]
        String LookupPrefix(String namespaceUri);

        /// <summary>
        /// Gets an unsigned short representing the type of the node.
        /// </summary>
        [DomName("nodeType")]
        NodeType NodeType { get; }

        /// <summary>
        /// Gets or sets a string representing the value of an object. For most
        /// node types, this returns null and any set operation is ignored.
        /// </summary>
        [DomName("nodeValue")]
        String NodeValue { get; set; }

        /// <summary>
        /// Gets or sets the textual content of an element and all its
        /// descendants.
        /// </summary>
        [DomName("textContent")]
        String TextContent { get; set; }

        /// <summary>
        /// Gets an indicator if the element has any child nodes, or not.
        /// </summary>
        [DomName("hasChildNodes")]
        Boolean HasChildNodes { get; }

        /// <summary>
        /// Inserts a node as the last child node of this element.
        /// </summary>
        /// <param name="child">The node to be appended.</param>
        /// <returns>The appended Node.</returns>
        [DomName("appendChild")]
        INode AppendChild(INode child);

        /// <summary>
        /// Inserts the newElement immediately before the referenceElement.
        /// </summary>
        /// <param name="newElement">The node to be inserted.</param>
        /// <param name="referenceElement">
        /// The existing child element that will succeed the new element.
        /// </param>
        /// <returns>The inserted node.</returns>
        [DomName("insertBefore")]
        INode InsertBefore(INode newElement, INode referenceElement);

        /// <summary>
        /// Removes a child node from the current element, which must be a
        /// child of the current node.
        /// </summary>
        /// <param name="child">The child to be removed.</param>
        /// <returns>The removed node.</returns>
        [DomName("removeChild")]
        INode RemoveChild(INode child);

        /// <summary>
        /// Replaces one child node of the current one with the second one
        /// given in the parameters.
        /// </summary>
        /// <param name="newChild">The child to be inserted.</param>
        /// <param name="oldChild">The child to be removed.</param>
        /// <returns>The old node, if any.</returns>
        [DomName("replaceChild")]
        INode ReplaceChild(INode newChild, INode oldChild);
    }
20 Tarzan_Pasha
 
13.03.16
14:38
а это бесплатная?
21 Serginio1
 
13.03.16
15:21
22 Serginio1
 
13.03.16
15:21
23 spock
 
14.03.16
09:46
(0) Для моего понимания: а зачем есть необходимость парсить сайты с помощью 1с? Почему именно с помощью 1с? Это же жутко не удобно.
24 Serginio1
 
14.03.16
09:54
(23) C помощью .Net, но для получения данных в 1С.
25 Конченный УТырок
 
14.03.16
10:09
(24) А на этом можно как-то зарабатывать?
26 Serginio1
 
14.03.16
10:31
(25) Н на новый ComОбъект можно зарабатывать?
Расширяя функциональность 1С ты повышаешь свою производительность, а значит повышается твоя производительность итд.
27 spock
 
14.03.16
10:32
(24) И все же?
28 Конченный УТырок
 
14.03.16
10:40
(26) Какие-то общие слова. В 1С своих костылей хватает, нафига еще какой-то Net в голову засовывать? Проще направление сменить.
29 Garykom
 
гуру
14.03.16
10:41
(27) Понятие бритвы/лезвия Оккама знакомо?

Зачем плодить лишние сущности в виде каких то парсеров отдельных если данные нужно будет в 1С засунуть?

В данном случае .net используется для расширения возможностей 1С с помощью бесплатного фреймворка
30 Конченный УТырок
 
14.03.16
10:44
(29) Зачем плодить лишние сущности в виде фреймворка в 1С, если можно парсером выгрузить сайт в Ексел и загрузить в 1С?
31 Garykom
 
гуру
14.03.16
10:48
(30) Сущности "Парсер" и "Ексел" из воздуха взялись?
32 Gary417
 
14.03.16
10:51
...Особенно эксель который денег стоит...
33 Кирпич
 
14.03.16
11:00
(32) Ну вместо Ексел и текстовый файл подойдет. Он бесплатный. А по существу, всё равно, кому как удобнее, тот так и будет решать задачу. Мне так этот .NET пока нигде, ни разу не понадобился.
34 Serginio1
 
14.03.16
11:07
(30) Тем, что нужно делать значительно меньше телодвижений.
Каждый решает для себя как ему проще решить ту или иную задачу.
Для примера отправка multipart/form-data можно решить и на http://catalog.mista.ru/public/20017/

Про асинхронность я вообще промолчу.
Распарсить HTML легко и непринужденно с помощью AngleSharp очень легко. Аналогичная тема  http://catalog.mista.ru/public/314045/

Та же проблема с Вэб сервисами
Пример работы с web-сервисом через http запрос с куками :)
Помощь с Web сервисом
v8: soap:Header

Итд.
35 crocop
 
14.03.16
11:16
а выполнить любой javascript на странице может?
36 Serginio1
 
14.03.16
11:20
(35) Может но не полностью. Есть отдельная библиотека https://github.com/AngleSharp/AngleSharp.Scripting

Вот примеры с использованием JavaScript https://github.com/AngleSharp/AngleSharp/wiki/Examples
37 spock
 
14.03.16
11:26
(29) Мнение про общие фразы я тоже разделяю.

Почему я задаюсь вопросом о парсинге сайтов с помощью 1с?
Потому что я имею к этой темой непосредственное отношение и мне это знакомо. Мой выбор пал на такой стек: ubuntu + python + selenium + phantomjs + sqlite. В 1с может быть можно было бы местами проще, но этот стек крутится круглосуточно на vps и выдает мне сграбленные данные, когда я цепляюсь к этому сервису из 1с.
Причем этот стек проглатывает и js, и iframe'ы. Как будто открываю сайт из браузера.

Реализовать бюджетно такие задачи полностью на 1с сложно.

Оговорюсь: я не против .Net в 1с, я неожиданно удивлен тому, что кто-то пытается это сделать на 1с. Я к тому, что своим задачам, свой инструмент.
38 crocop
 
14.03.16
11:28
не очень силен в вебе, вот например сайт 5lb.ru необходимо спарсить, можно ли на этой страничке http://www.5lb.ru/catalog/bcaa.html нажать на кнопку "показать всё"
39 Garykom
 
гуру
14.03.16
11:29
(37) у вас немного не то, по сути поднят свой сервис парсинга и в подобном случае пилить еще что то в 1С уже лишнее, хватит загрузки csv

но если ситуация не грабать 24\7 и только из 1С причем изредка решение на 1С вполне рабочее
40 spock
 
14.03.16
11:30
(38) Не понятно к кому вопрос, но все же отвечу.  С помощью selenium можно.
41 Garykom
 
гуру
14.03.16
11:31
(38) можно даже штатными средствами 1С 8 без ВК и .net
42 spock
 
14.03.16
11:33
(41) как? о_О Интересуюсь профессионально.
43 Serginio1
 
14.03.16
11:34
(37) Угу легкое такое решение.
(38) Берешь в руки браузер и F12 и ислледуешь, то что тебе нужно. Пробуешь парсить с помощью AngleSharp
44 Serginio1
 
14.03.16
11:34
45 crocop
 
14.03.16
11:35
(41) штатными средствами? а есть пример кода?:)
46 spock
 
14.03.16
11:38
(44) там есть про "нажать на кнопку "показать всё"?". Коллега спрашивает, как нажать на кнопку. Мне тоже интересно, как это можно сделать штатно.
47 spock
 
14.03.16
11:42
+46 Кстати, в (17) дальше первой страницы тоже ничего не грабится.
48 Serginio1
 
14.03.16
11:43
(46) Распарсить файл. Найти форму
<form action="/cgi-bin/mp/page.pl" method="get

Установить значения формы и послать Get запрос. В статье это выглядит так

Форма=document.QuerySelector("form#searchform");
    ссылка=    Форма.Action;
    
    структура=новый структура;
    Для каждого Элемент Из Форма.Elements  Цикл
        Элем=Врап.ПолучитьИнтерфейс(Элемент,"IHtmlInputElement");
        //Нужны только Input элементы
        //Выберем все элементы Input
        // и запишем их имена и значения
        Если Элем<> Неопределено Тогда
            структура.Вставить(Элем.Name,Элем.Value);
            Сообщить(Элем.Name+"="+Элем.Value);
            
        КонецЕсли;
        
        
    КонецЦикла;        
    структура.search="Кириллица";
    // Если удалить fulltext то произойдет Redirect
    // структура.Удалить("fulltext");
    Врап.ВСтроку(Элемент);
    сб=Врап.СоздатьОбъект(StringBuilder,ссылка+"?");
    //var uri = new Uri(builder.ToString(), dontEscape: true);
    
    // Создадим строку запроса. Для метода Get
    // так как Форма.Method=""
    Для каждого стр Из структура  Цикл
        
       сб.AppendFormat("{0}={1}&",HttpUtility.UrlPathEncode(стр.Ключ),HttpUtility.UrlPathEncode(стр.Значение),0);
    
    КонецЦикла;
    
    стр=сб.ToString(0,сб.Length-1);
    Сообщить(стр);
    //Сделаем запрос по относительному пути
    //Так как основной путь уже прописан в BaseAddress
    res = Client.GetStringAsync(стр).Result;
49 spock
 
14.03.16
11:45
(43) Да, не легкое, но бюджетное решение. Кстати, именно эта нелегкость отталкивает и заставляет искать дополнительные пути решения.
50 Serginio1
 
14.03.16
11:45
(47) Переходи по ссылкам. А что мешает?
51 Serginio1
 
14.03.16
11:48
(49) Я предлагаю значительно более легкое решение. Правда пока в этой библиотеке не полностью реализован JavaScript.
А так с ограничениями очень легко парсить в стиле JQuery.
А приделают JavaScript полностью, то лучше ничего и не надо
52 Кирпич
 
14.03.16
11:48
да с этим парсингом сайтов только начни и закончишь "ubuntu + python + selenium + phantomjs + sqlite" как в (37)
53 Serginio1
 
14.03.16
11:49
51+ Я опять же ничего не навязываю. Я описываю инструмент. А нужен он, или нет каждый решает сам
54 Serginio1
 
14.03.16
12:34
Добавлю, что библиотека очень понравилась, тем что можно использовать CSS селекторы и использовать в стиле JQuery.
На самом деле их применять значительно проще чем регулярные выражения

http://anton.shevchuk.name/javascript/jquery-for-beginners-selectors

http://htmlbook.ru/css/nth-child

https://learn.javascript.ru/css-selectors

https://habrahabr.ru/post/51717/
55 crocop
 
14.03.16
12:46
(54) спасибо, будем пробовать
56 Shamandafil
 
14.03.16
13:08
(17) Что это за метод?
Врап.ЗакрытьРесурс(HttpClient);
57 Serginio1
 
14.03.16
13:42
(56) Это я в последней версии добавил
public void ЗакрытьРесурс(Object Oбъект)
        {
           object объект = AutoWrap.ПолучитьРеальныйОбъект(Oбъект);
            IDisposable d = объект as IDisposable;

            if (d != null) d.Dispose();

        }
58 Serginio1
 
14.03.16
15:48
(38) Приблизительно так
Client = Врап.СоздатьОбъект(HttpClient);
    Client.BaseAddress = Врап.СоздатьОбъект("System.Uri","http://www.5lb.ru/catalog/";);
    Стр="/cgi-bin/mp/page.pl?id=32&m=docs&producer_id=0&price_min=220&price_max=8520&select_rating=0&unit_6=1&min_6=114&max_6=1588&unit_4=1&min_4=20&max_4=25&unit_5=1&min_5=30&max_5=500&unit_7=1&min_7=12&max_7=40&unit_3=1&min_3=60&max_3=600&unit_1=1&min_1=12&max_1=12&unit_2=1&min_2=500&max_2=1000";
    //Стр="/cgi-bin/mp/page.pl?id=32&m=docs&producer_id=0&price_min=220&price_max=8520&unit_6=1&min_6=114&max_6=1588&unit_4=1&min_4=20&max_4=25&unit_5=1&min_5=30&max_5=500&unit_7=1&min_7=12&max_7=40&unit_3=1&min_3=60&max_3=600&unit_1=1&min_1=12&max_1=12&unit_2=1&min_2=500&max_2=1000;
    
    
    
// Тест строки с параметрами из фиддлера    
    res = Client.GetStringAsync(стр).Result;
    
    // Посмотрим результат
    // Можно посмотреть страницу используя например
    //http://filyanin.ru/8-vizualnyy-HTML-onlayn-redaktor.html
    Текст=Новый ТекстовыйДокумент;
    Текст.УстановитьТекст(res);
    Текст.Показать();

    
    res = Client.GetStringAsync("bcaa.html").Result;
    document = parser.Parse(res);

        
    Форма=document.QuerySelectorAll("form").get_Item(1);
    ссылка=    СокрЛП(Форма.Action);
        
//id=32&m=docs&producer_id=0&price_min=220&price_max=8520&select_rating=0&unit_6=1&min_6=114&max_6=1588&unit_4=1&min_4=20&max_4=25&unit_5=1&min_5=30&max_5=500&unit_7=1&min_7=12&max_7=40&unit_3=1&min_3=60&max_3=600&unit_1=1&min_1=12&max_1=12&unit_2=1&min_2=500&max_2=1000
//id=32&m=docs&available=1&price_min=220&price_max=8520&unit_6=1&min_6=114&max_6=1588&unit_4=1&min_4=20&max_4=25&unit_5=1&min_5=30&max_5=500&unit_7=1&min_7=12&max_7=40&unit_3=1&min_3=60&max_3=600&unit_1=1&min_1=12&max_1=12&unit_2=1&min_2=500&max_2=1000

    структура=новый структура;
    Для каждого Элемент Из Форма.QuerySelectorAll("input")  Цикл
        Элем=Врап.ПолучитьИнтерфейс(Элемент,"IHtmlInputElement");
        //Нужны только Input элементы
        //Выберем все элементы Input
        // и запишем их имена и значения
        
        Если ПустаяСтрока(Элем.Name) Тогда
           Продолжить;
        КонецЕсли;
    
        Если Элем<> Неопределено Тогда
            Сообщить(Элем.Name+"="+Элем.Value);

            структура.Вставить(Элем.Name,Элем.Value);
            
            
        КонецЕсли;
        
        
    КонецЦикла;         

    
    // Можно изменить значение
    //структура.price_max="3000";
    структура.Вставить("producer_id","0");
    структура.Вставить("select_rating","0");
    сб=Врап.СоздатьОбъект(StringBuilder,ссылка+"?");
    //var uri = new Uri(builder.ToString(), dontEscape: true);
    
    // Создадим строку запроса. Для метода Get
    // так как Форма.Method=""
    Для каждого стр Из структура  Цикл
        
        
        сб.AppendFormat("{0}={1}&",HttpUtility.UrlPathEncode(стр.Ключ),HttpUtility.UrlPathEncode(стр.Значение),0);
        
        
    КонецЦикла;

    
    стр=сб.ToString(0,сб.Length-1);
    Сообщить(стр);
    //Сделаем запрос по относительному пути
    //Так как основной путь уже прописан в BaseAddress
    res = Client.GetStringAsync(стр).Result;
    
    // Посмотрим результат
    // Можно посмотреть страницу используя например
    //http://filyanin.ru/8-vizualnyy-HTML-onlayn-redaktor.html
    Текст=Новый ТекстовыйДокумент;
    Текст.УстановитьТекст(res);
    Текст.Показать();
    
    document = parser.Parse(res);
59 romix
 
14.03.16
17:41
(0) А для компиляции примеров подойдет бесплатный VS 2013?
60 Serginio1
 
14.03.16
17:53
(59)
Что касается 1C примеров, то нужна просто Фреймворк 4.6.1

Что касается C# то в принципе да. Просто у меня сделано под 4.6.1 на VS 2015

Просто бесплатную 2015 можно скачать https://www.visualstudio.com/ru-ru/downloads/download-visual-studio-vs.aspx

А можно с  торрентов.
61 Garykom
 
гуру
14.03.16
17:55
(59) для готовой ВК от ТС даже VS не требуется, чтобы на C# и .Net прямо из 1С кодить
62 Gary417
 
14.03.16
18:17
Есть ещё SharpDevelop, она полегче чем монстроподобная VS

хотя VS конечно идеал...
63 Serginio1
 
15.03.16
11:42
(47) Все грабится

    ЭтоПервая = истина;
Для каждого Аннотация Из Аннотации Цикл

    Если ЭтоПервая Тогда
     ЭтоПервая=Ложь;
     res = Клиент.GetStringAsync(Аннотация.PathName+Аннотация.Search).Result;
      Сообщить(СтрДлина(res));
        
    
    КонецЕсли;
Сообщить(Аннотация.TextContent+"="+Аннотация.PathName+Аннотация.Search);    

КонецЦикла;
64 mistеr
 
15.03.16
12:08
(11) Писать шарповый код внутри строк это все-таки тупиковый путь. Напиши удобную нативную ВК и люди потянутся.

Плюс есть еще более фундаментальная причина. Распыляться на два стека, да еще таких разных - для разработчика неэффективно экономически.
65 oleg_km
 
15.03.16
12:23
(64) Плюс есть еще более фундаментальная причина. Распыляться на два стека, да еще таких разных - для разработчика неэффективно экономически.

Сидеть и балаболить на Мисте еще более неефективно. А нормальные программисты прекрасно сочетают и 1С и .NET.
66 Serginio1
 
15.03.16
12:49
(64) Писать ВК на все случаи жизни задолбаешься.
Весь смысл использовать классы .Net внутри 1С.
Ты же работаешь с Com объектами.

Вот сегодня понадобилась работа с реестром

рап=СоздатьОбъект("NetObjectToIDispatch45");
    врап.УстЭтоСемерка();
    

Registry=Врап.ПолучитьТип("Microsoft.Win32.Registry");

стр=Registry.GetValue(Ключ,"DefaultPrinter","");

Сообщить(стр);
......

Тут даже не нужно знать .Net. Есть куча примеров, уже многие кроме меня просто помогут кодом.

А вообще программист должен постоянно совершенствоваться. Так, что это не распыление
67 mistеr
 
15.03.16
13:43
(66) > Писать ВК на все случаи жизни задолбаешься.
Тем не менее учетные системы пишут на 1С, а не на голом C++ или C#. Высокоурочневые API всегда вытесняют низкоуровневые (за исключением особых случаев).

> Тут даже не нужно знать .Net. Есть куча примеров, уже многие кроме меня просто помогут кодом.

Копипастить чудой код, не понимая, что он делает? Ты серьезно предлагаешь это?

> А вообще программист должен постоянно совершенствоваться. Так, что это не распыление.

Еще какое распыление. Потратить то же время на прокачку, скажем, в ERP 2.0 или КД3, — намного выгоднее, чем научиться парсить сайты или читать реестр. Если вдруг понадобится, раз в год.

Пойми правильно, я сейчас не от своего имени говорю, а от имени "усредненного" 1С-ника. Который не ставит себе задачу стать гуру во всем, а просто хочет оставаться востребованным на рынке.
68 Serginio1
 
15.03.16
13:55
(67) Для того, что бы использовать ВК нужно читать документацию к ней. А вот использовать ВК тебе постоянно приходится для интеграции с внешним миром.
Если тебе нужно парсить сайты, то знание КД3 тебе ничем не поможет. Если у меня стоит задача то на stackoverflow.com/ куча примеров и документации на том же MSDN https://msdn.microsoft.com/ru-ru/library/microsoft.win32.registry_methods(v=vs.110).aspx

Усредненному 1С ку мало, что нужно. Он так же и копипастит 1С код. Просто есть огромный пласт задач, которые на 1С решить нельзя или это будет монструозный код.

Я просто предлагаю решение для увеличения производительности. А уж использовать его или нет каждый решает сам.
69 Garykom
 
гуру
15.03.16
13:57
(67) Примерно тоже самое уже пытался несколько раз сказать автору это замечательной штуки.
Что "среднему 1С-нику" нужна просто некая ВК в которой "есть все".

И вполне можно такое сделать написав "расширяемую ВК".
К которой можно легко написать плагины/дополнения.
Тогда останется только сделать механизм распространения этих дополнений.
70 Garykom
 
гуру
15.03.16
13:58
(68) Для обычного 1С-ника слова MSDN и stackoverflow это какие то ругательства
71 oleg_km
 
15.03.16
14:16
(69) Зачем делать расширяемую ВК, если ВК Сергея "расширяется" просто кодом 1С?
72 mistеr
 
15.03.16
14:28
(68) > Я просто предлагаю решение для увеличения производительности.

О какой производительности ты сейчас говоришь? Если о производительности радработки, доработки и поддержки, то ты жестоко ошибаешься.

Для производительности мне нужна ВК с API как у HTTPСоединение, только расширенным. Чтобы я мог написать:

ДокументРезультат = СуперПарсер.ОтправитьДляОбработки();
Таблица = ДокументРезультат.Таблицы[0];

А у этой таблицы API как у табличного документа, и я уже знаю как с ней работать. Если плюс к этому оно умеет и "JQuery с использованием CSS селекторов" - замечательно, но только как плюс.

Вот это будет увеличение производительности. Подумай об этом. Если этого не сделаешь ты, а спрос будет, то сделает кто-то другой.
73 Garykom
 
гуру
15.03.16
14:45
(71) а вот чтобы эти "расширения кодом 1С" можно было легко другим использовать готовые... а на заново с 0 писать изучив слегка .net
74 Serginio1
 
15.03.16
14:46
(72) Так у меня есть пример.
stopWatch = Врап.СоздатьОбъект("System.Diagnostics.Stopwatch");
    
        stopWatch.Start();

          Client = Врап.СоздатьОбъект(HttpClient);
              Client.BaseAddress = Врап.СоздатьОбъект("System.Uri","https://en.wikipedia.org";);
              res = Client.GetStringAsync("wiki/List_of_The_Big_Bang_Theory_episodes").Result;

              parser = Врап.СоздатьОбъект("AngleSharp.Parser.Html.HtmlParser");
             //Just get the DOM representation
             document = parser.Parse(res);
             СелекторСтроки = "tr.vevent";
    Тз=новый ТаблицаЗначений;
    Колонки=Тз.Колонки;
    Колонки.Добавить("НомерСерии");
    Колонки.Добавить("НомерСерииВСезоне");
    Колонки.Добавить("Название");
    Колонки.Добавить("Режиссер");
    Колонки.Добавить("Автор");
    Колонки.Добавить("Дата");
    Колонки.Добавить("Код");
    Колонки.Добавить("Просмотров");

     Строки =document.QuerySelectorAll(СелекторСтроки);

     stopWatch.Stop();
    Сообщить("Скачка и парсинг");
    ВывестиВремя(stopWatch,истина);
    
    
    stopWatch.Restart();


           Для Каждого стр из Строки Цикл
        сч=0;
        стрТз=Тз.Добавить();
        Ячейки=стр.Cells;
                
        Для каждого Ячейка из Ячейки Цикл
                
         стрТз[сч]=Ячейка.TextContent;
         сч=сч+1;
           Если сч=8 Тогда
            прервать
           КонецЕсли;
        КонецЦикла
       КонецЦикла;
        
    stopWatch.Stop();
    
    
    Сообщить("Время выполнения =");
    ВывестиВремя(stopWatch,истина);

    Тз.ВыбратьСтроку();
75 Serginio1
 
16.03.16
11:04
(33) Кстати РегЭкспы: как указать в паттерне исключение символа из результата
Может пригодится
Оппоненты говорят РегЭкспы: как указать в паттерне исключение символа из результата

что у них не проходит. Вот где и .Net можешь применить
76 Serginio1
 
24.03.16
15:02
В составе AngleSharp.Scripting для парсинга сайтов с использованием JS
https://github.com/AngleSharp/AngleSharp/wiki/Examples

Есть парсер
https://github.com/sebastienros/jint

Вот пример использования

Engine=врап.ПолучитьТипИзСборки("Jint.Engine","d:\Vs2015Programs\WpfApplication1\WpfApplication1\bin\Debug\Jint.dll");
    JsValue=врап.ПолучитьТип("Jint.Native.JsValue");
      jint =  Врап.СоздатьОбъект (Engine);

            html = "
            |var o = { };
            |o.Foo = 'bar';
            |o.Baz = 42.0001;
            |o.Blah = o.Foo + o.Baz;
            |o.B64='YWRtaW5AbG9jYWxob3N0OnNlY3JldAo==';
            |o.Int =5;
            |if (o.Blah != 'bar42.0001') throw TypeError;
            |
            |function fib(n){
            |    if (n < 2)
            |    {
            |        return n;
            |    }
            |
            |    return fib(n - 1) + fib(n - 2);
            |}
            |
            |if (fib(3) != 2) throw TypeError;
            |";

            jint.Execute(html);
            o = jint.GetValue("o").ToObject();

            Baz = o.Baz;
            Сообщить(Baz);
            Сообщить(o.Blah);
            Сообщить(o.Int);            
            BitConverter=Врап.ПолучитьТип("System.BitConverter");
            Convert  =Врап.ПолучитьТип("System.Convert");
            data = Convert.FromBase64String(o.B64);
                        Сообщить(BitConverter.ToString(data));
           // int ii = o.Int;

            fib = jint.GetValue("fib");
            
            double5=Врап.ChangeType("System.Double",5);
            double5=Врап.СоздатьОбъект(JsValue,double5);
            Фиб5=врап.ВыполнитьМетод(fib,"Invoke",double5).AsNumber();

        //    Фиб5=fib.Invoke(double5).AsNumber();
            Сообщить(Фиб5);
77 Serginio1
 
24.03.16
15:04
Можно передавать свои объекты и и использовать их при выполнении скриптов

html = @"
var document = { };
document.cookie = '__DDOS_COOKIE =6c950441aeaf13f026a3aa8c0fee6df2; max-age=604800; path=/';
          ";

            jint.Execute(html);
            dynamic document = jint.GetValue("document").ToObject();
            textBox.AppendText(document.cookie.ToString() + Environment.NewLine);

            html = @"document.cookie = '__DDOS_COOKIE =6c950441aeaf13f026a3aa8c0fee6df2; max-age=604800; path=/';
            var nc = function() {
                return
document.cookie.indexOf('__DDOS_COOKIE=6c950441aeaf13f026a3aa8c0fee6df2') == -1;
            };
            var w = function() { document.body.innerHTML = document.getElementsByTagName('noscript')[0].textContent; };
            if (!window.opera)
            {
                if (!nc()) { window.location.reload(true); }
                var r = function() { if (nc()) w(); };
            }
            else {
                var r = function() {
                    if (!nc()) { window.location.reload(true); }
                    else { w(); }
                }
            }";

            dynamic document1 = new ExpandoObject();
            document1.cookie = "";
            document1.body= new ExpandoObject();
            dynamic window= new ExpandoObject();
            window.opera = false;
            window.location = new ExpandoObject();
            window.location.reload = (Action<bool>)((r) => { });

            jint.SetValue("document", document1);
            jint.SetValue("window", window);

            jint.Execute(html);
          
            textBox.AppendText(document1.cookie.ToString() + Environment.NewLine);
78 Serginio1
 
13.04.16
09:56
Проверил работают такие конструкции поиска

Поиск div с id начинающихся на "row"
СелекторСтроки = "div[id^=row]";

Найти аннотацию с классом pagenav и содеращую текст 'Вперёд'
a.pagenav:contains('Вперёд')
79 Serginio1
 
26.04.16
10:17
Я бы еще добавил Silenium прежде всего как построитель DOM в заскриптованных таблицах http://www.seleniumhq.org/docs/05_selenium_rc.jsp#c
http://scraping.pro/example-of-scraping-with-selenium-webdriver-in-csharp/

Для того что бы добраться до сформированного DOM можно использовать вместо PageSource
вычисляемый скрипт

http://stackoverflow.com/questions/26584215/selenium-page-source-does-not-return-modified-dom-tree

var pageSource = (string)driver.ExecuteScript("return document.body.outerHTML");
Основная теорема систематики: Новые системы плодят новые проблемы.