Какой самый быстрый способ парсить?

Mihalich

Пользователь
Регистрация
16.08.2016
Сообщения
39
Благодарностей
3
Баллы
8
Всем доброго дня.
Пришло время оптимизировать шаблон. Судя по трейсу почти все ключевые кубики парсят по 250-300мс.

Часть сделана через кубики "обработка текста" - закидываю {-Page.Dom-} в качестве входной переменной и regex-находит нужный фрагмент.
Часть сделана через конструктор действий - добавить в проект (не знаю как этот кубик называется).

Важный момент - все искомые элементы находятся в коде на одних и тех же местах. Страница не обновляется, никаких переходов, js молча обновляет на ней кучу данных. А мой шаблон фиксирует их появление/исчезновение и парсит из них значения.

1. Какие способы парсить самые быстрые, а каких лучше избегать если нужна скорость?
2. Даже логические кубики if - и те показывают иногда по 500мс. Подскажите как условия делать на порядок быстрее?
 
Последнее редактирование:

Sergodjan

Administrator
Команда форума
Регистрация
05.09.2012
Сообщения
22 653
Благодарностей
10 129
Баллы
113
Всем доброго дня.
Пришло время оптимизировать шаблон. Судя по трейсу почти все ключевые кубики парсят по 250-300мс.

Часть сделана через кубики "обработка текста" - закидываю {-Page.Dom-} в качестве входной переменной и regex-находит нужный фрагмент.
Часть сделана через конструктор действий - добавить в проект (не знаю как этот кубик называется).

Важный момент - все искомые элементы находятся в коде на одних и тех же местах. Страница не обновляется, никаких переходов, js молча обновляет на ней кучу данных. А мой шаблон фиксирует их появление/исчезновение и парсит из них значения.

1. Какие способы парсить самые быстрые, а каких лучше избегать если нужна скорость?
2. Даже логические кубики if - и те показывают иногда по 500мс. Подскажите как условия делать на порядок быстрее?
Время работы кубиков замеряли при включенной отрисовке в ПМ?
 

amyboose

Client
Регистрация
21.04.2016
Сообщения
2 311
Благодарностей
1 192
Баллы
113
Взять весь html и закинуть в htmlagility, затем можно парсить за пару миллисекунд всё от начала до конца.
 
  • Спасибо
Реакции: Mihalich

Lord_Alfred

Client
Регистрация
09.10.2015
Сообщения
3 916
Благодарностей
3 881
Баллы
113
Взять весь html и закинуть в htmlagility, затем можно парсить за пару миллисекунд всё от начала до конца.
А ещё лучше отсниффать запросы, которые тянет js и получать всё в удобоваримом варианте (если там json).
 
  • Спасибо
Реакции: Nike59 и Mihalich

Mihalich

Пользователь
Регистрация
16.08.2016
Сообщения
39
Благодарностей
3
Баллы
8
Время работы кубиков замеряли при включенной отрисовке в ПМ?
Измерял в zennoposter через ПКМ по проекту - Трассировать выполнение - тут c:\Users\Администратор\Documents\ZennoLab\Traces\тест.xmlz\49.txt
 

Mihalich

Пользователь
Регистрация
16.08.2016
Сообщения
39
Благодарностей
3
Баллы
8
Спасибо, пошёл изучать Xpath и htmlagility в этот пост.
 
  • Спасибо
Реакции: orka13

Mihalich

Пользователь
Регистрация
16.08.2016
Сообщения
39
Благодарностей
3
Баллы
8
Подключил htmlagility и сделал C# в котором выдёргиваю один элемент и текст из него.
Но в трейсе ещё хуже стало - 500 мс в среднем.
Что делают не так? Как ускорить на порядок?

Вот код:
Код:
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument(); // создание объекта
doc.LoadHtml(instance.ActiveTab.DomText); // грузим DOM напрямую сюда
//string temp = "";
string result = "";
//var sourceList = project.Lists["List1_Urls"]; // получаем список, с которым будем работать (в шаблоне должен уже быть пустой список List1_Urls)

var var_xpath1 = "//div[contains(@class,'buy')]/div[@class='tv-trading-toolbar__value js-value' and 2]"; // условие xpath
var Nodes_list_1 = doc.DocumentNode.SelectNodes(var_xpath1); //  получаем список элементов по условию var_xpath1

//project.SendInfoToLog("нашли столько узлов: " + Nodes_list_1.Count.ToString(), true);

// разбираем что нашли
if (Nodes_list_1 != null)
{
foreach (var res in Nodes_list_1) //  начинаем цикл
    {
           result = res.InnerText; //  получаем текст каждого элемента
        //project.SendWarningToLog("элемент = "+result,true); // в лог пишем
    }      
}
return result;
 

Mihalich

Пользователь
Регистрация
16.08.2016
Сообщения
39
Благодарностей
3
Баллы
8
Нашёл. Вот эта строчка даёт такую задержку: doc.LoadHtml(instance.ActiveTab.DomText);
Кто знает - есть какие-то более шустрые альтернативы?
 

Mihalich

Пользователь
Регистрация
16.08.2016
Сообщения
39
Благодарностей
3
Баллы
8
Вынес её из кода в кубик (Табы - Данные - взять DOM). В половине случаев он выполняется за 60мс. в половине за 600мс. В среднем получается 320мс.
Какие есть способы оптимизировать и ускорить ЗП, чтобы стабильно получать страницу для парсинга за 60-100мс?
 

samsonnn

Client
Регистрация
02.06.2015
Сообщения
2 056
Благодарностей
1 887
Баллы
113
Вынес её из кода в кубик (Табы - Данные - взять DOM). В половине случаев он выполняется за 60мс. в половине за 600мс. В среднем получается 320мс.
Какие есть способы оптимизировать и ускорить ЗП, чтобы стабильно получать страницу для парсинга за 60-100мс?
Как вариант оставить браузер в покое, и перейти на Post/Get запросы
 

Mihalich

Пользователь
Регистрация
16.08.2016
Сообщения
39
Благодарностей
3
Баллы
8
Там одна страничка загружается и дальше похоже только js-ы обновляют данные вот по такой ссылке: wss://site.com/socket.io/websocket?from=chart%2FGfc340Hb%2F&date=2018_11_16-15_48
Выглядит это нескончаемым потоком http://joxi.ru/p277BBSobdxp27?d=1
Как её слушать и вылавливать данные?
 

Hartwell

Client
Регистрация
25.09.2014
Сообщения
194
Благодарностей
119
Баллы
43
Там одна страничка загружается и дальше похоже только js-ы обновляют данные вот по такой ссылке: wss://site.com/socket.io/websocket?from=chart%2FGfc340Hb%2F&date=2018_11_16-15_48
Выглядит это нескончаемым потоком http://joxi.ru/p277BBSobdxp27?d=1
Как её слушать и вылавливать данные?
wss:// - web socket

https://kaazing.com/inspecting-websocket-traffic-with-chrome-developer-tools/


https://docs.microsoft.com/ru-ru/dotnet/api/system.net.sockets.socket?redirectedfrom=MSDN&view=netframework-4.7.2
 
  • Спасибо
Реакции: Mihalich

Mihalich

Пользователь
Регистрация
16.08.2016
Сообщения
39
Благодарностей
3
Баллы
8
Глянул, но там идут сплошные Binary Frame (Opcode 2). В хроме их контент не видно. Да и как "присосаться" к этому потоку в ЗП не знаю.
Может кто поможет? Там две цифры обновляющиеся нужно постоянно мониторить в цикле.
 

Hartwell

Client
Регистрация
25.09.2014
Сообщения
194
Благодарностей
119
Баллы
43
Глянул, но там идут сплошные Binary Frame (Opcode 2). В хроме их контент не видно. Да и как "присосаться" к этому потоку в ЗП не знаю.
Может кто поможет? Там две цифры обновляющиеся нужно постоянно мониторить в цикле.
линк бы раз такая специфика на словах

ну а в c# выглядит это как то так (с чтением данных из сокета)
на примере wss.idex.market

Код:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Windows.Forms;
using System.Xml;

namespace CodeEvaler {
    public static class Program {
        public static void Main() {
            (new CodeEvaler()).Eval();
        }
    }

    public class CodeEvaler {
        public void Eval() {
            MakeRequests();
        }
//Calls request functions sequentially.
private void MakeRequests()
{
    HttpWebResponse response;
    string responseText;

    if (Request_wss_idex_market(out response))
    {
        //Success, possibly use response.
        responseText = ReadResponse(response);

        response.Close();
    }
    else
    {
        //Failure, cannot use response.
    }
}

//Returns the text contained in the response.  For example, the page HTML.  Only handles the most common HTTP encodings.
private static string ReadResponse(HttpWebResponse response)
{
    using (Stream responseStream = response.GetResponseStream())
    {
        Stream streamToRead = responseStream;
        if (response.ContentEncoding.ToLower().Contains("gzip"))
        {
            streamToRead = new GZipStream(streamToRead, CompressionMode.Decompress);
        }
        else if (response.ContentEncoding.ToLower().Contains("deflate"))
        {
            streamToRead = new DeflateStream(streamToRead, CompressionMode.Decompress);
        }

        using (StreamReader streamReader = new StreamReader(streamToRead, Encoding.UTF8))
        {
            return streamReader.ReadToEnd();
        }
    }
}

/// <summary>
/// Tries to request the URL: https://wss.idex.market/
/// </summary>
/// <param name="response">After the function has finished, will possibly contain the response to the request.</param>
/// <returns>True if the request was successful; false otherwise.</returns>
private bool Request_wss_idex_market(out HttpWebResponse response)
{
    response = null;

    try
    {
        //Create request to URL.
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://wss.idex.market/");

        //Set request headers.
        request.Headers.Set(HttpRequestHeader.Pragma, "no-cache");
        request.Headers.Set(HttpRequestHeader.CacheControl, "no-cache");
        request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36";
        request.Headers.Set(HttpRequestHeader.Upgrade, "websocket");
        request.Headers.Add("Origin", @"https://idex.market");
        request.Headers.Add("Sec-WebSocket-Version", @"13");
        request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate, br");
        request.Headers.Set(HttpRequestHeader.AcceptLanguage, "en,ru;q=0.9");
        request.Headers.Set(HttpRequestHeader.Cookie, @"__cfduid=d88e16e134560b5565e4770398f9333521532634285");
        request.Headers.Add("Sec-WebSocket-Key", @"cj20R8IQfpldg9qv5JxoHw==");
        request.Headers.Add("Sec-WebSocket-Extensions", @"permessage-deflate; client_max_window_bits");

        //Get response to request.
        response = (HttpWebResponse)request.GetResponse();
    }
    catch (WebException e)
    {
        //ProtocolError indicates a valid HTTP response, but with a non-200 status code (e.g. 304 Not Modified, 404 Not Found)
        if (e.Status == WebExceptionStatus.ProtocolError) response = (HttpWebResponse)e.Response;
        else return false;
    }
    catch (Exception)
    {
        if(response != null) response.Close();
        return false;
    }

    return true;
}

    }
}

альтернативный вариант заюзать js или html5, тупо локально клиент подрубать и по файлу грзить страничку с js кодом аля file:///c:/mysocket.html (но правд нахрена... если можно все через консоль туже)
 
  • Спасибо
Реакции: pym933 и Mihalich

Zy6ek

Client
Регистрация
15.09.2018
Сообщения
21
Благодарностей
6
Баллы
3
В хроме их контент не видно.
В хроме клацни вкладку WS в Network, появится соединение, жмешь на него и справа будет Headers , Frames, cookies. Жмеш на Frames и пойдут данные. Или я юзаю в ФФ дополнение WebSocket Monitor, он появится там же где и все остальное добро.
scroff6539fabbff8e.jpg
Так же рекомендую сайт https://www.websocket.org/echo.html У них есть тестовый wss к которому можно пробовать прицепится зенкой. У меня получилось на C# в Visual Studio прицепится и получать данные в wss потоке в консоли, но перенести в зенку так и не смог. Я юзал вот эту библиотеку https://github.com/sta/websocket-sharp
 
Последнее редактирование:
  • Спасибо
Реакции: Mihalich

Zy6ek

Client
Регистрация
15.09.2018
Сообщения
21
Благодарностей
6
Баллы
3
Итак получилось у меня подружить таки зенку и вебсокет. Вот рабочее решение:
В Общий код добавляем
Код:
using WebSocketSharp;
В кубик пишем:
Код:
using (var ws = new WebSocket("wss://ТВОЙПОТОК"))
{
ws.OnMessage += (sender, e) =>
project.SendInfoToLog(e.Data, true);
System.Threading.Thread.Sleep(2000);
ws.Connect();
System.Threading.Thread.Sleep(1000);
//у меня чтобы wss сервер начал отправлять данные, нужно было отправить ключевую фразу
ws.Send("сообщение которое нужно отправить");
//паузу и выход по действию прикрутиш уже сам,
System.Threading.Thread.Sleep(5000);
}
Данный код выводит в лог зенки принимаемые данные. Дальше уже сам решай куда тебе их, в список или в переменную.
Библиотека использовалась https://github.com/sta/websocket-sharp
 
Последнее редактирование:
  • Спасибо
Реакции: pym933 и Jfgertz

Jfgertz

Новичок
Регистрация
05.09.2017
Сообщения
6
Благодарностей
0
Баллы
1
Zy6ek , не могли бы вы объяснить как добавить эту библиотеку в проект?
я добавил using WebSocketSharp; в общий код, но при выполнении C# ошибка:


 

Meteorburn

Client
Регистрация
23.05.2016
Сообщения
1 570
Благодарностей
632
Баллы
113
Zy6ek , не могли бы вы объяснить как добавить эту библиотеку в проект?
я добавил using WebSocketSharp; в общий код, но при выполнении C# ошибка:


А сам dll куда нужно перенесли, а в проект добавили?

Если апи библиотеки используется в самом проекте, то using надо вписывать на вкладку директивы using
 

Jfgertz

Новичок
Регистрация
05.09.2017
Сообщения
6
Благодарностей
0
Баллы
1

Meteorburn

Client
Регистрация
23.05.2016
Сообщения
1 570
Благодарностей
632
Баллы
113
  • Спасибо
Реакции: Jfgertz

Jfgertz

Новичок
Регистрация
05.09.2017
Сообщения
6
Благодарностей
0
Баллы
1
Данный код выводит в лог зенки принимаемые данные. Дальше уже сам решай куда тебе их, в список или в переменную.
Объясните пожалуйста, как из лога перенести данные в переменную либо список?
Или же если возможно писать поток не в лог, а сразу в переменную или список.

Код:
using (var ws = new WebSocket("wss://ТВОЙПОТОК"))
{
ws.OnMessage += (sender, e) =>
project.SendInfoToLog(e.Data, true);
ws.Connect();
//паузу и выход по действию прикрутиш уже сам,
System.Threading.Thread.Sleep(5000);
}
 

Hartwell

Client
Регистрация
25.09.2014
Сообщения
194
Благодарностей
119
Баллы
43
Тип того вроде
readsocket:
ws.Connect();

if (e.IsText) {
// делаешь что то с e.Data
string project.varible = e.Data;
  return;
}}
 

Кто просматривает тему: (Всего: 2, Пользователи: 0, Гости: 2)