habrahabr

Как я писал бота для аукциона AliExpress

  • среда, 2 июля 2014 г. в 03:10:39
http://habrahabr.ru/post/228209/

imageЗнаете, на aliexpress есть такие аукционы — Gaga Deals, сейчас там помойка, но когда-то были очень интересные предложения. Их идея заключалась в том, что:

  • Продажи стартуют каждый час
  • Число товаров ограничено
  • Кто первый встал того и тапки


Были очень вкусные лоты со скидкой 90%, топовые смартфоны этого года за 200-300 долларов, прошлогодние по 100 долларов. Разыгрывалось всего по 5 штук каждой позиции. Попробовал выиграть вручную, разумеется ничего не получилось. Ну и решил я написать бота…

Первым делом прощупал как оно вообще работает, вручную. Все свои попытки выиграть я записывал фидлером, потом копался в его отчетах. Пока копался, думал какого бота написать. Начал было делать консольное приложение с отправкой запросов через сокеты и парсингом ответов. Разыгрывались сначала вкусные лоты, и все попытки выиграть их вручную были безуспешными, но я не расстраивался, анализировал трафик, программировал шаги из того что проанализоровал. Тут подтянулись никому ненужные лоты. Наконец то я прошёл дальше и увидел капчу. Консольное приложение отпало сразу. Пришло в голову написать расширение для хрома. Целью было помочь мне быстро докликаться до капчи, поставить курсор для ввода, и потом кликать дальше. Сказано сделано, для такого расширения нужно всего 2 файла: manifest.json и content.js. В манифесте прописываем content.js как инжектируемый скрипт и всё, теперь он выполняется на каждой странице. А там через document.querySelector выбираем нужные элементы и программно кликаем по ним. Бот или лучше назвать пока его Helper работает на ура, ненужные товары заказывает без проблем, а нужные всё равно оказываются уже проданы. Слишком медленно.

Отчасти проблема была в том, что обратный отчет на сайте отстаёт от реальных часов, за час наверно на 5 минут. Плюс если обновить одновременно 2 страницы они могут загрузится со сдвигом в счётчике в 2 секунды.

Следовательно, надо постоянно обновлять страницу и следить за актуальным счётчиком. Открыл несколько вкладок, стал писать бота с обменом информацией через localstorage расширения, но на неактивных вкладках были постоянные проблемы, то скрипт не стартует, то querySelector ничего не находит, то в выбранном элементе текста с оставшимся временем нет — парсить нечего. А у активной страницы всегда всё работало.

Проблема видимо в оптимизации браузера с невидимыми вкладками, надо все страницы на виду держать. Сделал 9 фреймов прямо внутри главной страницы, в которых обновлялись постоянно страницы продукта со счётчиком, но теперь прямого доступа к фрейму не было. Странно, все страницы на одном домене, скрипт работает из контекста расширения, но при попытке доступа к frames[i].contentDocument — индейская национальная изба -”фигвам” называется. Оказалось что китайцы на главной странице присваивали document.domain = «aliexpress.com» — к домену второго уровня, не знаю зачем им это надо, других фреймов на странице нет. Я попытался вернуть обратно, не тут то было. Оказывается уровень домена уменьшать можно, а увеличивать нельзя. Даже если страница загружена с того-же домена который ты хочешь присвоить. Пришлось везде менять домен на второй уровень — прямой доступ к фреймам получил. Парсил время, вычислял лучшее и не трогал его пока кто нибудь не загружался с более лучшим временем, обновлял другие фреймы — это работало, лучший счётчик всегда был готов к клику. Потом число фреймов сократил до 4.

Отладил расширение на ненужных лотах, при наступлении времени «Ч» оно меня благополучно вело до капчи, которую я вводил и нажимал enter, далее заказ оформлялся автоматически. Всё подготовлено, и я стал ждать новый розыгрыш.

Во время следующего розыгрыша меня ждал сюрприз в виде диалоговых окон выбора цвета и/или комплектации, такого я ещё не видел и мой бот на них останавливался, быстро были дописаны соответствующие шаги и…

Всё продано, постоянно всё продано. Слишком медленно, что делать? Китайские и индийские сервисы по распознаванию капчи сработают не быстрее меня. Нормальную программу по распознаванию к расширению не прикрутишь. Уже подумывал вернуться к консольному приложению, и закинул вопросы на работе кто — что знает какие-либо модули или библиотеки по распознаванию капчи. Стал смотреть как загружать капчу, откуда взять url. как заметил особенность, картинка капчи подгружается с другого домена «checktoken1.alibaba.com», в url подставляется идентификатор сессии и всё, при обновлении картинки — цифры каждый раз разные.

И тут меня осенило
Капчу можно распознать заранее.
Она видимо работает так: когда приходит запрос на сервер капчи, он генерирует текст и по нему картинку. Сохраняет последнее соответствие текста и id сессии в базе, без проверки что вообще такая сессия существует и была открыта страница с капчей. А уже после отправки формы проверяется соответствие введенного текста пользователем и текста из базы.


Проверил я свою догадку так: в hosts заблокировал домен checktoken1.alibaba.com для checktoken1.alibaba.co прописал нужный IP и загрузил картинку в другой вкладке (насчёт этого я боялся больше всего, с поддельного домена картинка могла бы и не загрузится и пришлось бы использовать второй комп). Обновил форму с капчей. Ввёл старое значение, форма сработала, капча валидная, опытным путем установил значение сброса сессии в 15 минут.
Доработал страницу с фреймами, сделал текстовое поле и картинку с другого домена, вводил капчу примерно за 5 минут до розыгрыша, и расширение работало как часы, если конечно был не фейк и не было других злобных роботов.

Собственно, теперь можно было бы вернуться к консольному приложению, без браузера оно бы работало гораздо шустрее, но лень матушка мне подсказывала — зачем писать снова когда и так работает.

Осенью 2013-го разработчики aliexpress что-то сделали с капчей, распознанная заранее их перестала удовлетворять, и мой бот перестал работать. В режиме Helper’a с ручным распознаванием капчи заказ оформляется слишком медленно.

Итого

Из крупного выиграл фотик Nikon d5100 за $246 в мае 2013, телефон Nokia lumia 800 за $136 в марте 2013, Blackberry bold 9900 за $136. Ничего из топовых предложений так и не смог выиграть, либо там фейки, либо боты ещё по злее моего там пасутся. Через месяца 2-4 я проверял, кто скупил эти топовые позиции — покупатели были только из России, Белоруссии и Украины.

Исходники расширения на GitHub