0. Serginio 799 09.03.16 14:39 Сейчас в теме

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

Часто приходится парсить сайты, в том числе с авторизацией, перескакивая со страницы на страницу по ссылкам.
Тот, кто занимался вэб программированием, знает, как удобно использовать JQuery и CSS селекторы. На .Net написана очень удобная библиотека AngleSharp.
Я покажу, как с её помощью можно значительно облегчить себе труд.

Перейти к публикации

Комментарии
Избранное Подписка Сортировка: Древо
1. Serginio 799 11.03.16 11:50 Сейчас в теме
Я уже не буду перегружать статью. Но можно использовать скрипты для заполнения данных 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,Тз);
	
	тз.ВыбратьСтроку();
Показать
2. YPermitin 5827 11.03.16 13:55 Сейчас в теме
(1) классные статьи, тоже интересная.

Но есть парочку НО:
1. Материал подается в неудобочитаемом виде.
2. Мало практических примером, близких к реальности.

ИМХО. Без обид.
Gureev; yarsort; +2 Ответить
3. Serginio 799 11.03.16 14:40 Сейчас в теме
(2) Спасибо. Может подкинешь идею? Могу в свободное время взяться за конкретный пример или кому то помочь с реальной задачей
4. invertercant 22 11.03.16 16:11 Сейчас в теме
(3) я был бы рад увидеть статью про валидаторы данных применительно к 1с, особенно приятно если бы это получилось хорошо. Понимаю что тема большая, но хоть что то. Вот например по этой тематике https://habrahabr.ru/post/246521/
5. Serginio 799 11.03.16 16:21 Сейчас в теме
(4) Да уж. Можно смотреть на валидаторы внутри ASP.Net MVC. Там генерятся валидаторы как на JavaScript так и на уровне HTML5
http://stephenwalther.com/archive/2012/03/13/html5-form-validation
6. invertercant 22 11.03.16 16:56 Сейчас в теме
(5) У тебя по ссылке валидация форм, хотя хотелось бы иметь валидацию произвольных данных. На входе - произвольный набор проверяемых данных и правила которым он должен удовлетворять. На выходе - ошибки, если есть. Если ошибок нет - валидация прошла успешно. Например, ты грузишь что то из какого нибудь excel или внешней базы и надо чтобы данные удовлетворяли определенным условиям. Часто фарш в данных обнаруживается значительно позднее чем мог бы.
14. YPermitin 5827 14.03.16 08:58 Сейчас в теме
(3) можно написать обработку, которая сжимает или приводит к одному виду изображения в базе с помощью средств .NET платформы, да еще и Parallel прикрутить для ускорения.
Еще было бы интересно рассказать про стандартные возможности .NET'а слежения за изменением в каталоге, передача файлов по сети с помощью фоновой интеллектуальной службы BITS (Windows).

Может об этом уже писали конечно, не искал специально.
15. Serginio 799 14.03.16 09:51 Сейчас в теме
(14) Большое спасибо за совет.
.NET(C#) для 1С. Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия
Там есть подписка на события System.IO.FileSystemWatcher

Насчет картинок была статья Elisy Обработка изображений 1С средствами .Net framework
Я на мисте предлагал http://www.forum.mista.ru/topic.php?id=758131&page=3#229
Но как то мало это народ интересует.
Нужны какие то простые, но понятные примеры типа Строка в дату. Универсальное решение. Применение NetObjetToIDispatch45
http://www.forum.mista.ru/topic.php?id=763810&page=1

Например больше всего популярностью пользуется Использование классов .Net в 1С для новичков
Главное заинтересовать, а там дальше пойдет.
dima.jung; +1 Ответить
30. Denanhel 05.10.18 19:48 Сейчас в теме
(15) Пилил сжатие изображений.

ИмяВходногоФайлаКартинки - путь к файлу картинки
		
ИмяВыходногоФайлаКартинки = ПолучитьимяВременногоФайла(".jpg")

Врап = новый COMОбъект("NetObjectToIDispatch45");  		
			
Picture = Врап.СоздатьОбъект("System.Drawing.Bitmap", ИмяВходногоФайлаКартинки);
			
Множитель = Макс(Число(Picture.Height), Число(Picture.Width)) / 500;

Если Множитель >= 1 Тогда
	nPicture = Врап.СоздатьОбъект("System.Drawing.Bitmap", Picture, Цел(Picture.Width/Множитель), 
        Цел(Picture.Height/Множитель));
        Picture.Dispose();
        nPicture.Save(ИмяВыходногоФайлаКартинки); 
        nPicture.Dispose();
Показать

КонецЕсли;

Режет картику до размера 500 пикселей на сколько-то там.... Ну исходя из начального размера. Если размер меньше 500 пикселей то оставляет как есть, жмет неплохо, качество не теряется, быстро и сердито, можно красивее, но нужно было сделать что-то быстро, а потом оказалась и так неплохо.
20. Serginio 799 24.03.16 15:16 Сейчас в теме
В составе 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);
Показать
16. Serginio 799 15.03.16 10:36 Сейчас в теме
Еще один пример парсинга


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&sele­ct_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&u­nit_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);
		

	структура=новый структура;
	Для каждого Элемент Из Форма.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);
Показать
8. invertercant 22 11.03.16 17:15 Сейчас в теме
(7) Это была идея для статьи чтобы не придумывать велосипед, а взять готовый на NET, если такой существует.
9. Serginio 799 11.03.16 17:19 Сейчас в теме
(8) Они существуют. Только не универсальные. XML, HTML, C# итд.
10. Serginio 799 11.03.16 17:29 Сейчас в теме
Что касается LIVR то прочтя https://github.com/koorchik/LIVR вроде как на .Net нет библиотеки
11. Serginio 799 11.03.16 20: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/";

   Клиент.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);
Показать
12. Serginio 799 12.03.16 10:44 Сейчас в теме
Обратите внимание
Аннотация= document.QuerySelector("a.log-in");
    //Полный относительный путь Аннотация.PathName+Аннотация.Search
    // Но в данном случае Аннотация.Search просто нет
    // Если использовать BrowsingContext то полный путь содержится в Href

    res= Клиент.GetStringAsync(Аннотация.PathName).Result;
13. Serginio 799 13.03.16 14:28 Сейчас в теме
Один из основных интерфейсов

 [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 upd ated.
        /// </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; se t; }

        /// <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);
    }
Показать
17. Гость 18.03.16 15:55
Подскажите, пожалуйста, где взять файл AngleSharp.dll?
18. Serginio 799 18.03.16 15:57 Сейчас в теме
(17) http://files.rsdn.ru/19608/AndleSharpScriptDlls.zip

Но за версиями лучше следить здесь https://www.nuget.org/packages/AngleSharp/
https://anglesharp.github.io/
Кстати новая версия вышла. Проверю. Обновил
19. Гость 21.03.16 12:51
Спасибо! А то скачал сборку с Гитхаба, а как ее использовать не понял..
21. Serginio 799 24.03.16 15:17 Сейчас в теме
Можно передавать свои объекты и и использовать их при выполнении скриптов . Пример на C#




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>)(® => { });

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

            jint.Execute(html);
           
            textBox.AppendText(document1.cookie.ToString() + Environment.NewLine);
Показать
22. Serginio 799 13.04.16 09:57 Сейчас в теме
Проверил работают такие конструкции поиска

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


Найти аннотацию с классом pagenav и содеращую текст 'Вперёд'
a.pagenav:contains('Вперёд')
23. Serginio 799 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");
27. quick 573 23.05.17 23:04 Сейчас в теме
(23) Сергей дело говорит, selenium часто спасает. Правда я его юзаю через python, но какая разница.
Никогда не мог понять зачем делать парсер в 1С, если можно на том же .NET написать нормальный парсер и юзать его через тот же SOAP как веб сервис. А если потребуется парсить в несколько потоков или т.д.? Для чего жопаболь с 1С-языком?
31. Denanhel 05.10.18 19:57 Сейчас в теме
(23) Может кому будет полезным.


Процедура GZIPРаспаковать(вхФайл, исхФайл, МассивОшибок) Экспорт
	
	Попытка
		Врап = новый COMОбъект("NetObjectToIDispatch45");	
		MemoryStream = Врап.ПолучитьТип("System.IO.MemoryStream");
	    UTF8 = Врап.ПолучитьТип("System.Text.Encoding").UTF8;
	    CompressionMode = Врап.ПолучитьТип("System.IO.Compression.CompressionMode");
		FileMode = Врап.ПолучитьТип("System.IO.FileMode"); 			
		
		ПотокСжатыхДанных = Врап.СоздатьОбъект("System.IO.FileStream", вхФайл, FileMode.OpenOrCreate);
		GZipПоток = Врап.СоздатьОбъект("System.IO.Compression.GZipStream", ПотокСжатыхДанных, CompressionMode.Decompress);
		ПотокРазжатыхДанных = Врап.СоздатьОбъект("System.IO.FileStream", исхФайл, FileMode.OpenOrCreate);
		GZipПоток.CopyTo(ПотокРазжатыхДанных);     		
			
		ПотокСжатыхДанных.Close();
		GZipПоток.Close(); 
		ПотокРазжатыхДанных.Close();
	Исключение
		МассивОшибок.Добавить("Не удалось распаковать данные" + " " + ОписаниеОшибки()); 
		Возврат;
	КонецПопытки;
КонецПроцедуры

Показать
24. Serginio 799 01.06.16 21:22 Сейчас в теме
Для получения атрибута нужно применить следующий код

Картинки = doc.QuerySelectorAll("img[src]");

Для каждого стр из Картинки Цикл
	адрес=Врап.ПолучитьИнтерфейс(стр,"IElement").GetAttribute("src");
	
КонецЦикла
25. user650124_dao-piglet 09.12.16 18:43 Сейчас в теме
Сергей, подскажите плиз, что не так в этом коде?
Объекты HttpClient и HttpRequestMessage создаются.
А дальше нужно добавить к запросу Method и RequestUri - это не получается.
(В C# аналогичный код работает)

ХТТПЗапрос.RequestUri = Врап.СоздатьОбъект("System.Uri", адрес);
HttpMethod = Врап.ПолучитьТипИзСборки("System.Net.Http.HttpMethod", "System.Net.Http.dll");
ХТТПЗапрос.Method = HttpMethod.Get;

И в 1-й и в 2-й строках одинаковая ошибка:
Произошла исключительная ситуация (mscorlib): Exception has been thrown by the target of an invocation.

Получение System.Uri видел у Вас здесь и в других публикациях. HttpMethod попробовал методом тыка.
26. Serginio 799 10.12.16 18:22 Сейчас в теме
А зачем для Get нужен какой то метод. Используй нужные методы с Get
Вот здесь куча примеров
.Net в 1С. Асинхронные HTTP запросы, отправка Post нескольких файлов multipart/form-data, сжатие трафика с использованием gzip, deflate, удобный парсинг сайтов и т.д.

Используй HTTPClient . он более продвинутый. У меня все примеры с ним.
29. s_vidyakin 06.08.18 13:40 Сейчас в теме
А как тестировать и отлаживать парсинг? Компилить каждый раз прогу на C# или дергать весь сайт заново из 1С?
Не надо извращений со скрещиванием C# и 1С. Берете python и пишете на BeautyfulSoup парсинг в реальном времени в консольке.
Изучается за час-два, получаете результат в JSON и передаете в 1С.

Можно и прямо из 1С запускать готовые py-скрипты, даже хранить их в базе, а не зашивать в хардкоде алгоритмы.

Уже не один год вижу статьи про .NET+1C, такое ощущение что автору в какой то глубинке нечем заняться и он упорно шлифует "свою прелесть"
albert.goncharov; +1 Ответить
32. albert.goncharov 83 03.12.18 23:31 Сейчас в теме
А есть ли какой-то способ вызывать конструкции вида =>
?
    //Do something with LINQ
    var blueListItemsLinq = document.All.Where(m => m.LocalName == "li" && m.ClassList.Contains("blue"));
33. albert.goncharov 83 21.07.19 03:08 Сейчас в теме
Потребовалось находить дженерик-функцию SubmitAsync, у которой больше 2-х параметров, которая видимо в современных редакциях AngleSharp превратилась в дженерик.
Вот как она выглядит в файле AngleSharp.xml:
AngleSharp.Extensions.ApiExtensions.SubmitAsync(AngleSharp.Dom.Html.IHtmlFormElement,System.Collections.Generic.IDictionary{System.String,System.String},System.Boolean)

Если обратить внимание на её описание - то можно заметить что ниже по тексту идут ИМЕНОВАННЫЕ параметры, с которыми она вызывается.
// Возвращает метод дженерик-фунции
//
// Параметры:
//	Врап		- COMОбъект("NetObjectToIDispatch45")	- первый параметр при работе с библиотеками .NET из 1С
//	тип			- COMОбъект								- тип того объекта, который на C# пишется перед точкой при вызове дженерик-метода
//	ИмяМетода	- Строка								- собственно тот дженерик-метод, который мы ищем
//	имяПараметра1...имяПараметра9						- подсмотренные в AngleSharp.xml названия параметров дженерик-метода, по которым мы можем отличить его от других похожих
//
// Возвращаемое значение:
//	COMОбъект		- который потом может приниматься в качестве параметра при вызове Врап.MethodInfo_Invoke(COMОбъект, null, Параметр1, Параметр2, ...)
//	Неопределено	- в случае, когда метод найти не удалось
//
Функция ПолучитьМетодИнфоМногоПараметров(Врап, тип, ИмяМетода, имяПараметра1 = Неопределено, имяПараметра2 = Неопределено, имяПараметра3 = Неопределено,
																имяПараметра4 = Неопределено, имяПараметра5 = Неопределено, имяПараметра6 = Неопределено,
																имяПараметра7 = Неопределено, имяПараметра8 = Неопределено, имяПараметра9 = Неопределено) Экспорт
	
	method = Неопределено;
	
	КоличествоПараметров = ?(имяПараметра1 = Неопределено, 0,
		?(имяПараметра2 = Неопределено, 1,
		?(имяПараметра3 = Неопределено, 2,
		?(имяПараметра4 = Неопределено, 3,
		?(имяПараметра5 = Неопределено, 4,
		?(имяПараметра6 = Неопределено, 5,
		?(имяПараметра7 = Неопределено, 6,
		?(имяПараметра8 = Неопределено, 7,
		?(имяПараметра9 = Неопределено, 8, 
	9)))))))));
	
	Для каждого m in Врап.ТипКакОбъект(тип).GetMethods() Цикл
        
        параметры = m.GetParameters();
		
		if (m.Name = ИмяМетода) И (параметры.Length = КоличествоПараметров) Тогда
			
			КоличествоСовпавших = 0;
			
			Для каждого параметр Из параметры Цикл
			
				Если (параметр.Name = имяПараметра1)
						Или (параметр.Name = имяПараметра2) 
						Или (параметр.Name = имяПараметра3) 
						Или (параметр.Name = имяПараметра4) 
						Или (параметр.Name = имяПараметра5) 
						Или (параметр.Name = имяПараметра6) 
						Или (параметр.Name = имяПараметра7) 
						Или (параметр.Name = имяПараметра8) 
						Или (параметр.Name = имяПараметра9) // поскольку когда имяПараметра9 = Неопределено - то совпасть они не могут
				Тогда
						
					КоличествоСовпавших = КоличествоСовпавших + 1;
					
				КонецЕсли;
			
			КонецЦикла;
			
			Если КоличествоСовпавших = КоличествоПараметров Тогда
				method = m;
				Прервать;
			КонецЕсли;
			
		КонецЕсли;
		
    КонецЦикла;
    
    return method;
    
КонецФункции // ПолучитьМетодИнфоМногоПараметров()
Показать
Оставьте свое сообщение
Новые вопросы с вознаграждением
Автор темы объявил вознаграждение за найденный ответ, его получит тот, кто первый поможет автору.

Вакансии

Программист 1С
Красноярск
зарплата от 50 000 руб.
По совместительству

Бизнес-архитектор 1С, ведущий консультант
Санкт-Петербург
Полный день

Руководитель проектов 1С
Санкт-Петербург
Полный день


Программист 1С
Белгород
зарплата от 50 000 руб. до 60 000 руб.
Полный день