Боты, которых мы будем создавать, будут не только выполнять какие-либо действия на сайтах, но и собирать, структурировать и перерабатывать информацию. Стандартных средств iMacros для подобных целей просто нету. Здесь нам поможет Javascript, который предоставляет богатый инструментарий для работы с любыми данными.
Мы используем не самый старый браузер для ботоводства, поэтому у нас есть возможность насладиться новыми и очень удобными фишками JavaScript. Мы будем использовать некоторые фишки из спецификации ECMAScript 2015(ES 6) и проверенные годами подходы к программированию. Для качественного понимания JS я категорически рекомендую вот этот бесплатный онлайн-учебник на русском языке http://learn.javascript.ru — это лучшее и очень подробное руководство по Javascript от очень крутого Frontend-девелопера Ильи Кантора. Я не преследую цель обучить вас все возможностям JS, я буду рассматривать только те области, которые нам понадобятся для написания ботов.
Типы переменных Number, String, Boolean, Function, Object
Как вы уже знаете, в JS можно задавать переменные при помощи ключевого слова var. Обратите внимание, что при таком задании переменной, она автоматом прописывается в глобальный объект window, но доступна не из любого места. Можно сделать переменную глобальной, если убрать var, и тогда она будет доступна везде. На этом примере, вы увидите отличия:
// Пишем функцию, но не запускаем function testVars () { var t = 5; // Обычная переменная s = true; // Глобальная переменная window.console.log(window.t); // "t" автоматом записывается в window window.console.log(window.s); // "s" автоматом записывается в window } //Запускаем функцию testVars(); window.console.log("s = ", s); // глобальная переменная доступна, выводит true window.console.log("t = ", t); // вылезает ошибка undefined, отсюда переменная недоступна
В Javascript нету строгой типизации, как в С++ например. И стоит помнить, что в JS, все — является объектом, даже функции и переменные. При помощи ключевого слова var мы можем создавать переменные различных типов и проверить их тип, используя функцию typeof()
:
var n = 1; var nan = NaN; //Not a number - тоже является численной переменной var inf = Infinity; //бесконечное число - тоже является численной переменной window.console.log(typeof(n), typeof(nan), typeof(inf)); // выведет "number number number" var s = "little text"; window.console.log(typeof(s)); // выведет "string" var b = true; window.console.log(typeof(b)); // выведет "boolean" var f = function () {}; //это функция window.console.log(typeof(f)); // выведет "function" var a = {}; //это пустой объект window.console.log(typeof(a)); // выведет "object" var a = []; //это массив window.console.log(typeof(a)); // выведет "object" var d = new Date(); //это дата window.console.log(typeof(d)); // выведет "object"
Это основные типы переменных, которые мы будем использовать. А теперь давайте перейдем к самой интересной и необходимой части — мы будем создавать объекты и массивы объектов.
Не путайте Объекты и Массивы
Массив — это набор данных, к каждому элементу массива можно обратиться по индексу и получить значение. Нумерация объектов в массиве начинается с нуля. В массиве могут содержаться переменные и значения любых типов.
Объект — представляет собой ассоциативный список с неограниченной вложенностью. У объекта обязательно есть ключи и их значения. Значением может быть переменная любого типа, функция, другой объект и даже любой массив.
Новичкам крайне рекомендую изучить раздел отличного учебника по JS — http://learn.javascript.ru/data-structures
Примеры работы объектов и массивов:
var arr = []; // Пустой массив var arr = [1, 2, "text", true, {objName: "objValue"}, []]; window.console.log(arr[0]); //выведет первый элемент массива window.console.log(arr[4].objName); //выведет значение objName пятого элемента массива var obj = {}; // пустой объект obj.name = "Nagibaka"; // Добавляем новый ключ объекту window.console.log(obj.name); // Читаем знаение объекта window.console.log(obj['name']); // Можно читать его и таким образом, записывать аналогично // Усложним объект var obj = { name: "Nagibaka", site: "https://nagibaka.ru", status: { online: true, onlineUsers: 170 } }; window.console.log(obj.name, " have a site with online: ", obj.status.onlineUsers, " users.");
Нам очень часто пригодится использование массивов объектов, это массивы, которые содержат в себе различные объекты. Приведу пример, как он выглядит:
var arr = [ { name: "Nagibaka", site: "https://nagibaka.ru", status: { online: true, onlineUsers: 170 } }, { name: "Yandex", site: "http://ya.ru", status: { online: true, onlineUsers: 54000000 } } ]; // Выводит данные из каждого объекта в массиве arr.forEach(function (item) { window.console.log(item.name + ' have online: ' + item.status.onlineUsers + ' users.') });
Это очень важно понимать принцип работы массивов и объектов. Они используются в формате JSON, в базе данных MongoDB, которую мы позже будем использовать, для построения крутых и четких скриптов с хорошо организованным кодом, да вообще везде.
Парсим список биткойн-кранов с faucetbox.com
Чтобы теория не была слишком скучной, давайте попробуем учиться на практике, иначе не ясно, а зачем нам эти объекты, массивы и прочее.
Наша задача будет следующей: Мы заходим на сайт https://faucetbox.com/en/list/BTC — там список биткойн-кранов, на текущий момент их 1035. Далее мы получаем всю доступную информацию по каждому крану(название, ссылка, возраст и т.д.) и заносим все данные в массив, с которым потом в дальнейшем будет удобно работать.
Откройте Firefox(надеюсь расширение Firebug у вас уже установлено). Открываем Firebug по нажатию клавиши F12 и исследуем первую ссылку в списке кранов.
Как мы можем видеть, ссылка находится внутри таблицы с классом "table faucets-list"
. Давайте переключимся во вкладку консоли и прикинем, как лучше выдрать данные. Попробуем простой JS-код window.document.querySelectorAll(".faucets-list a")
, который вернет все ссылки из таблицы.
Сразу стало ясно, что такой подход не сработает, на странице 1035 кранов, а в консоли результатов больше 2805. Также мы видим, что для голосования за кран тоже используется тег <a>. Посмотрим на ссылки повнимательней:
//Так выглядит необходимая нам ссылка: <a target="_blank" href="leave?url=http%3A%2F%2Ffree-bitc0in.com%2F"> Free-bitc0in.com </a> //А вот так ссылка для голосования: <a title="" data-placement="top" data-toggle="tooltip" data-vote="up" data-faucet="137355" class="vote-link up" href="#" data-original-title="I like this faucet"> <span class="glyphicon glyphicon-thumbs-up"></span> </a>
Отличий много, нужные ссылки легко выделить, я буду делать это по атрибуту target, который имеется и одинаковый только у ссылок на сами биткойн-краны. Немного переделаем наш селектор:
window.document.querySelectorAll(".faucets-list a[target='_blank']") window.document.querySelectorAll(".faucets-list a[target='_blank']").length // 1035 элементов нашлось, как и ожидалось
Метод querySelectorAll
возвращает массив DOM-элементов. Для пробы мы можем обратиться к первой найденной ссылке и получить значение ее атрибута href.
// Получаем значение аттрибута href для первой ссылки var link = window.document.querySelectorAll(".faucets-list a[target='_blank']")[0].getAttribute('href'); // в link сейчас содержится "leave?url=http%3A%2F%2Ffree-bitc0in.com%2F" // Убираем лишний "leave?url=" link = link.replace("leave?url=", ""); // http%3A%2F%2Ffree-bitc0in.com%2F // Преобразуем в нормальный вид link = decodeURIComponent(link); // http://free-bitc0in.com/ - Отлично!
Все супер, мы получили чистую ссылку на первый кран. Писать под каждый кран эти функции, меняя индекс 0 на другие долго и неэффективно. Нам на помощь придут циклы. Воспользуемся самым простым, давайте изменим наш test.js.
var data = window.document.querySelectorAll(".faucets-list a[target='_blank']"); for (var i = 0; i < data.length; i++) { // Объединяем все манипуляции со строкой // Для лучшей читаемости кода я их напишу в несколько строк var cranUrl = decodeURIComponent( data[i] .getAttribute('href') .replace("leave?url=", "") ); window.console.log(cranUrl); }
Запустив подобный код, мы увидим в консоли список всех ссылок на краны. Это основа. Теперь давайте попробуем получить для каждого крана его название, возраст, и определим наличие метки «Possibly broken», что означает, что кран скорей всего сломан, либо от него не было давно выплат.
Финальный код:
var cransList = []; var data = window.document.querySelectorAll(".faucets-list a[target='_blank']"); for (var i = 0; i < data.length; i++) { // Получаем название крана(.replace - третьим параметром 'g' - это глобальная замена всех совпадений) var cName = data[i].innerHTML.replace('\n','','g'); var cUrl = decodeURIComponent( data[i] .getAttribute('href') .replace("leave?url=", "") ); var cAge = data[i].closest('tr').querySelector('.age-col').innerHTML.replace(' days',''); // тут мы используем тернарное выражение var cIsBroken = ( data[i].closest('tr').querySelector('.label-danger') != null && data[i].closest('tr').querySelector('.label-danger').innerHTML == "Possibly broken" ) ? true : false; // Создаем объект с данными о кране var obj = { cranName: cName, cranUrl: cUrl, cranAge: cAge, cranIsBroken: cIsBroken } // Добавляем объект в массив cransList cransList.push(obj); } window.console.log(cransList);
Вот и все, мы создали очень удобный массив объектов, с которым очень легко и удобно работать. Такой массив вы сможете легко изменять, фильтровать, осуществлять поиск, сохранять и читать данные в формате JSON, который нативно без каких-либо плагинов поддерживается в Javascript.
Давайте немного пофантазируем, у нас есть список кранов, можно зайти на каждый из них, определить тип капчи и тип антиботов, автоматом вставить свой кошелек, запустить функцию распознавания капчи и собрать сатоши. Разумеется, часть кранов будет не работать, где-то будет авторизация, где-то нетипичные шаблоны, но все же из 1000+ кранов найдется пару десятков, с которых получится собрать сатоши, и все это в автоматическом режиме.
Оставляйте ваши вопросы и отзывы в комментариях!
Здравствуйте! Не подскажите как этот код скормить imacrosu, уже неделю мучаюсь(((
Я так понимаю что проблема именно с window, но без нее мне никак. Если запустить в консоле, то срабатывает четко, а вот IMACROS не хочет негодяй. Подскажите пожалуйста, если знаете, в чем проблема.
Fn = «ок»;
Fan = «Fn2»;
function Fn1(){
window[Fan]();
}
function Fn2(){
alert(window.Fn)
}
Fn1();