В прошлом уроке вы уже немного познакомились с регулярными выражениями JavaScript. Сегодня мы попробуем использовать их на практике совместно с iMacros. Я буду рассматривать примеры, которые вам могут реально пригодиться в ваших скриптах. Бывают ситуации, когда нужно обработать несколько сайтов с различным дизайном и соответственно с отличающейся html-разметкой. Предположим, вы не знаете, в каких тегах находится интересующая вас информация, но точно знаете, что она расположена сразу после какой-либо фразы или между двух слов и состоит, скажем из нескольких цифр. Для таких задач, регулярные выражения — идеальное решение.
Как получить размер награды, интервал сбора и процент реферальной комиссии биткойн-крана?
В прошлых уроках мы с вами рассматривали способы получения баланса биткойн-крана при помощи методов для работы со строками и при помощи регулярных выражений. Предлагаю немного усложнить задачку. Прежде чем писать код, давайте изучим пару обычных биткойн-кранов.
Вот первый пример биткойн крана:
Тут мы видим фразу «150 satoshi every 180 minutes«, под которую легко написать регулярку используя опорные слова и получить размер награды и интервал для клейма.
И еще «Share this link with your friends and earn 10% referral commission«, тут тоже достаточно опорных слов, вокруг цифры 10, которую нам предстоит извлечь.
Второй пример:
Тут сложнее, количество наград несколько и у них разный процент получения, значит — понадобится дополнительная регулярка. Для рефералки используется такая же фраза, значит регулярка от первого крана подойдет.
Пока хватит этих двух разновидностей кранов, хотя можно адаптировать ваш код под любое количество различных кранов и написать универсальный скрипт по сбору сатош с большинства кранов на автомате.
Получаем размер реферальной комиссии биткойн-крана
Начнем с простого скрипта. У нас есть фраза:
«Share this link with your friends and earn 10% referral commission«
На разных кранах начало фразы может отличаться, но как правило заканчивается она одинаково «referral commission«. Поэтому мы составим шаблон такого вида:
[1-3цифры][знак процента][пробел и остаток фразы]
Если выражать в коде, то получится вот так:
var str = window.document.querySelector('body').textContent; // текст всей страницы var found = str.match(/(\d{1,3})% referral commission/i); // ["10% referral commission", "10"] window.console.log(found[1]); // 10
\d{1,3}
означает от 1 до 3 цифр, еще мы заключили эту конструкцию в круглые скобки, это добавило в массив значение, которому соответствует это выражение — то есть «10». Вроде все неплохо, но давайте посмотрим, что произойдет, если на странице не окажется строки с реферальной комиссией.
Мы получим ошибку TypeError: found is null, line 107 (Error code: -991)
Она произошла, потому что на странице не нашлось ни одного совпадения с шаблоном нашего регулярного выражения и в итоге found = null. Ошибка возникает, когда мы пытаемся вывести на экран второй элемент массива при помощи found[1], его просто не существует. Из-за таких мелких ошибок ваш скрипт просто перестанет работать, поэтому всегда думайте, как будет работать ваш iMacros-скрипт во всех возможных ситуациях. Давайте исправим эту ошибку и заодно обернем весь скрипт в функцию, чтобы можно было одной строкой вызывать в нужном месте. Наша функция будет возвращать либо процент награды, либо false.
var getRefComission = function () { var str = window.document.querySelector('body').textContent; var found = str.match(/(\d{1,3})% referral commission/i); return found != null ? found[1] : false; }; window.console.log( getRefComission() ); // 10
Тут я чуть иначе определил функцию var getRefComission = function () {
, это тоже самое, что и function getRefComission () {
. Такой код мы можем запустить на абсолютно любом сайте и ошибок не будет при любом содержимом страницы. Всегда старайтесь писать функции, которые не будут сваливаться с ошибкой и останавливать работу iMacros, даже если они выполняются на абсолютно пустой странице. Тогда ваши скрипты будут бронебойными и смогут работать при любых ошибках 24 часа в сутки и 7 дней в неделю, не вылетая.
Получаем интервал сбора сатош на биткойн-кране
С промежутком, через который можно собирать сатоши, все просто, будем делать также, как и с рефералкой, только добавим еще спереди ключевые слова. Наши фразы:
«150 satoshi every 180 minutes.«
«60 (95%), 100 (4%), 150 (1%) satoshi every 240 minutes.«
На данный момент нас интересует не размер награды, а вторая часть фразы, которая идентична(выделил курсивом). Составляем сразу регулярное выражение и оборачиваем его в функцию:
var getClaimInterval = function () {
var str = window.document.querySelector('body').textContent;
var found = str.match(/satoshi every (\d{1,4}) minutes/i); // ["satoshi every 240 minutes", "240"]
return found != null ? found[1] : false;
};
window.console.log( getClaimInterval() ); // 240
Думаю, тут все понятно.
Получаем размер награды на биткойн-кране
Здесь придется немного попотеть. В первом варианте у нас одна цифра получается. Во втором варианте несколько возможных наград с различной вероятностью. Получается нам нужно создать функцию, которая будет работать универсально и возвращать данные в одном формате. Будет не круто, если в первом случае у нас результатом работы функции будет одна цифра, а во втором случае, будет массив с вероятностями и размером награды. Предлагаю сделать единый формат, это избавит от лишнего кода в дальнейшем. Я хочу чтобы он выглядел вот так:
// Для первого случая(Награда 150 сатоши со 100% вероятностью) [ { reward: 150, percentage: 95 } ] // Для второго случая [ { reward: 60, percentage: 95 }, { reward: 100, percentage: 4 }, { reward: 150, percentage: 1 } ]
При помощи такой структуры мы описали все возможные случаи для наших 2 кранов. Нужно сделать скрипт, который будет работать с любым количеством возможных наград.
Небольшая ремарка: на некоторых кранах помимо нескольких наград с разным шансом, еще размер каждой награды может варьироваться, например «100-120(10%)«, тогда вы можете вместо ключа reward в массиве объектов, добавить minReward
и maxReward
. Вот так легко можно расширять возможности выбранного вами формата данных.
Для создания более сложных регулярок я обычно использую сайт https://regex101.com. Я просто зашел на биткойн-кран и с помощью Ctr+A и Ctrl+C скопировал весь текст и вставил на этом сайте. Я написал выражение и справа сразу видно, что в тексте найдено 3 совпадения с паттерном, и, при помощи скобочных групп, я могу вытащить значения процентов и наград.
Итоговое регулярное выражение:
(\d{2,4}) \((\d{1,3})%\)
(\d{2,4})
— первая скобочная группа(размер награды в сатошах), от 2 до 4 цифр
(\d{1,3})
— вторая скобочная группа(проценты), от 1 до 3 цифр
\( ... \)
— это обычные скобки(не путайте со скобочными группами), как видите они экранированы обратными слешами
Не забудьте пробел между скобочными группами, или можете заменить его классом \s
Забегая чуть вперед, скажу, что мы будем применять нестандартное использование функции replace(), о чем я говорил в прошлом уроке.
Итоговый код получится такой:
var getReward = function () { var str = window.document.querySelector('body').textContent; var out = []; // результирующий массив // Для первого крана var found = str.match(/(\d{1,9}) satoshi every (\d{1,4}) minutes/i); // found = ["150 satoshi every 180 minutes", "150", "180"] // для второго крана эта регулярка вернет null if (found != null) { out.push({ reward: parseInt(found[1]), // Преобразуем строку в число percentage: 100 }); } // Для второго крана // Такое решение с match не подойдет: // var found2 = str.match(/(\d{2,4}) \((\d{1,3})%\)/ig); // ["60 (95%)", "100 (4%)", "150 (1%)"] // Воспользуемся читорным методом replace с каллбэком: var found = str.replace(/(\d{2,4}) \((\d{1,3})%\)/igm, function (match, rwd, prtg, offset, string) { out.push({ reward: rwd, percentage: prtg }); return match; }); return out; }; window.console.log( getReward() );
Отлично! На обоих кранах мы получаем ровно такие структуры данных, какие я описал выше. Между прочим, это корректный JSON-формат, с которым мы познакомимся чуть ближе в следующих уроках и вы полюбите его!
Еще я буду вас потихоньку приучать, как грамотнее оформлять свой код. Вы наверно уже привыкли видеть в скриптах из интернета паршиво отформатированные скрипты, содержащие в себе множество var и кучу function func1() {} и т.д. Это не самый хороший подход.
Я сейчас вам покажу, как можно упаковать все созданные нами функции в один большой объект. Такие объекты очень удобно использовать в своих различных скриптах, как своего рода небольшую библиотеку функций. Помимо упаковки в объект, я буду использовать указатель this. Подробно разбирать не буду, в принципе там все и так должно быть более-менее понятно.
Мини-библиотека для получения информации о биткойн-кране
var Helper = { _getContent: function () {return window.document.querySelector('body').textContent}, getRefComission: function () { var found = this._getContent().match(/(\d{1,3})% referral commission/i); return found != null ? found[1] : false; }, getClaimInterval: function () { var found = this._getContent().match(/satoshi every (\d{1,4}) minutes/i); return found != null ? found[1] : false; }, getReward: function () { var out = []; var found = this._getContent().match(/(\d{1,9}) satoshi every (\d{1,4}) minutes/i); if (found != null) { out.push({ reward: parseInt(found[1]), percentage: 100 }); } var found = this._getContent().replace(/(\d{2,4}) \((\d{1,3})%\)/igm, function (match, rwd, prtg, offset, string) { out.push({ reward: rwd, percentage: prtg }); return match; }); return out; } }; // Пример использования window.console.log(` ================================== Possible rewards:`); Helper.getReward().forEach(function (item) { window.console.log(`${item.reward} satoshi with chance ${item.percentage}%`); }); window.console.log(` Interval: ${Helper.getClaimInterval()} minutes Ref.reward: ${Helper.getRefComission()}% ================================== `);
Вот, что получится:
Сегодня мы разобрали не очень сложные примеры, но очень полезные с практической точки зрения. Регулярные выражения только по-началу кажутся страшными и непонятными. Поработав с ними некоторое время, вы будете испытывать огромное удовольствие, когда одна ваша достаточно сложная регулярка будет раздербанивать тысячи строк текста в красивые структурированные массивы объектов, как в примерах выше.
Пишите ваши замечания, вопросы и предложения в комментариях!