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 5892 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 5892 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 руб. до 80 000 руб.
Полный день

Программист 1С
Новосибирск
зарплата от 80 000 руб. до 120 000 руб.
Полный день

Программист, аналитик, эксперт 1С
Санкт-Петербург
По совместительству

Технический лидер, архитектор 1С, руководитель проектов
Санкт-Петербург
зарплата от 150 000 руб.
Полный день

Автор новостных обзоров на тему 1С и бухучета
Санкт-Петербург
По совместительству