wiki:скрипт_для_проверки_баланса_в_peoplenet

Это старая версия документа.


Скрипт для проверки баланса в

PeopleNet В данной статье рассматривается процесс создания скрипта для проверки баланса украинского мобильного оператора PeopleNet, который обычно используется для мобильного доступа к 3G интернету. Целью статьи является популяризация написания скриптов для облегчения ежедневных задач.

Всё началось с вопроса моего друга. «Нельзя ли что-нибудь сделать с теперешним подсчетом трафика в PeopleNet? Ведь что-то же считает!» Я сразу же стал теоретизировать, что таки да, можно… И через пару ночей я засел за работу и родился скрипт, которым я хочу поделиться с вами. Нужно ввести читателя в курс дел.

В популярном пакете «777» от PeopleNet предоставляется ежедневно трафик размером 232 МБ (как бы 7 ГБ в месяц и как бы за 77 грн). Узнать остаток доступного трафика на текущие сутки можно, отправив с 3G модема SMS на служебный номер и прочитав ответ (при помощи «фирменной» программы для Windows. Отправлять SMS в Linux, с 3G модемов как-то еще не очень получается. Кроме того, существует страничка биллинга, называемая Системой самообслуживания клиентов. Раньше я уже писал скрипт для подобных целей. Но раньше было проще. Можно было получить информацию о потраченном трафике за каждую сессию за каждый день в течение последнего месяца. Теперь же на странице красовалось одно число — количество потраченных МБ с начала месяца. С тех пор сёрфинг в сети велся практически вслепую…

Я почти полностью переписал скрипт, избавился от множества промежуточных шагов, временных переменных и файлов, и это пошло скрипту только на пользу. Его основу составляет одна «волшебная» строчка кода, которая получает со страницы самообслуживания число потраченных с начала месяца мегабайт:

curl -s -d "X_Username=380921234567&X_Password=11223344" --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills&rp="$(expr \( $(date +%y) - 2 \) \* 12 + $(date +%m)) | grep -A 3 EVDO | tail -n 1 | grep -o '[0-9]*'

или в с переносом строки

curl -s -d "X_Username=380921234567&X_Password=11223344" \
--url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills&rp="$(expr \( $(date +%y) - 2 \) \* 12 + $(date +%m)) | \
 grep -A 3 EVDO | tail -n 1 | grep -o '[0-9]*'

Здесь используется curl — удобная программа, которую можно в шутку назвать «веб-браузер для робота». Ее можно вызывать из своих скриптов для отсылки запросов, форм, получения и отправки страниц и файлов. Для того, чтобы получить информацию по своему номеру, вы должны изменить 380921234567 на свой номер, а 11223344 — на свой пароль для входа на страницу самообслуживания. В процессе работы будет загружена страничка размером 11,5 кБ и из нее будет выделено единственное число, которое вы и получите «на выходе». О том, что делать дальше с этим числом, мы поговорим немного позже.

Как работает этот код

Обо всех опциях команды curl вы сможете узнать, если выполните в терминале команду

curl --help

Такой подход к получению справки типичен для большинства команд в Linux. Здесь мы используем такие ключи:

  • -s — «молчаливый» режим. Curl не будет печатать в терминале не нужную нам информацию о размере и скорости закачки указанной страницы;
  • -d и следующая строка в кавычках — данные, отсылаемые на сервер по методу POST;
  • –url и длинная строка, заканчивающаяся перед вертикальной чертой — адрес страницы, которую нужно получить. Сам ключ «–url» можно было бы и не писать, оставив только строку. Вертикальная черта передает страничку, загруженную командой curl, дальше, следующей команде, по конвейеру.

Откуда взялись параметры для ключей -d и –url? Проследим работу системы самообслуживания. Зайдем при помощи обычного браузера на страницу http://my.people.net.ua/. Нас просят ввести номер телефона и пароль, затем нажать кнопку подтверждения. Далее нужно перейти по ссылке «Ежемесячный счет». На следующей странице выбрать нужный месяц из выпадающего списка (текущий месяц находится вверху и поэтому выбирать ничего не нужно) и нажать кнопку подтверждения. На следующей странице нужно пробежаться глазами по таблице и найти в строчке «Передача даних EVDO» нужное нам число. Теперь научим робота делать то же самое. Для исследования страниц нам пригодится ключ -o команды curl. После этого ключа указываем название файла и страничка, указанная в ключе –url будет загружена в этот файл.

Итак, первый шаг:

curl --url "http://my.people.net.ua/" -o "take1.html"

Открываем полученный файл take1.html в текстовом редакторе (нужно хотя бы немного разбираться в html-разметке). Мы видим html-форму:

<form target="_top" action="/TSU/WWW/ACCOUNT_INFO/" method="post"
    name="LoginForm">
    ...
    <input value="" name="X_Username" size="9" title="Введіть номер Вашого
           телефону" type="text">
    ...
    <input name="X_Password" size="9" title="Введіть Ваш пароль" type="password"> 
    ...
    <input value="Вхід" type="submit">
    ...
</form>

Я удалил всё, не относящееся к делу, чтобы можно было сосредоточиться на нашем задании. Итак, данные формы отправляются методом POST, значит, воспользуемся ключом -d команды curl. Вот, если бы метод был GET, то можно было бы не городить огород, а дописать передаваемые данные прямо в строку адреса (примерно так: http://наш.длинный/адрес?параметр1=значение1&параметр2=значение2).

Итак, из анализа формы становится понятно, что при нажатии кнопки подтверждения данные формы отсылаются по адресу http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/ и эти данные — X_Username=номер телефона и X_Password=пароль.

Второй шаг наших раскопок:

curl -d "X_Username=380921234567&X_Password=11223344" --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/" -o "take2.html"

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

<a href="http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO?sid=bills">Ежемесячный счет</a>

Я снова убрал всё лишнее. Попробуем:

curl --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO?sid=bills" -o "take3.html"

Получаем страничку с ошибкой. Хм, попробуем так:

curl --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills" -o "take3.html"

Теперь получаем первоначальную страничку для входа в систему самообслуживания. Нас забыли и снова предлагают ввести номер и пароль! Попробуем не городить огород, а просто объединим две команды, два адреса в один: curl -d «X_Username=380921234567&X_Password=11223344» –url «http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills» -o «take3a.html» Так! Мы продвинулись дальше! Просматривая страницу, находим в ней форму для выбора месяца:

<form action="http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO" method="GET">
  <input type="hidden" name="sid" value="bills">
  <select name="rp">
    <option value="117" selected>вересень 2011 року</option>
    <option value="116">серпень 2011 року</option>
    <option value="115">липень 2011 року</option>
    <option value="114">червень 2011 року</option>
    <option value="113">травень 2011 року</option>
    <option value="112">квітень 2011 року</option>
    <option value="111">березень 2011 року</option>
    <option value="110">лютий 2011 року</option>
    <option value="109">січень 2011 року</option>
    <option value="108">грудень 2010 року</option>
    <option value="107">листопад 2010 року</option>
  </select>
  <input type="submit" value="Показати">
</form>

Я снова убрал всё лишнее из html-разметки. В зависимости от вашего «стажа» в PeopleNet длина списка у вас будет другая. Итак, адрес для отсылки формы ясен; метод, кстати — GET, значит, пишем параметры прямо в строку адреса. Имеется скрытая (hidden) переменная с именем sid и значением bills. Вторая переменная с именем rp и нужным нам значением 117. Формируем адрес: http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills&rp=117

Пробуем снова совместить команды:

curl -d "X_Username=380921234567&X_Password=11223344" --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills&rp=117" -o "take4.html"

Да, мы продвинулись еще дальше. Правда, такого же восторга уже нет. Остается работа. И она заключается в следующем.

Во-первых, каждый месяц число в параметре rp будет меняться. Во-вторых, нам нужно проанализировать код страницы. Подберем формулу для расчета числа:

rp = ( год - 2 ) * 12 + месяц

Номер года (две последние цифры) и номер месяца (две цифры) мы можем получить соответствующими командами:

date +%y
date +%m

Если окружить команду такой оберткой — $(команда), то тогда результат работы этой команды будет представлен в виде строки и его можно будет использовать для дальнейших вычислений в более сложных командах. Для математических расчетов используем команду expr.

expr ( $(date +%y) - 2 ) * 12 + $(date +%m)

Получаем ошибку, говорящую о некорректном синтаксисе, курим маны и «экранируем» скобки, входящие в нашу формулу, а также звездочку (знак умножения), поставив перед ними бэкслэш (\):

expr \( $(date +%y) - 2 \) \* 12 + $(date +%m)

Получаем 117. Что нам и требовалось! Теперь окружаем эту команду при помощи $(…) и подставляем ее вместо числа 117 в нашу супер-команду curl:

curl -s -d "X_Username=380921234567&X_Password=11223344" --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills&rp="$(expr \( $(date +%y) - 2 \) \* 12 + $(date +%m))

Заметьте, что кавычки закрываются после «rp=» и сразу же мы пишем обернутую команду, таким образом, результат команды (число 117) дописывается к строке.

Теперь пришло время «во-вторых» — анализ кода страницы. Вы помните, как выглядит табличка, когда вы заходили через браузер? Ищем строчку с аббревиатурой EVDO и находим такой участок html-разметки:

  <tr>
    <td>
      <i>      Передача даних EVDO</i>
    </td>
    <td class="ar4">
      <i> 224</i>
    </td>
    <td class="ar4">
      <i>0.00</i>
    </td>
  </tr>

Здесь я не стал убирать ничего. Нам нужно «научить робота» выделять вот это число — 224.

Давайте поищем на странице слово «EVDO» (в текстовом редакторе, в котором вы просматриваете эту страничку). Нашли только один раз, хорошо. Курим маны. Пользуемся командой grep. Команда grep EVDO выдает нам только строчку, в которой найдено слово EVDO, а команда grep -A 3 EVDO выдает нам эту строчку и еще три следующих за ней строки. Как раз в третьей строке находится наше число! Итак, код: cat «take4.html» | grep -A 3 EVDO Здесь мы при помощи команды cat выводим содержимое файла take4.html и при помощи вертикальной черты передаем его дальше по конвейеру команде grep. Получаем:

      <i>      Передача даних EVDO</i>
    </td>
    <td class="ar4">
      <i> 224</i>

Теперь «откусим» только последнюю строку при помощи команды tail:

cat "take4.html" | grep -A 3 EVDO | tail -n 1

Получаем:

      <i>�224</i>

Вы заметили некий гаденький символ перед цифрами? Так в консоль выводится символ неразрывного пробела, который непонятно зачем всунули разработчики этой странички. В старой версии скрипта я бы написал несколько команд, которые последовательно по конвейеру, удаляли бы из строки ненужные нам символы. Сначала бы заменили пробел(ы) на ничто (т. е. удалили их), затем «<i>», после «</i>», и, наконец, этот гаденький символ. Синтаксис команды sed (для замены строк) прост:

sed -e 's/что-менять/на-что-менять/g'

Ключ g говорит, что менять нужно глобально, а не только первый попавшийся случай. Так, команда:

sed -e 's/ //g; s/<i>//g; s/<\/i>//g'

последовательно заменит все пробелы на «ничто», затем «<i>» и «</i>». А, вот, с этим символом не всё так просто. Кодировка скрипта, конечно же, UTF-8, а кодировка странички — windows-1251. Поэтому, команда sed ничего не найдет. А, если же сохранить скрипт в кодировке 1251, то мы не сможем выводить этим скриптом русские буквы. А, если, сохранить в 1251, вставить символ в скрипт, а затем открыть как UTF-8, то текстовый редактор откажется работать с этим скриптом. Да-а…

Отмечу, что ту же задачу можно было бы решить по-другому:

cut -d ">" -f 2 | cut -d "<" -f 1

Здесь сначала мы разбиваем нашу строку на части. Разделитель частей Всё хорошо, но число с этим символом в начале нельзя подставлять в математические выражения — получим ошибку! Покурив маны, я нашел простое и элегантное решение:

grep -o '[0-9]*'

В переводе на русский язык это значит: выдать из исходной строки только символы из интервала 0-9 (цифры), а звездочка обозначает, что этих цифр может быть произвольное количество.

Вот и всё! Получился скрипт в одну строку, который выполняет такую сложную задачу! Вот в этом и заключается сила командной строки Linux, профессионалы могут сделать в консоли всё что угодно. А новички не верят, говорят, устарело. Неправда…— символ «>», берем вторую часть. Затем полученную строку снова разбиваем на части, но уже символом «<» и берем первую часть. То, что задачу можно решить как минимум двумя разными способами — тоже типично для Linux.

Обрабатываем полученное значение