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

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
wiki:скрипт_для_проверки_баланса_в_peoplenet [2011/09/27 21:50]
— (текущий)
Строка 1: Строка 1:
-====== Скрипт для проверки баланса в ====== 
- 
-{{ :​wiki:​peoplenet.png|PeopleNet}} В данной статье рассматривается процесс создания скрипта для проверки баланса украинского мобильного оператора PeopleNet, который обычно используется для мобильного доступа к 3G интернету. Целью статьи является популяризация написания скриптов для облегчения ежедневных задач. 
- 
-Всё началось с вопроса моего друга. «Нельзя ли что-нибудь сделать с теперешним подсчетом трафика в PeopleNet? Ведь что-то же считает!» Я сразу же стал теоретизировать,​ что таки да, можно… И через пару ночей я засел за работу и родился скрипт,​ которым я хочу поделиться с вами. 
-Нужно ввести читателя в курс дел. 
- 
-В популярном пакете «777» от PeopleNet предоставляется ежедневно трафик размером 232 МБ (как бы 7 ГБ в месяц и как бы за 77 грн). Узнать остаток доступного трафика на текущие сутки можно, отправив с 3G модема SMS на служебный номер и прочитав ответ (при помощи «фирменной» программы для Windows. Отправлять SMS в Linux, с 3G модемов как-то еще не очень получается. 
-Кроме того, существует страничка биллинга,​ называемая Системой самообслуживания клиентов. Раньше я уже писал скрипт для подобных целей. Но раньше было проще. Можно было получить информацию о потраченном трафике за каждую сессию за каждый день в течение последнего месяца. Теперь же на странице красовалось одно число — количество потраченных МБ с начала месяца. С тех пор сёрфинг в сети велся практически вслепую… 
- 
-Я почти полностью переписал скрипт,​ избавился от множества промежуточных шагов, временных переменных и файлов,​ и это пошло скрипту только на пользу. Его основу составляет одна «волшебная» строчка кода, которая получает со страницы самообслуживания число потраченных с начала месяца мегабайт:​ 
- 
-<code bash>​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]*'</​code>​ 
-или в с переносом строки 
-<code bash>​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]*'</​code>​ 
- 
-Здесь используется **curl** — удобная программа,​ которую можно в шутку назвать «веб-браузер для робота». Ее можно вызывать из своих скриптов для отсылки запросов,​ форм, получения и отправки страниц и файлов. Для того, чтобы получить информацию по своему номеру,​ вы должны изменить **380921234567** на свой номер, а **11223344** — на свой пароль для входа на страницу самообслуживания. В процессе работы будет загружена страничка размером 11,5 кБ и из нее будет выделено единственное число, которое вы и получите «на выходе». О том, что делать дальше с этим числом,​ мы поговорим немного позже. 
- 
-===== Как работает этот код ===== 
- 
-Обо всех опциях команды curl вы сможете узнать,​ если выполните в терминале команду 
-<​code>​curl --help</​code>​ 
-Такой подход к получению справки типичен для большинства команд в Linux. 
-Здесь мы используем такие ключи: 
-  * -s — «молчаливый» режим. Curl не будет печатать в терминале не нужную нам информацию о размере и скорости закачки указанной страницы;​ 
-  * -d и следующая строка в кавычках — данные,​ отсылаемые на сервер по методу POST; 
-  * --url и длинная строка,​ заканчивающаяся перед вертикальной чертой — адрес страницы,​ которую нужно получить. Сам ключ «--url» можно было бы и не писать,​ оставив только строку. Вертикальная черта передает страничку,​ загруженную командой curl, дальше,​ следующей команде,​ по конвейеру. 
- 
-Откуда взялись параметры для ключей **-d** и **--url**? 
-Проследим работу системы самообслуживания. Зайдем при помощи обычного браузера на страницу http://​my.people.net.ua/​. Нас просят ввести номер телефона и пароль,​ затем нажать кнопку подтверждения. Далее нужно перейти по ссылке //​«Ежемесячный счет»//​. На следующей странице выбрать нужный месяц из выпадающего списка (текущий месяц находится вверху и поэтому выбирать ничего не нужно) и нажать кнопку подтверждения. На следующей странице нужно пробежаться глазами по таблице и найти в строчке //​«Передача даних EVDO»// нужное нам число. Теперь научим робота делать то же самое. 
-Для исследования страниц нам пригодится ключ **-o** команды curl. После этого ключа указываем название файла и страничка,​ указанная в ключе **--url** будет загружена в этот файл. 
- 
-Итак, первый шаг: 
- 
-<code bash>​curl --url "​http://​my.people.net.ua/"​ -o "​take1.html"</​code>​ 
-Открываем полученный файл **take1.html** в текстовом редакторе (нужно хотя бы немного разбираться в html-разметке). Мы видим html-форму:​ 
-<file 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>​ 
-</​file>​ 
-Я удалил всё, не относящееся к делу, чтобы можно было сосредоточиться на нашем задании. Итак, данные формы отправляются методом POST, значит,​ воспользуемся ключом -d команды curl. Вот, если бы метод был GET, то можно было бы не городить огород,​ а дописать передаваемые данные прямо в строку адреса (примерно так: [[http://​наш.длинный/​адрес?​параметр1=значение1&​параметр2=значение2]]). 
- 
-Итак, из анализа формы становится понятно,​ что при нажатии кнопки подтверждения данные формы отсылаются по адресу http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO/​ и эти данные — **X_Username=номер телефона** и **X_Password=пароль**. 
- 
-Второй шаг наших раскопок:​ 
-<code bash>​curl -d "​X_Username=380921234567&​X_Password=11223344"​ --url "​http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO/"​ -o "​take2.html"</​code>​ 
- 
-Просмотрев загруженную страничку,​ мы видим, что да, нас успешно пустили в систему самообслуживания. Теперь нас интересует ссылка:​ 
-<​file><​a href="​http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO?​sid=bills">​Ежемесячный счет</​a></​file>​ 
-Я снова убрал всё лишнее. Попробуем:​ 
-<code bash>​curl --url "​http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO?​sid=bills"​ -o "​take3.html"</​code>​ 
-Получаем страничку с ошибкой. Хм, попробуем так: 
-<code bash>​curl --url "​http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO/?​sid=bills"​ -o "​take3.html"</​code>​ 
-Теперь получаем первоначальную страничку для входа в систему самообслуживания. Нас забыли и снова предлагают ввести номер и пароль! Попробуем не городить огород,​ а просто объединим две команды,​ два адреса в один: 
-curl -d "​X_Username=380921234567&​X_Password=11223344"​ --url "​http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO/?​sid=bills"​ -o "​take3a.html"​ 
-Так! Мы продвинулись дальше! Просматривая страницу,​ находим в ней форму для выбора месяца:​ 
-<file 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>​ 
-</​file>​ 
- 
-Я снова убрал всё лишнее из html-разметки. В зависимости от вашего «стажа» в PeopleNet длина списка у вас будет другая. Итак, адрес для отсылки формы ясен; метод, кстати — GET, значит,​ пишем параметры прямо в строку адреса. Имеется скрытая (hidden) переменная с именем sid и значением bills. Вторая переменная с именем rp и нужным нам значением 117. Формируем адрес: 
-[[http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO/?​sid=bills&​rp=117]] 
- 
-Пробуем снова совместить команды:​ 
-<code bash>​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"</​code>​ 
-Да, мы продвинулись еще дальше. Правда,​ такого же восторга уже нет. Остается работа. И она заключается в следующем. 
- 
-Во-первых,​ каждый месяц число в параметре rp будет меняться. Во-вторых,​ нам нужно проанализировать код страницы. Подберем формулу для расчета числа: 
-<code bash>rp = ( год - 2 ) * 12 + месяц</​code>​ 
-Номер года (две последние цифры) и номер месяца (две цифры) мы можем получить соответствующими командами:​ 
-<code bash>​date +%y</​code>​ 
-<code bash>​date +%m</​code>​ 
-Если окружить команду такой оберткой — $(команда),​ то тогда результат работы этой команды будет представлен в виде строки и его можно будет использовать для дальнейших вычислений в более сложных командах. Для математических расчетов используем команду expr. 
-<code bash>​expr ( $(date +%y) - 2 ) * 12 + $(date +%m)</​code>​ 
-Получаем ошибку,​ говорящую о некорректном синтаксисе,​ курим маны и «экранируем» скобки,​ входящие в нашу формулу,​ а также звездочку (знак умножения),​ поставив перед ними бэкслэш (\): 
-<code bash>​expr \( $(date +%y) - 2 \) \* 12 + $(date +%m)</​code>​ 
-Получаем 117. Что нам и требовалось! 
-Теперь окружаем эту команду при помощи $(...) и подставляем ее вместо числа 117 в нашу супер-команду curl: 
-<code bash>​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))</​code>​ 
- 
-Заметьте,​ что кавычки закрываются после «rp=» и сразу же мы пишем обернутую команду,​ таким образом,​ результат команды (число 117) дописывается к строке. 
- 
-Теперь пришло время «во-вторых» — анализ кода страницы. Вы помните,​ как выглядит табличка,​ когда вы заходили через браузер?​ Ищем строчку с аббревиатурой EVDO и находим такой участок html-разметки:​ 
-<file html> 
-  <tr> 
-    <td> 
-      <​i>​      Передача даних EVDO</​i>​ 
-    </td> 
-    <td class="​ar4">​ 
-      <​i>​ 224</​i>​ 
-    </td> 
-    <td class="​ar4">​ 
-      <​i>​0.00</​i>​ 
-    </td> 
-  </tr> 
-</​file>​ 
-Здесь я не стал убирать ничего. Нам нужно «научить робота» выделять вот это число — **224**. 
- 
-Давайте поищем на странице слово «EVDO» (в текстовом редакторе,​ в котором вы просматриваете эту страничку). Нашли только один раз, хорошо. Курим маны. Пользуемся командой grep. Команда grep EVDO выдает нам только строчку,​ в которой найдено слово EVDO, а команда grep -A 3 EVDO выдает нам эту строчку и еще три следующих за ней строки. Как раз в третьей строке находится наше число! Итак, код: 
-cat "​take4.html"​ | grep -A 3 EVDO 
-Здесь мы при помощи команды cat выводим содержимое файла take4.html и при помощи вертикальной черты передаем его дальше по конвейеру команде grep. Получаем:​ 
-<file html> 
-      <​i>​      Передача даних EVDO</​i>​ 
-    </td> 
-    <td class="​ar4">​ 
-      <​i>​ 224</​i>​ 
-</​file>​ 
-Теперь «откусим» только последнюю строку при помощи команды tail: 
-<code bash>cat "​take4.html"​ | grep -A 3 EVDO | tail -n 1</​code>​ 
-Получаем:​ 
-<file html> ​     <​i>​�224</​i></​file>​ 
- 
-Вы заметили некий гаденький символ перед цифрами?​ Так в консоль выводится символ неразрывного пробела,​ который непонятно зачем всунули разработчики этой странички. В старой версии скрипта я бы написал несколько команд,​ которые последовательно по конвейеру,​ удаляли бы из строки ненужные нам символы. Сначала бы заменили пробел(ы) на ничто (т. е. удалили их), затем «<​i>​»,​ после «</​i>​»,​ и, наконец,​ этот гаденький символ. 
-Синтаксис команды sed (для замены строк) прост: 
-<code bash>sed -e '​s/​что-менять/​на-что-менять/​g'</​code>​ 
-Ключ g говорит,​ что менять нужно глобально,​ а не только первый попавшийся случай. Так, команда:​ 
-<code bash>sed -e 's/ //g; s/<​i>//​g;​ s/<​\/​i>//​g'</​code>​ 
- 
-последовательно заменит все пробелы на «ничто»,​ затем «<​i>​» и «</​i>​». А, вот, с этим символом не всё так просто. Кодировка скрипта,​ конечно же, UTF-8, а кодировка странички — windows-1251. Поэтому,​ команда **sed** ничего не найдет. А, если же сохранить скрипт в кодировке 1251, то мы не сможем выводить этим скриптом русские буквы. А, если, сохранить в 1251, вставить символ в скрипт,​ а затем открыть как UTF-8, то текстовый редактор откажется работать с этим скриптом. Да-а… 
- 
-Отмечу,​ что ту же задачу можно было бы решить по-другому:​ 
-<code bash>cut -d ">"​ -f 2 | cut -d "<"​ -f 1</​code>​ 
-Здесь сначала мы разбиваем нашу строку на части. Разделитель частей Всё хорошо,​ но число с этим символом в начале нельзя подставлять в математические выражения — получим ошибку! Покурив маны, я нашел простое и элегантное решение:​ 
-<code bash>​grep -o '​[0-9]*'</​code>​ 
-В переводе на русский язык это значит:​ выдать из исходной строки только символы из интервала 0-9 (цифры),​ а звездочка обозначает,​ что этих цифр может быть произвольное количество. 
- 
-Вот и всё! Получился скрипт в одну строку,​ который выполняет такую сложную задачу! Вот в этом и заключается сила командной строки Linux, профессионалы могут сделать в консоли всё что угодно. А новички не верят, говорят,​ устарело. Неправда…— символ «>», берем вторую часть. Затем полученную строку снова разбиваем на части, но уже символом «<» и берем первую часть. 
-То, что задачу можно решить как минимум двумя разными способами — тоже типично для Linux. 
- 
-===== Обрабатываем полученное значение ===== 
-