- Регистрация
- 21.04.2016
- Сообщения
- 2 311
- Реакции
- 1 192
- Баллы
- 113
Это ждун и он ждет, пока в твоём шаблоне закончится пауза и шаблон наконец продолжит зарабатывать тебе копеечку на хлеб с красной икрой.
Добрый день всем и хочу вам представить шаблон. Он ускорить рутинную работу с ZennoPoster.
Часто бывает такое, что шаблон буквально усеян паузами. Делается это по банальной причине - подождать пока гарантированно загрузится элемент. Ещё один вариант решения проблемы с ожиданием элементов на странице - это кубик свойства действия:
При подходе с паузами всегда возникает лишнее время ожидания, а при использовании кубика нельзя задать необходимые параметры, как, например, дождаться пока у элемента размер будет больше 50 пикселей.
Всё это мучило и меня. Я начал использовать циклы в следующем стиле:
C#:
for (int i = 0; ;i++)
{
HtmlElement heSubmit = instance.ActiveTab.FindElementByXPath(@"//button[@class='submit", 0);
if (!heSubmit.IsVoid)
{
heSubmit.RiseEvent("click", "Full");
break;
}
if (i > 5)
throw new Exception("Кнопка сабмит не найдена");
Thread.Sleep(1000);
}
Поэтому я искал альтернативное решение и оно нашлось. Я реализовал подход из библиотеки Selenium с ожиданием элементов, который очень хорошо показал себя на практике, оказался очень удобным и теперь я его использую повсеместно.
Давайте рассмотрим его подробнее в виде самого простого кода. К коду приложил комментарии
C#:
//Создаем браузер
IBrowser browser = new ZennoBrowser(instance, project);
//Создаем ожидающий элемент, в каждом кубике создается всего 1 раз
BrowserWait<ITab> waiter = new BrowserWait<ITab>(browser.ActiveTab, TimeSpan.FromSeconds(15))
{
//Устанавливаем таймаут проверки страницы, по умолчанию - 1 секунда
//Можно закомментировать
PollingInterval = TimeSpan.FromSeconds(1)
};
//Ждем пока html элемент появится и получаем его
IHtmlElement he = waiter.Until(ExpectedConditions<ITab>.ElementExists(By.XPath("//div[@class='recaptcha-checkbox-checkmark']")));
С первого взгляда код кажется не меньше кода с циклом for. Но из всего кода большая часть только подготовительная, а основной является следующая:
C#:
IHtmlElement he = waiter.Until(ExpectedConditions<ITab>.ElementExists(By.XPath("//div[@class='recaptcha-checkbox-checkmark']")));
Давайте теперь нажмем на кнопку и подождем пока стиль изменится на "visibility: visible". Я только дополню прошлый код:
C#:
//Нажимаем на кнопку
he.ClickFull();
//Ждем пока появится элемент с нужным параметром
IHtmlElement heWindows = waiter.Until(ExpectedConditions<ITab>.ElementExists(By.XPath("//div[contains(@style, 'visibility: visible')]/div/iframe[starts-with(@src, 'https://www.google.com/recaptcha/api2')]")));
Далее рассмотрим более сложный вариант, когда рассматривается сразу несколько вариантов. Код сопроводил комментариями.
C#:
IBrowser browser = new ZennoBrowser(instance, project);
BrowserWait<ITab> waiter = new BrowserWait<ITab>(browser.ActiveTab, TimeSpan.FromSeconds(15))
{
PollingInterval = TimeSpan.FromSeconds(1)
};
IHtmlElement heSiteKey = null;
IHtmlElement heRecaptchaSubmit = null;
IHtmlElement heSendCode = null;
waiter.Until(condition =>
{
//Если найдена кнопка с просьбой перезагрузить страницу, то генерируем ошибку
IHtmlElement heReloadPage = browser.ActiveTab.FindElement(Info.ReloadPageXPath);
if (heReloadPage != null)
throw new Exception("Страница с рекапчей не открылась");
//Если на странице не появилась рекапча, а сразу появился нужный нам блок с запросом телефона, то удачно завершаем
//return true как раз означает удачное завершение цикла
heSendCode = browser.ActiveTab.FindElement(Info.SendCodeXPath);
if (heSendCode != null)
return true;
//Проверяем на наличие рекапчи. Если её нету, то ждем и начинаем сначала весь цикл проверок
//return false как раз означает, что нужно начинать все проверки с начала
heSiteKey = browser.ActiveTab.FindElement(Info.SiteKeyXPath);
if (heSiteKey == null)
return false;
//Проверяем на наличие кнопки submit. Если её нету, то ждем и начинаем сначала весь цикл проверок
//return false как раз означает, что нужно начинать все проверки с начала
heRecaptchaSubmit = browser.ActiveTab.FindElement(Info.RecaptchaSubmitXPath);
if (heRecaptchaSubmit == null)
return false;
//В данном случае все необходимые условия выполнены, поэтому можем спокойно завершить проверки
//return true как раз означает удачное завершение цикла
return true;
});
1) возвращается false, если выполнены не все условия, ждёт и потом идет ещё на следующий круг цикла, пока не достигнет ошибки или true
2) генерируется ошибка, если дальнейшее ожидание не имеет смысла
3) возвращается true, когда все условия выполнены и выходит из цикла.
Таким образом можно проектировать даже сложные конструкции ожидания.
Этот пример вырезан из моего кода, поэтому не пытайтесь его повторить, так как он выдаст ошибку из-за моих упрощений в виде замены By.XPath на Info.ReloadPageXPath и подобных.
Напоследок ещё один пример. Тут код начинает грузить страницу и сразу же проверяет в быстром режиме пока основной фрейм не загрузится. Таймаут проверок - 100 мс.
C#:
instance.ActiveTab.Navigate("https://www.google.com/recaptcha/api2/demo");
IBrowser browser = new ZennoBrowser(instance, project);
BrowserWait<ITab> waiter = new BrowserWait<ITab>(browser.ActiveTab, TimeSpan.FromSeconds(15))
{
PollingInterval = TimeSpan.FromMilliseconds(100)
};
waiter.Until(condition =>
{
string result = browser.ActiveTab.MainDocument.EvaluateScript("return document.readyState == 'complete';", true);
bool documentOpened = result == "true";
return documentOpened;
});
- Номер конкурса шаблонов
- Восьмой конкурс шаблонов
- Уровень сложности
- Продвинутый
- Категория
- Полезно
Вложения
Последнее редактирование:




