|   |   | 
| 
 | .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 | 
        Вот ссылка на DLL http://files.rsdn.ru/19608/AndleSharpScriptDlls.zip     | |||
| 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"); | 
 
 | Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |