[Урок 4] . Объекты и массивы JS. Парсим список биткойн-кранов с faucetbox.com при помощи iMacros.

Боты, которых мы будем создавать, будут не только выполнять какие-либо действия на сайтах, но и собирать, структурировать и перерабатывать информацию. Стандартных средств 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 и исследуем первую ссылку в списке кранов.

iMacros биткойн кран

Как мы можем видеть, ссылка находится внутри таблицы с классом "table faucets-list". Давайте переключимся во вкладку консоли и прикинем, как лучше выдрать данные. Попробуем простой JS-код window.document.querySelectorAll(".faucets-list a"), который вернет все ссылки из таблицы.

ссылки из Bitcoin

Сразу стало ясно, что такой подход не сработает, на странице 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&nbsp;like&nbsp;this&nbsp;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+ кранов найдется пару десятков, с которых получится собрать сатоши, и все это в автоматическом режиме.

Оставляйте ваши вопросы и отзывы в комментариях!

 

1 комментариев

  1. Здравствуйте! Не подскажите как этот код скормить imacrosu, уже неделю мучаюсь(((
    Я так понимаю что проблема именно с window, но без нее мне никак. Если запустить в консоле, то срабатывает четко, а вот IMACROS не хочет негодяй. Подскажите пожалуйста, если знаете, в чем проблема.

    Fn = «ок»;
    Fan = «Fn2»;

    function Fn1(){
    window[Fan]();
    }

    function Fn2(){
    alert(window.Fn)
    }

    Fn1();

    Ответить

Оставить комментарий