|
.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"); |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |