Всем привет. Я не силен в техническом плане, поэтому что такое post-get рассказывать не буду. Надеюсь, большинство из вас в курсе.
Обычно отыскать нужный урл среди запросов не проблема. Проблема – понять, как формируется тот или иной параметр, чтобы правильно сформировать запрос. Так вот, если вы в этом плане не шарите (как я), то возможно нижеизложенная информация будет полезна.
Что мы будем делать:
Естественно, прокатит это не везде, но как минимум это можно использовать для парсеров социальных сетей, где из-за необходимости скролить страницу вниз писать шаблон на веб нереально (я пробовал, лучше не надо).
Класс TrafficItem Есть такой класс, как TrafficItem - https://help.zennolab.com/en/v7/zennoposter/7.1.4/webframe.html#topic697.html. Суть его в том, что мы можем вытащить всю информацию о любом запросе, который отображается во вкладке «трафик».
Включаем инструмент «трафик»

Переходим на яндекс

Чтобы это реализовать, разберем свойства данного класса:




Добавляем в своем проекте директивы using и общий код

Открываем, удаляем всё и вставляем нижеприведенный код

Создаем кубик c#:

Создаем шесть переменных, куда ляжет наш результат:

Пишем в кубике c# следующее:
Теперь добавим кубик перехода на https://yandex.ru , запустим и посмотрим на результат


А теперь подробнее о каждом параметре:
Связано это с тем, что на c# нам заголовки надо передать в виде массива, а не переменной, как это сделано в кубике GET-POST. Да и использовать в этом случае переменные от разработчиков зенки тут не нужно.
P.S. Кто повнимательней посмотрит на реализацию заметит, что код явно не оптимальный. Отчасти это связано с тем, что я не программист, а отчасти, что у меня уже была заготовка именно под c#. Я быстренько перепелил её под кубик, не заморачиваясь с тем, чтобы не дублировать код и т.д.
В видео ниже я демонстрирую пример заготовки парсера для инстраграмма. ВАЖНО: это лишь набросок, а не полноценный парсер. Мне важно передать вам идею, а уж реализовывать вам придется самим. На этом у меня всё. Надеюсь, был полезен.
Обычно отыскать нужный урл среди запросов не проблема. Проблема – понять, как формируется тот или иной параметр, чтобы правильно сформировать запрос. Так вот, если вы в этом плане не шарите (как я), то возможно нижеизложенная информация будет полезна.
Что мы будем делать:
- Заходим на нужную нам страницу через браузер
- «Тырим» все данные, что нам нужны
- Работаем на запросах
Естественно, прокатит это не везде, но как минимум это можно использовать для парсеров социальных сетей, где из-за необходимости скролить страницу вниз писать шаблон на веб нереально (я пробовал, лучше не надо).
Класс TrafficItem
Включаем инструмент «трафик»

Переходим на яндекс

Чтобы это реализовать, разберем свойства данного класса:
Код:
instance.UseTrafficMonitoring = true;
var traffic = instance.ActiveTab.GetTraffic();
foreach(var t in traffic)
//далее внутри можем вызывать:
t.Url - урл нашего запроса (string)
t.Method - метод нашего запроса (string)
t.ResultCode - код ответа нашего запроса (uint)
t.Time - время между отправкой нашего запроса и получением ответа (int)
t.RequestHeaders - заголовки нашего запроса (string)
t.RequestBody - тело нашего запроса (string)
t.RequestCookies - куки нашего запроса (string)
t.RequestReplacedBody - тело нашего запроса, если мы делали замену с помощью метода ChangeRequest (если не делали будет пусто) (string)
t.RequestQuery - ? (запрос части урл) (string)
==
t.ResponseBody - тело высланное в ответ на наш запрос (byte[]) - пример добавления в список teloZaprosaGraphql.Add(System.Text.Encoding.UTF8.GetString(t.ResponseBody))
t.ResponseContentCharset - кодировка высланная в ответ на наш запрос (string)
t.ResponseContentType - content type высланный в ответ на наш запрос (string)
t.ResponseCookies - куки высланные в ответ на наш запрос (string)
t.ResponseHeaders - заголовки, высланные в ответ на наш запрос (string)
t.ResponseReplacedBody - тело нашего запроса, если мы делали замену с помощью метода ChangeResponse (иначе будет пусто), высланное в ответ на наш запрос (byte[])
высланный в ответ на наш запрос
==
t.HasResponse - вернет true, если браузер получил ответ на запрос
t.IsBlocked - вернет true, если этот запрос был заблокирован по политике содержимого




Как нам всё это вытащить
Я постарался подготовить более-менее универсальное решение. Если вы разбираетесь в c#, то можете посмотреть реализацию и подправить что-либо под себя. Если нет, то действуем по инструкции ниже.Добавляем в своем проекте директивы using и общий код

Открываем, удаляем всё и вставляем нижеприведенный код

C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Text.RegularExpressions;
using ZennoLab.CommandCenter;
using ZennoLab.InterfacesLibrary;
using ZennoLab.InterfacesLibrary.ProjectModel;
using ZennoLab.InterfacesLibrary.ProjectModel.Collections;
using ZennoLab.InterfacesLibrary.ProjectModel.Enums;
using ZennoLab.Macros;
using Global.ZennoExtensions;
using ZennoLab.Emulation;
using ZennoLab.CommandCenter.TouchEvents;
using ZennoLab.CommandCenter.FullEmulation;
using ZennoLab.InterfacesLibrary.Enums;
namespace ZennoLab.OwnCode
{
/// <summary>
/// A simple class of the common code
/// </summary>
public class CommonCode {
/// <summary>
/// Lock this object to mark part of code for single thread execution
/// </summary>
public static object SyncObject = new object();
public enum SearchType
{
Contains,
Exact
}
public static Random r = new Random();
/// <summary>
/// Ищем запрос
/// </summary>
/// <param name="instance">передаем instance</param>
/// <param name="url">искомый урл</param>
/// <param name="typeRequest">тип запроса (GET, POST, ...)</param>
/// <param name="searchType">Тип поиска (перечисление CommonCode.SerchType. Может быть: exact(точное) или contains(содержит))</param>
/// <param name="number">Номер совпадения</param>
/// <param name="minLength">Минимальная длина искомого урл</param>
/// <returns></returns>
private static TrafficItem SearchRequest(Instance instance, string url, string typeRequest, SearchType searchType, int number, int minLength)
{
//instance.UseTrafficMonitoring = true;
List < TrafficItem > urls = new List < TrafficItem > ();
//перебираем запросы из вкладки "Трафик"
var traffic = instance.ActiveTab.GetTraffic();
foreach(var t in traffic)
{
//если выбрали CommonCode.SerchType.Contains
if (searchType == SearchType.Contains)
{
//проверяем содержится ли в урл искомый урл, соответствие на тип запроса и соответствие на длину. Если всё подходит, складываем в список urls
if (t.Url.Contains(url) && t.Method.Contains(typeRequest))
{
if (t.Url.Length > minLength) urls.Add(t);
}
}
//если выбрали CommonCode.SerchType.Exact
else if (searchType == SearchType.Exact)
{
//аналогично, только ищем точное соответствие урл
if (t.Url == url && t.Method.Contains(typeRequest))
{
if (t.Url.Length > minLength) urls.Add(t);
}
}
}
//выходим по ошибке, если ничего не найдено
if (urls.Count == 0) throw new Exception("искомый урл не найден - " + url);
//если что-то найдено, возвращаем. try-catch сделан для понятного оповещения, если указанный номер не присутствует в списке
else
{
try
{
return urls[number];
} catch
{
throw new Exception($"нет урл по вашему номеру совпадения. всего было найдено {urls.Count} урл");
}
}
}
/// <summary>
/// Формируем заголовки для ZennoPoster.HttpGet/HttpPost. Возвращаем куки в переменную и заголовки в массив через out
/// </summary>
/// <param name="RequestHeaders">передаем строку, полученную в результате выполнения свойства RequestHeaders класса trafficitem</param>
/// <param name="Cookies">передаем пустую переменную для куки через out</param>
/// <param name="UserAgent">передаем пустую переменную для user agent через out</param>
/// <param name="Headers">передаем пустой массив для заголовков через out</param>
private static void RequestHeadersInGetPost(string RequestHeaders, out string Cookies, out string UserAgent, out string[] Headers)
{
List < string > headers = new List < string > ();
List < string > cookies = new List < string > (); //список для кук
string cook = "";
string peremenDlySikla = "";
string ua = "";
headers.AddRange(RequestHeaders.Split('\n')); //помещаем заголовки и их значения в список
///
/// начало: формируем куки
///
for (int i = 0; i < headers.Count; i++)
{
//если в заголовке содержатся куки
if (headers[i].Contains("Cookie"))
{
//удалили их из списка
lock(SyncObjects.ListSyncer)
{
cook = headers[i].Replace("Cookie: ", ""); //переложим в переменную, уберем Cookie:
headers.RemoveAt(i);
}
i--;
//сложим куки в список (строк с куками может быть несколько. мы сложим все куки в один список и удалим дубли в конце)
cookies.AddRange(cook.Split(';')); //складываем куки в список (убрали надпись Cookie: и разделили с помощью ;)
}
//если в заголовке содержится user-agent
else if (headers[i].Contains("User-Agent"))
{
lock(SyncObjects.ListSyncer)
{
ua = headers[i].Replace("User-Agent: ", "").Trim(' ', '\r', '\n'); //ложим useragent в переменную
headers.RemoveAt(i);
}
i--;
}
}
cookies.UdalenieDubleiAndPustyhStrokIzSpiska();
cook = ""; //очищаем переменную кук
//переложим всё из списка в переменную
foreach(string s in cookies)
cook += s + "; ";
//если последний символ точка с запятой, мы её удалим
if (cook != "")
{
string obrezka = cook.Substring(cook.Length - 2, 1);
if (cook.Substring(cook.Length - 2, 1) == ";") cook = cook.Remove(cook.Length - 2);
}
Cookies = cook; //возвращаем куки с помощью out Cookies
UserAgent = ua; //возвращаем user-agent с помощью out UserAgent
///
/// конец: формируем куки
///
//переносим из списка в массив и "возвращаем" его
Headers = headers.ToArray();
for (int i = 0; i < Headers.Length; i++) //удаляем переносы строк, которые создает список
{
Headers[i] = Headers[i].Trim('\r', '\n');
}
}
/// <summary>
/// Формируем заголовки для ZennoPoster.HttpGet/HttpPost. Возвращаем куки в переменную и заголовки в массив через out
/// </summary>
/// <param name="RequestHeaders">передаем строку, полученную в результате выполнения свойства RequestHeaders класса trafficitem</param>
/// <param name="Cookies">передаем пустую переменную для куки через out</param>
/// <param name="UserAgent">передаем пустую переменную для user agent через out</param>
/// <param name="Headers">передаем пустой массив для заголовков через out</param>
private static string RequestHeadersInGetPost(string RequestHeaders, out string Cookies, out string UserAgent)
{
List < string > headers = new List < string > ();
List < string > cookies = new List < string > (); //список для кук
string cook = "";
string peremenDlySikla = "";
string ua = "";
headers.AddRange(RequestHeaders.Split('\n')); //помещаем заголовки и их значения в список
///
/// начало: формируем куки
///
for (int i = 0; i < headers.Count; i++)
{
//если в заголовке содержатся куки
if (headers[i].Contains("Cookie"))
{
//удалили их из списка
lock(SyncObjects.ListSyncer)
{
cook = headers[i].Replace("Cookie: ", ""); //переложим в переменную, уберем Cookie:
headers.RemoveAt(i);
}
i--;
//сложим куки в список (строк с куками может быть несколько. мы сложим все куки в один список и удалим дубли в конце)
cookies.AddRange(cook.Split(';')); //складываем куки в список (убрали надпись Cookie: и разделили с помощью ;)
}
//если в заголовке содержится user-agent
else if (headers[i].Contains("User-Agent"))
{
lock(SyncObjects.ListSyncer)
{
ua = headers[i].Replace("User-Agent: ", "").Trim(' ', '\r', '\n'); //ложим useragent в переменную
headers.RemoveAt(i);
}
i--;
}
}
cookies.UdalenieDubleiAndPustyhStrokIzSpiska();
cook = ""; //очищаем переменную кук
//переложим всё из списка в переменную
foreach(string s in cookies)
cook += s + "; ";
//если последний символ точка с запятой, мы её удалим
if (cook != "")
{
string obrezka = cook.Substring(cook.Length - 2, 1);
if (cook.Substring(cook.Length - 2, 1) == ";") cook = cook.Remove(cook.Length - 2);
}
Cookies = cook; //возвращаем куки с помощью out Cookies
UserAgent = ua; //возвращаем user-agent с помощью out UserAgent
///
/// конец: формируем куки
///
string Headers = "";
//переносим из списка в переменную и "возвращаем" его
for (int i = 0; i < headers.Count; i++)
{
Headers += headers[i].Trim('\r', '\n') + Environment.NewLine;
}
return Headers;
}
/// <summary>
/// Достаем урл нашего запроса, тип запроса и тело ОТВЕТА на наш запрос
/// </summary>
/// <param name="s">переменная TrafficItem, в которой содержится наш запрос</param>
/// <param name="url">Переменная для возврата урл</param>
/// <param name="typeMethod">Переменная для возврата типа запроса</param>
/// <param name="body">Переменная для возврата тела запроса</param>
private static void UrlAndBodyRequest(TrafficItem s, out string url, out string typeMethod, out string body)
{
url = s.Url;
typeMethod = s.Method;
body = System.Text.Encoding.UTF8.GetString(s.ResponseBody);
}
/// <summary>
/// Поиск нужного урл из вкладки "Трафик" и возврат кук, userAgent, заголовков, урл, типа запроса и тела в ОТВЕТ на наш запрос
/// </summary>
/// <param name="instance">пишем instance</param>
/// <param name="url">пишем урл, который хотим найти</param>
/// <param name="typeRequest">тип запроса (GET, POST, ...)</param>
/// <param name="searchType">Тип поиска (перечисление CommonCode.SerchType. Может быть: exact(точное) или contains(содержит))</param>
/// <param name="number">Номер совпадения</param>
/// <param name="minLength">Минимальная длина искомого урл</param>
/// <param name="Cookies">передаем пустую переменную для куки через out</param>
/// <param name="UserAgent">передаем пустую переменную для user agent через out</param>
/// <param name="Headers">передаем пустой массив для заголовков через out</param>
/// <param name="url">Переменная для возврата урл через out</param>
/// <param name="typeMethod">Переменная для возврата типа запроса через out</param>
/// <param name="body">Переменная для возврата тела запроса через out</param>
public static void GetHeaders(Instance instance, string url, string typeRequest, SearchType searchType, int number, int minLength, out string Cookies, out string UserAgent, out string[] Headers, out string urlR, out string typeMethod, out string body)
{
TrafficItem t = CommonCode.SearchRequest(instance, url, typeRequest, searchType, number, minLength);
CommonCode.RequestHeadersInGetPost(t.RequestHeaders, out Cookies, out UserAgent, out Headers);
CommonCode.UrlAndBodyRequest(t, out urlR, out typeMethod, out body);
}
/// <summary>
/// Поиск нужного урл из вкладки "Трафик" и возврат кук, userAgent, заголовков, урл, типа запроса и тела в ОТВЕТ на наш запрос
/// </summary>
/// <param name="instance">пишем instance</param>
/// <param name="url">пишем урл, который хотим найти</param>
/// <param name="typeRequest">тип запроса (GET, POST, ...)</param>
/// <param name="searchType">Тип поиска (перечисление CommonCode.SerchType. Может быть: exact(точное) или contains(содержит))</param>
/// <param name="number">Номер совпадения</param>
/// <param name="minLength">Минимальная длина искомого урл</param>
/// <param name="Cookies">передаем пустую переменную для куки (project.Variables["имя переменной"])</param>
/// <param name="UserAgent">передаем пустую переменную для user agent (project.Variables["имя переменной"])</param>
/// <param name="Headers">передаем пустой массив для заголовков (project.Variables["имя переменной"])</param>
/// <param name="url">Переменная для возврата урл (project.Variables["имя переменной"])</param>
/// <param name="typeMethod">Переменная для возврата типа запроса (project.Variables["имя переменной"])</param>
/// <param name="body">Переменная для возврата тела запроса (project.Variables["имя переменной"])</param>
public static void GetHeaders(Instance instance, string url, string typeRequest, SearchType searchType, int number, int minLength, ILocalVariable Headers, ILocalVariable Cookies, ILocalVariable UserAgent, ILocalVariable urlR, ILocalVariable typeMethod, ILocalVariable body)
{
TrafficItem t = CommonCode.SearchRequest(instance, url, typeRequest, searchType, number, minLength);
string s = CommonCode.RequestHeadersInGetPost(t.RequestHeaders, out string cookies, out string userAgent);
Headers.Value = s;
Cookies.Value = cookies;
UserAgent.Value = userAgent;
CommonCode.UrlAndBodyRequest(t, out string z1, out string z2, out string z3);
urlR.Value = z1;
typeMethod.Value = z2;
body.Value = z3;
}
}
public static class ListExtension
{
/// <summary>
/// Удаление дублей и пустых строк из списка List - string
/// </summary>
/// <param name="spisok">Список List, в котором надо удалить дубли</param>
/// <param name="path">Путь к txt файлу</param>
public static void UdalenieDubleiAndPustyhStrokIzSpiska(this List < string > Spisok)
{
//удаляем дубли и пустые строки
string dlySikla = "";
List < string > timeList = new List < string > ();
List < string > spisok = Spisok.ToList();
timeList.AddRange(spisok.Distinct().ToList().Where(arg => !string.IsNullOrWhiteSpace(arg)).ToList());
//возвращаем обратно
lock(SyncObjects.ListSyncer)
{
Spisok.Clear();
Spisok.AddRange(timeList);
}
}
}
}
Создаем кубик c#:

Создаем шесть переменных, куда ляжет наш результат:

Пишем в кубике c# следующее:
C#:
instance.UseTrafficMonitoring = true;
CommonCode.GetHeaders(instance, "https://yandex.ru/", "GET", CommonCode.SearchType.Contains, 0,0,project.Variables["cookie"],project.Variables["useragent"],project.Variables["headers"],project.Variables["url"],project.Variables["type"],project.Variables["body"]);


А теперь подробнее о каждом параметре:
- instance – поскольку в общем коде у нас инстанс недоступен, я его передаю. Не заморачиваемся и просто пишем instance.
- url – тот урл, который вы хотите найти (t.url). Можно часть урл, но тогда надо будет выбрать тип совпадения contains(об этом далее)
- typeRequest – тип запроса. Это может быть GET, POST и т.д. Важно: пишем в верхнем регистре.
- SearchType – тип поиска. Тут реализовано перечисление. Это значит, вам надо написать CommonCode.SearchType. и далее выбрать один из двух вариантов: либо Exapt (точное совпадение по урл), либо Contains (ищет в урл указанную вами часть).
- Number – номер совпадения. Если в результате поиска по части урл у вас будет найдено несколько результатов, вы можете указать номер совпадения, который вам нужен. Помним, что счет идет с нуля.
- minLength – минимальная длина искомого урл. Если для вас это не важно, просто пишите урл. Сделал для дополнительного отсева, если будет найдено несколько совпадений.
- Headers – передаем переменную, куда будут помещены заголовки. Для этого просто руками создаем, копируем имя и вставляем его project.Variables["имяВашейПеременной"]
- Cookies – аналогично, переменная для кук
- UserAgent - аналогично, переменная для UA
- urlR - аналогично, переменная для урл.
- typeMethod - аналогично, переменная для типа метода
- body - аналогично, переменная для тела ОТВЕТА. Обратите внимание: сюда ляжет тело ОТВЕТА на наш запрос. Если до этого мы данные брали из нашего же запроса, то здесь мы достаем то, что получили в ответ в теле.
C#:
//для тех, кто пишет на c#
CommonCode.GetHeaders(instance, "https://ya", "GET", CommonCode.SearchType.Contains, 0, 90, out string cookies, out string useragent, out string[] headers,out string url,out string typeMethod,out string bodyResponse);
return url;
Связано это с тем, что на c# нам заголовки надо передать в виде массива, а не переменной, как это сделано в кубике GET-POST. Да и использовать в этом случае переменные от разработчиков зенки тут не нужно.
P.S. Кто повнимательней посмотрит на реализацию заметит, что код явно не оптимальный. Отчасти это связано с тем, что я не программист, а отчасти, что у меня уже была заготовка именно под c#. Я быстренько перепелил её под кубик, не заморачиваясь с тем, чтобы не дублировать код и т.д.
Как использовать это в своих проектах
Я уже упоминал о соц сетях, а именно о случае, когда вам надо спарсить пользователей, но требуется скролл мышкой. Браузер не подходит, т.к. работает очень медленно и много вы так ненапарсите (по крайне мере у меня не вышло).В видео ниже я демонстрирую пример заготовки парсера для инстраграмма. ВАЖНО: это лишь набросок, а не полноценный парсер. Мне важно передать вам идею, а уж реализовывать вам придется самим. На этом у меня всё. Надеюсь, был полезен.
- Номер конкурса статей
- Четырнадцатый конкурс статей
- Тема статьи
- Парсинг
Вложения
Последнее редактирование:






Стас Костюшкин сделал заявление о романе с Наталией Орейро"
