Вытаскиваем данные из вкладки "Трафик" (плагин + код c#)

volody00

Client
Регистрация
06.09.2016
Сообщения
978
Благодарностей
1 067
Баллы
93
Введение

Начну с того, что такое трафик, как с ним работать и решение какой проблемы предлагает мой плагин. Более подробно этой темы я уже касался тут, поэтому здесь пробежимся кратко.

Итак, когда мы переходим на какую-то страницу, браузер вместо нас отправляет запросы на сервер и получает ответы. Благодаря разработчикам Zennoposter все эти данные можно достать (урл запроса, заголовки запроса/ответа, тело запроса/ответа).
125202

Первым делом нам нужно включить монитор трафика. Его достаточно прописать один раз где-нибудь в начале шаблона.
C#:
instance.UseTrafficMonitoring = true;
Далее, когда нам нужно собрать запросы, то мы получаем массив всех этих данных и вытаскиваем именно то, что нам требуется. Пример для страницы https://zenno.club/discussion/
C#:
string headers = string.Empty, cookies = string.Empty, body = string.Empty;

//собираем все запросы из вкладки трафик
var trafficList = instance.ActiveTab.GetTraffic();

//проходимся по ним в цикле
foreach(var s in trafficList)
{
    //получаем урл
    string url = s.Url;
  
    //сравниваем урл
    if(url == "https://zenno.club/discussion/")
    {
        //дожидаемся прогрузки
        s.WaitResponse(10, 2);
      
        //достаем заголовки ответа
        headers = s.ResponseHeaders;
      
        //достаем куки
        cookies = s.ResponseCookies;
      
        //достаем тело
        if(s.ResponseBody != null) body = System.Text.Encoding.UTF8.GetString(s.ResponseBody);
      
    }
}

//выводим в лог
project.SendInfoToLog(headers);
project.SendInfoToLog(cookies);
project.SendInfoToLog(body);

/*
чтобы поместить в зенковские переменные
project.Variables["headers"].Value = headers;
project.Variables["cookies"].Value = cookies;
project.Variables["body"].Value = body;
*/
Но что, если мы хотим собрать данные с ещё одного запроса (на этой же странице), например, https://zenno.club/discussion/styles/class/fonts/icons/material-icons/css/materialdesignicons.min.css ? Вы можете подумать, что копипастим в новый кубик c#, поменяв урл, и всё будет гуд, но не тут-то было…
125203

Получаем пустоту. Дело в том, что, вызывая метод GetTraffic(), мы очищаем весь трафик. Когда мы создали новый кубик c# и "скопипастили" код, то он пытается найти уже новые запросы. И вот тут возникает проблема у тех, кто не знает c#, ибо методом тыка "натыкать" может быть не так просто.

У нас с вами есть пару вариантов. Первый – модифицировать первый кубик так, чтобы можно было собрать сразу несколько запросов. На форуме был найден такой сниппет, собирающий данные в таблицу

C#:
var traffic = instance.ActiveTab.GetTraffic();
var tt = project.Tables["trafficTable"];

tt.AddRow(new List<string>()
{
    "Method",
    "ResultCode",
    "Url",
    "ContentType",
    "RequestHeaders",
    "RequestCookies",
    "RequestBody",
    "ResponseHeaders",
    "ResponseCookies",
    "ResponseBody"
});

foreach(TrafficItem t in traffic)
{
    var row = new List<string>()
    {
        t.Method,
        t.ResultCode.ToString(),
        t.Url,
        t.ResponseContentType,
        t.RequestHeaders,
        t.RequestCookies,
        t.RequestBody,
        t.ResponseHeaders,
        t.ResponseCookies,
        t.ResponseBody == null ? "" : Encoding.UTF8.GetString(t.ResponseBody, 0, t.ResponseBody.Length)
    };
    
    tt.AddRow(row);
}
Второй – воспользоваться project.Context, дабы сохранить данные со "старого трафика". Давайте покажу, как это. В первом кубике нам надо будет в конце добавить одну строчку
C#:
string headers = string.Empty, cookies = string.Empty, body = string.Empty;

var trafficList = instance.ActiveTab.GetTraffic();

foreach(var s in trafficList)
{
    string url = s.Url;
  
    if(url == "https://zenno.club/discussion/")
    {
        s.WaitResponse(10, 2);
        headers = s.ResponseHeaders;
        cookies = s.ResponseCookies;
        if(s.ResponseBody != null) body = System.Text.Encoding.UTF8.GetString(s.ResponseBody);
      
    }
}


project.SendInfoToLog(headers);
project.SendInfoToLog(cookies);
project.SendInfoToLog(body);

//сохраняем контекст в "переменную" с именем network
project.Context["network"] = trafficList;
А во втором кубике собирать данные уже не с помощью метода GetTraffic(), а именно из project.Context.
C#:
string headers = string.Empty, cookies = string.Empty, body = string.Empty;

//подгружаем данные из переменной "network"
var trafficList = project.Context["network"];

foreach(var s in trafficList)
{
    string url = s.Url;
  
    if(url == "https://zenno.club/discussion/styles/class/fonts/icons/material-icons/css/materialdesignicons.min.css")
    {
        s.WaitResponse(10, 2);
        headers = s.ResponseHeaders;
        cookies = s.ResponseCookies;
        if(s.ResponseBody != null) body = System.Text.Encoding.UTF8.GetString(s.ResponseBody);
      
    }
}


project.SendInfoToLog(headers);
project.SendInfoToLog(cookies);
project.SendInfoToLog(body);
В принципе, проблему это решает. Но чем мне не нравится project.Context, так это тем, что при его использовании вы не сможете пользоваться пошаговой отладкой в c# (по крайне мере в PM, может быть в VS ситуация получше).

Оба варианта имеют право на жизнь, но я решил предложить вам ещё более удобную штуку.

Плагин

Суть его очень простая. Он соберет все запросы и все данные в формате json, ну а далее вы можете вытаскивать что душе угодно с помощью кубика "парсить json".

Итак, первым делом добавляем плагин к себе в проект. Идём в настройки->плагины->добавить плагины и выбираем плагин
125204

Теперь создаем кубик c# и включаем мониторинг трафика

instance.UseTrafficMonitoring = true;

Переходим на нужную страницу, используем плагин и распаршиваем полученный json.
Реализация на c#

На c# есть вариант как с project.Context, так и с сохранением в json. Первым делом надо будет вам добавить библиотеку Newtonsoft.json. Для этого заходим в ссылки из gac -> добавить -> C:\Program Files\ZennoLab\RU\ZennoPoster Pro V7\7.7.ваша_версия\Progs и там находим Newtonsoft.json

125205

Важно:
  • Не забыть прописать перед вызовом класса instance.UseTrafficMonitoring = true;
  • Для использования в других кубиках следует переносить через project.Context. P.S. При отладке project.Context ведет себя капризно и может выдавать ошибку "Выполнение действия CSharp OwnCode: получаем тело уже другого запроса из другого кубика. Возникло непредвиденное исключение при выполнении привязки динамической операции". Так что иметь в виду и выполнять без остановки.


public bool GetTraffic(string url = "", string searchType = "contains", bool searchAllUrl = true, int maxTimeout=30, bool stopMonitoring = true, int wait=1, bool waitAllurls = false) – мониторит трафик на протяжении указанного времени.

Задача метода – записать весь трафик в список trafficList.

Также мы можем задать список урл для проверки, есть ли они в трафике и узнать это исходя из того, что вернёт метод.

Данный метод всегда вызываем первым, т.к. остальные работают исключительно с trafficList, а не с самим трафиком.

Метод перезаписывает список trafficList, т.к. происходит вызов зенковского GetTraffic!

Параметры:

  • url [""] – список урл, которые ищем. Если пустой, то вернём true, если в трафике будет найден хотя бы 1 запрос. Можно передать 1 урл. Можно передать несколько урл через точку с запятой.
  • searchType ["contains"] – тип поиска. "contains" [по умолч], "regex", "startsWith", "endsWith", "exactMatch"
  • searchAllUrl [true] – надо ли нам отыскать все урл (если задано несколько). Если да, то вернёт true только в том случае, если будут найдены все урл. Если нет, то вернёт true в том случае, если будет найден хотя бы один запрос.
  • maxTimeOut [30] – сколько секунд максимум мониторим трафик. Если заданы урл, мониторинг прекратится после того, как они будут найдены.
  • stopMonitoring [true] – прекратить ли мониторинг трафика, если на протяжении 3-4 секунд новые запросы в трафике больше не появляются. Всегда false, если задан список урл, но при этом заканчивает работу, если все урл найдены.
  • wait [1] - Сколько "кругов" (1 круг = 1 секунда) ждать появления новых запросов, прежде чем прервем метод. Чем меньше ставим, тем быстрее отработает метод, но повышается вероятность упустить какие-то запросы, которые могут появиться чуть позже "основной" пачки.
  • waitAllurls - Ждать прогрузки всех урл, а не только тех, которые указали мы [false]
Возвращаемое значение:
  • true или false в зависимости от ситуации, описанной выше
  • По окончании работы ВСЕ запросы из монитора трафика сохраняются в список trafficList
==

public string GetBody(string url, string searchType = "contains") – ищем урл в списке TrafficList и получаем тело запроса. Можно задать только 1 урл.

Параметры:
  • url – искомый урл
  • searchType ["contains"] – тип поиска. contains" [по умолч], "regex", "startsWith", "endsWith", "exactMatch"
Возвращаемое значение:
  • "" – если урл не найден
  • тело запроса в string
==

public void Clear() – принудительная очистка списка TrafficList

public string GetJsonFromTraffic(string url = "", string searchType = "contains", bool searchAllUrl = true, int maxTimeout=30, bool stopMonitoring = true, int wait=1, bool waitAllurls = false) – сохраняем весь трафик в строку json. Параметры аналогичны GetTraffic(). Если запросы не найдены, вернет "".

public NetworkObjectList GetObjectFromJson(string json) – из json помещаем данные обратно в объект. Т.е. этот метод используется после GetJsonFromTraffic().

Примеры использования методов смотрите в прикрепленном шаблоне.

В видео я покажу вам, как вы можете расширить данную библиотеку, поработав с общим кодом.

 

Вложения

Последнее редактирование модератором:

seodamage

Client
Регистрация
08.09.2014
Сообщения
232
Благодарностей
74
Баллы
28
спасибо, для одной тапалки пригодиться. она там на юнити написана и из запросов как раз можно понять когда сессия устарела.
 

russya

Client
Регистрация
08.07.2014
Сообщения
753
Благодарностей
81
Баллы
28
На зеннодроид нельзя так отлавливать трафик?
 

gospodinkot

Client
Регистрация
04.03.2019
Сообщения
179
Благодарностей
49
Баллы
28
Отлично! Работает в ПМ, но в постере на этом кубике получаю ошибку "Выполнение действия CSharp OwnCode. Ссылка на объект не указывает на экземпляр объекта."
Как это можно исправить?
Использую самый первый пример кода, который берёт данные из одного запроса.

UPD
Не актуально. Проблему решил.
Спасибо за код! Очень выручил!
 
Последнее редактирование:

Alex91

Известная личность
Read only
Регистрация
15.08.2024
Сообщения
880
Благодарностей
253
Баллы
63
Отлично! Работает в ПМ, но в постере на этом кубике получаю ошибку "Выполнение действия CSharp OwnCode. Ссылка на объект не указывает на экземпляр объекта."
Как это можно исправить?
Использую самый первый пример кода, который берёт данные из одного запроса.
Сделай логирование в коде, что бы понимать где вылетает.
Используй try , и вывод в лог ошибку.

Вообще , без try такую конструкцию нельзя использовать... Вот не прогрузился запрос и приплыли 100% к необработанному исключению. Или в запросе туфта пришла, вместо ожидаемого... И опять приплыли :-)
 
  • Спасибо
Реакции: gospodinkot

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