Обращаю Ваше внимание, что в связи с нестабильной работой сервера почты Китая, а также с введением дополнительной проверки капчи скрипт chinapost.php стал нерабочим. Помимо этого в связи с хакерской атакой на сайт почты России 21 августа 2012 года изменился алгоритм работы скрипта rupost.php. Теперь при каждом запросе на отслеживание посылки, сайт Русской почты подсовывает Java-скрипт, содержащий уникальный номер. Если номер обратно не отправить серверу, то информацию об отправлении нам не получить. Скрипт rupost.php исправлен, архив source.rar актуализирован.
28 октября 2012 года
Примерно 14 ноября 2012 года на сайте почты России появилось нововведение, теперь чтобы отследить посылку необходимо ввести проверочный код с картинки (капчу). Как временное решение предлагаю использовать сервис antigate.com для заполнения проверочного кода. Измененный скрипт в открытый доступ не выкладываю, чтобы его получить необходимо в индивидуальном порядке обратиться ко мне на почту.
18 ноября 2012 года
PHP скрипт для отслеживания посылок
В последнее время я очень сильно увлекся покупками за рубежом – теперь просто не представляю, как раньше обходился без этого. Каждый месяц раз по пять-десять прихожу на почту и забираю посылки, пришедшие мне либо из Китая, либо из Америки. Заказываю в основном товары по различным акциям в интернет магазинах Китая и радиодетали, при этом понимая в какую лотерею, приходится играть с крупной государственной структурой, именуемой Почта России.
Вот и сейчас в ожидании 10 штук HT1632C, решил автоматизировать процесс отслеживания посылок. Для успешной реализации идеи нам потребуется виртуальный хостинг со следующими минимальными характеристиками: поддержка PHP (наличие модуля CURL), MySQL (необязательно), Cron. К счастью, у меня оказалась возможность «присоседится» к серверу, оплачиваемому моим знакомым. Для отправки СМС через интернет можно воспользоваться одним из следующих сервисов: 93W.RU, SMS-центр, "Простор", iqsms.ru, Yakoon, COMTUBE и другие. Средняя цена за отправку сообщений составляет 50 копеек, SMS можно отправлять с помощью GET или POST запросов, что является крайне удобным для нас.
Несмотря на обилие в интернете сервисов, предлагающих подобную услугу (специально не буду их рекламировать), у них у всех есть один большой недостаток – тарифы на SMS информирование. Кредиты, покупаемые у системы для отправки сообщений, очень быстро расходуются (с трудом хватает 50 рублей для отслеживания двух посылок). К тому же, имея собственную систему, можно определять период опроса почтовых сервисов, корректировать текст SMS и многое другое.
Сейчас расскажу о концепции проекта. За отслеживание посылки в каждой стране будет отвечать отдельный файл. Это связано с «непостоянством» почтовых сервисов – они то и дело норовят поменять протокол, а как следствие приходится изменять исходный код. На данный момент разработаны модули для отслеживания с помощью почтовых служб Китая (файл chinapost.php), Гонконга (файл hkpost.php), США (файл usps.php) и России (файл rupost.php). Стандартные функции, используемые в работе, также вынесены отдельным модулем.
Рассмотрим состав основного модуля (файл function.php). Самая значимая функция, которая отправляет POST-запрос на получение страницы, называется GetPostRequest. В качестве аргументов ей передается 2 параметра: $url – адрес страницы, $post_data – данные POST-запроса (если параметров несколько, то они разделяются знаком «&»). Функция использует библиотеку CURL и возвращает загруженную страницу.
function GetPostRequest($url,$post_data) { $ch = curl_init(); //инициализируем библиотеку CURL curl_setopt($ch, CURLOPT_URL, $url); //передаем URL curl_setopt($ch, CURLOPT_HEADER, 0); //не передаем заголовки curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //получаем результат в переменную curl_setopt($ch, CURLOPT_POST, 1); //указываем, что запрос POST curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); //передаем параметры запроса $result = curl_exec($ch); //выполняем CURL запрос curl_close($ch); //закрываем CURL return $result; //возвращаем результат }
Если библиотека CURL по каким-то причинам недоступна, то функцию можно немного переделать. В таком варианте она спокойно «живет» на моем роутере D-Link DIR-320.
function GetPostRequest ($url, $data) { $parse = parse_url($url); //получаем ассоциативный массив $url_host=$parse['host']; //извлекаем имя хоста $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Не работает\n"); //создаем сокет socket_connect($sock, $url_host, 80); //соединяемся с сервером //формируем запрос $request = "POST ".$parse['path']." HTTP/1.1\r\n"; $request .= "Host: ".$url_host."\r\n"; $request .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\n"; $request .= "Content-type: application/x-www-form-urlencoded\r\n"; $request .= "Content-Length: ".strlen($data)."\r\n"; $request .= "Connection: Close\r\n\r\n"; $request .= $data; //запрос сформирован socket_write($sock, $request); //передаем запрос серверу $buff= ""; do { $recv = ""; $recv = socket_read($sock, '1400'); //считываем данные if($recv != "") //если данные не пустые { $buff .= $recv; //дописываем их к буферу } } while($recv != ""); //повторяем так до последнего байта socket_close($sock); //закрываем сокет return $buff; //возвращаем результат }
После того, как страница успешно загружена, необходимо извлечь из неё нужные нам данные. Для этой операции разработана функция GetParamHTML, принимающая в качестве аргумента 4 параметра: $data – данные для парсинга, $stag – открывающий тэг, $endtag – закрывающий тэг, $offs – смещение от начала данных. Результатом выполнения функции будет фрагмент данных, заключенный между тэгами $stag и $endtag, если тэги не найдены, то будет возвращен код ошибки.
function GetParamHTML($data,$stag,$endtag,$offs) { global $tmpend; //используем глобальную переменную $tmppos=strpos($data,$stag,$offs); //находим открывающий тэг if ($tmppos!==false) //проверяем найден ли тэг { $tmpend=strpos($data,$endtag,$tmppos)+strlen($endtag); //находим закрывающий тэг $result=substr($data,$tmppos,$tmpend-$tmppos); //вырезаем фрагмент return $result; //возвращаем результат } else { return -1; //ошибка } }
Там где не справляется функция GetParamHTML, работает функция GetParamHTMLv2. Подробно останавливаться на последней не будем. Она является менее чувствительной к закрывающемуся тэгу и применяется для парсинга сайта американской почты.
Не знаю, почему так сложилось, но не люблю я кодировку UTF-8. Как оказалось некоторые провайдеры, предоставляющие услуги SMS рассылок, работают только с русскоязычной кодировкой WIN CP-1251, а сайт Российской почты выдает данные в кодировке UTF-8. Для согласования кодировок в модуль function.php добавлена функция UTFtoCP1251 ($str,$type). Где $str – строка для преобразования, $type –конечная кодировка («w» – WIN CP-1251, «u» – UTF-8).
Еще раз повторюсь, что для каждой страны предполагается наличие своего модуля, содержащего только одну функцию. Так модуль usps.php содержит функцию GetUSATrackData, которая в качестве аргумента требует только трек американской почты. После вызова функция вернет двумерный массив (в случае успешного выполнения) либо -1 (если номер не зарегистрирован в почтовой системе).
Простейший пример, позволяющий распечатать информацию об отслеживании с американского сайта USPS, приведен в следующем куске кода.
<? include_once "function.php"; include_once "usps.php"; $datas=GetUSATrackData('CJ462051684US'); if ($datas==-1) { echo 'Данные об отправлении устарели либо недоступны'; exit; } for ($x=0;$x<count($datas);$x++) { for ($y=0;$y<count($datas[$x]);$y++) { echo $datas[$x][$y].';'; } echo '<br>'; } ?>
Аналогично работает функция GetRussiaTrackData из модуля rupost.php. Для отслеживания посылок в Гонконге разработана функция GetHonKongTrackData (модуль hkpost.php), для Китая – GetChinaTrackData (модуль chinapost.php). Обращаю внимание, что последние две функции возвращают одномерный массив, содержащий лишь текущее состояние посылки.
Чтобы описанный код обрел значимость и полезность необходим еще один модуль, назовем его условно main_task.php. Для полноценной работы алгоритма нам понадобится 2 таблицы MySQL:
1. Таблица rupost. Сюда мы будем заносить информацию с почтовых серверов.
Поле | Тип | Сравнение | Null | Дополнительно | Особые параметры |
Id | bigint(20) | Нет | auto_increment | Ключевое поле | |
track | varchar(14) | cp1251_general_ci | Нет | ||
operation | varchar(255) | cp1251_general_ci | Нет | ||
dateop | datetime | Нет | |||
postalcode | varchar(7) | cp1251_general_ci | Нет | ||
nameops | varchar(255) | cp1251_general_ci | Нет | ||
atrib | varchar(255) | cp1251_general_ci | Нет | ||
weight | varchar(10) | cp1251_general_ci | Нет | ||
money_val | varchar(10) | cp1251_general_ci | Нет | ||
money_pay | varchar(10) | cp1251_general_ci | Нет | ||
postal_adr | varchar(7) | cp1251_general_ci | Нет | ||
adress | varchar(255) | cp1251_general_ci | Нет | ||
posttype | varchar(1) | cp1251_general_ci | Нет |
2. Таблица task, содержащая перечень номеров для отслеживания.
Поле | Тип | Сравнение | Null | Дополнительно | Особые параметры |
Id | bigint(20) | Нет | auto_increment | Ключевое поле | |
tracknumber | varchar(14) | cp1251_general_ci | Нет |
Разберемся теперь, как работает алгоритм. Из таблицы task циклически считываются номера, запрос о состоянии которых посылается первым делом на сайт русской почты, а затем, в случае неудачи, на адреса международных почтовых служб. После каждого удачного запроса формируется строка, которая посредством MySQL сравнивается со значениями таблицы rupost. Если новые данные в таблице отсутствуют, то они дописываются в rupost, и формируется SMS сообщение об изменении статуса посылки. В случае если при очередном запросе новых данных (об одном отправлении) оказалось больше чем строчка, то в SMS сообщении придет лишь последняя.
Файл main_task.php требует предварительной настройки. Необходимо инициализировать значения следующих переменных:
$dblogin="user"; //Имя пользователя для доступа к БД MYSQL $dbpassword="password"; //Пароль для доступа к БД MySQL $dbsqlname="basename"; //Имя базы данных MYSQL $phone="+79020000004"; //Телефон на который будут отсылаться SMS
Оператором для отправки SMS через интернет я выбрал службу SMSC.RU, поэтому требуется занести данные своего аккаунта в файл smsc_api.php.
Итак, файлы настроены и залиты на хостинг. Вы можете спросить, что же делать дальше? Все просто – добавляем задание в Cron и радуемся жизни.
В заключении хочется сказать, что весь материал предназначен лишь для ознакомления. Использование наработок в коммерческих целях строго запрещено. Перепечатка материалов возможна только с моего разрешения и с соблюдением ссылок на первоисточник. Желающих поддержать не только словом, но и делом, а также поблагодарить – прошу ко мне на почту.
Файлы из статьи можно скачать здесь.
Удачи в Ваших начинаниях!!!