Всем привет. Я не силен в техническом плане, поэтому что такое 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;
P.S. Кто повнимательней посмотрит на реализацию заметит, что код явно не оптимальный. Отчасти это связано с тем, что я не программист, а отчасти, что у меня уже была заготовка именно под c#. Я быстренько перепелил её под кубик, не заморачиваясь с тем, чтобы не дублировать код и т.д.
Как использовать это в своих проектах
Я уже упоминал о соц сетях, а именно о случае, когда вам надо спарсить пользователей, но требуется скролл мышкой. Браузер не подходит, т.к. работает очень медленно и много вы так ненапарсите (по крайне мере у меня не вышло).В видео ниже я демонстрирую пример заготовки парсера для инстраграмма. ВАЖНО: это лишь набросок, а не полноценный парсер. Мне важно передать вам идею, а уж реализовывать вам придется самим. На этом у меня всё. Надеюсь, был полезен.
- Тема статьи
- Парсинг
- Номер конкурса статей
- Четырнадцатый конкурс статей
Вложения
-
1,1 КБ Просмотры: 242
-
44 байт Просмотры: 200
-
49,3 КБ Просмотры: 249
-
17,2 КБ Просмотры: 267
Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...
Для того чтобы запустить шаблон, откройте нужную программу. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.
Последнее редактирование: