Google, к примеру, индексирует и выставляет оценки веб-сайтам абсолютно автономно посредством мощных «спайдеров» или ботов. Существуют также сервисы проверки ссылок, валидаторы кода HTML, автоматизированные сервисы оптимизации и шпионы. Да-да, именно шпионы. Именно таким приложением мы и займёмся сегодня.
На самом деле, мы не уверены, привычный ли это термин в обществе и использовался он когда-нибудь ранее, но мы думаем, что этот термин идеально подходит как описание приложения. Основная цель – создать ПО, которое отслеживало бы цены на продукцию ваших конкурентов, чтобы вы всегда могли выиграть в ценовой политике.
Возможно, у вас возникнет мысли типа: «Ой, это бесполезно для меня. Я же фрилансер, мне не приходится иметь дела с разницей в ценах на услуги». Не беспокойтесь, вы правы, в какой-то степени. Но у вас могут быть такие клиенты, которым крайне важно быть впереди, так что вы тоже сможете быть впереди, и предложить им дополнительный сервис, так сказать, аналитики (не бойтесь даже завышать расценки). Всё это говорит о том, что и вам было бы неплохо уметь проводить сравнения.
Итак, приступаем!
Требования
PHP сервер на Linux – нам нужно будет использовать crontab, так что лучше выбрать хороший сервер.
MySQL – нам нужно будет где-то хранить данные, поэтому нужна база данных.
Основа получения информации
Мы начнем с попыток создания функции получения информации, а именно с самого получения информации. Давайте предположим, что вы торгуете туфлями, а компания Zappos – ваш конкурент (хотя об этом только мечтать!). Первый продукт, который вам нужно отследить – прекрасная пара кроссовок Nike Free Run+. Сейчас мы воспользуемся функцией fopen для открытия страницы, fgets для чтения каждой строки текста на странице и feof для определения окончания считывания информации. Сейчас вам надо активировать функцию fopen на сервере (проверьте этот параметр посредством phpinfo). Наш первый кусочек кода будет таким:
<?php
if(!$fp = fopen("http://www.zappos.com/nike-free-run-black-victory-green-anthracite-white?zlfid=111" ,"r" )) {
return false;
} //our fopen is right, so let's go
$content = "";
while(!feof($fp)) { //while it is not the last line, we will add the current line to our $content
$content .= fgets($fp, 1024);
}
fclose($fp); //we are done here, don't need the main source anymore
?>
На данном этапе, если вы выведите $content, то увидите, что у нас есть все содержимое страницы, но без CSS и JS, так как на сайте Zappos везде проставлены сторонние ссылки на файлы.
Теперь у нас есть содержимое, и нам нужно определить цену продукта.
Как вы узнаете разницу между ценой и другой информацией на странице? Итак, это крайне просто, так как у каждой цены перед цифрами стоит знак «$», так что следующее, что мы сделаем – получим данные и запустим постоянное выражение для отображения цен со знаком $ со всей страницы.
Но наше постоянное выражение будет соответствовать каждой цене на странице. Так как Zappos явно удобен для шпионов, «официальные» цены у них стоят вначале. Всегда. Остальные просто используются посредством javascript, поэтому мы можем игнорировать их.
Наш Regex и выдача цен будет выглядеть примерно так:
<?php
//our fopen, fgets here
//our magic regex here
preg_match_all("/([$][0-9]*[,]*[.][0-9]{2})/", $content, $prices, PREG_SET_ORDER);
echo $prices[0][0]."<br />";
?>
Итак, теперь у нас есть цена. Не забудьте о других ценах. Они понадобятся нам, если на сайте Zappos произойдут изменения.
Сохраняем данные в MySQL
Давайте подготовим базу данных для хранения данных. Нужно создать таблицу zappos. Внутри неё нам нужны 4 колонки:
ID – ключевое поле в таблице
Date – дата, когда данные были получены. Это следует записывать, чтобы вы затем смогли делать отчеты.
Value – значения, которые были извлечены
Other_values – значения, которые не являются теми, которые вам были нужны, но очень важно их сохранить на случай, если владелец веб-сайта внесет изменения в код, чтобы у вас оставался откат.
Посредством phpmyadmin создаём БД под названием spy, и внутри неё находится таблица zappos:
CREATE TABLE IF NOT EXISTS `zappos` (
`ID` int(5) NOT NULL AUTO_INCREMENT,
`Date` date NOT NULL,
`Value` float NOT NULL,
`Other_Values` char(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3;
Как только вы создали таблицу, мы начнем вносить данные. Итак, нам понадобится создать соединение с БД в нашем PHP, а также подготовить прайс-листы к сохранению.
Так как наши данные передаются не идеально, нам нужно подготовить их. Итак, у нас будут лишь цифры и точки.
Для соединения с БД мы будем использовать mysql_connect, а затем используем mysql_select_db для выбора базы данных spy, а дальше последует запрос посредством mysql_query для сохранения или получения данных.
<?php
//preparing to save all other prices that isn't our "official" price
$otherValues = "";
foreach ($prices as $price) {
$otherValues .= str_replace( array("$", ",", " "), '', $price[0]); //we need to save it as "float" value, without string stuff like spaces, commas and anything else you have just remove here
$otherValues .= ","; //so we can separate each value via explode when we need
}
//if someday Zappos changes his order (or you change the site you want to spy), just change here
$mainPrice = str_replace( array("$", ",", " "), '', $prices[0][0]);
//lets save our date in format YYYY-MM-DD
$date = date('Y\-m\-d');
$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = '';
$dbname = "spy";
$dbtable = "zappos";
$conn = mysql_connect($dbhost, $dbuser, $dbpass)
or die ('Error connecting to mysql');
echo "<br />Connected to MySQL<br />";
$selected = mysql_select_db($dbname)
or die( mysql_error() );
echo "Connected to Database<br />";
//save data
$insert = mysql_query("
INSERT INTO `$dbname`.`$dbtable` (
`ID` ,
`Date` ,
`Value` ,
`Other_values`
)
VALUES (
NULL , '$date', '$mainPrice', '$otherValues'
);
");
//get data
$results = mysql_query("SELECT * FROM $dbtable");
mysql_close($conn);
//all data comes as MYSQL resources, so we need to prepare it to be shown
while($row = mysql_fetch_array($results, MYSQL_ASSOC)) {
echo "ID :{$row['ID']} " .
"Date : {$row['Date']} " .
"Value : {$row['Value']}";
echo "<br />";
}
?>
Улучшаем шпиона посредством crontab
Итак, с помощью crontab мы можем запланировать некоторые задачи в системе Linux, чтобы они запускались в автономном режиме. Это полезно для вещей, относящихся к работе, связанной с БД, оптимизацией веб-сайта и многими другими вещами, которые не так и охота делать вручную.
Так как нашему шпиону нужна свежая информация, мы создадим задачу, которая будет запускаться каждый день в 1:00. На сайте net.tuts+ лежит очень доходчивая обучающая статья, посвященная планировке задач посредством cron, так что, если вы не знакомы с этим, то обязательно просмотрите статью.
Вкратце, у нас есть строки с командами, которыми мы можем воспользоваться:
#here we load php and get the physical address of the file
#0 2 * * * says that it should run in minute zero, hour two, any day of month, any month and any day of week
0 2 * * * /usr/bin/php /www/virtual/username/cron.php > /dev/null 2>&1
#my favorite, with wget the page is processed as it were loaded in a common browser
0 2 * * * wget http://whereismycronjob/cron.php
Разработаем немного диаграмм

Если вы планируете использовать эти данные, то простая запись в базе данных не сильно вам поможет. Потому нам нужно как-то эту информацию «вывести на экран», так сказать.
Почти вся работа здесь будет выполняться идеальным jQuery-плагином gvChart. Он получает все данные из таблицы, и создает отличные диаграммы. Нам нужно лишь вывести данные в виде таблицы, чтобы плагин смог воспользоваться ими. На этот раз наш код будет выглядеть следующим образом (для более подробной информации скачайте демо-файл):
<?php
$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = '';
$dbname = "spy";
$dbtable = "zappos";
$conn = mysql_connect($dbhost, $dbuser, $dbpass)
or die ('Error connecting to mysql');
$selected = mysql_select_db($dbname)
or die( mysql_error() );
//get data
$results = mysql_query("SELECT * FROM $dbtable ORDER BY `ID` DESC LIMIT 15");
mysql_close($conn);
$dates = array();
$values = array();
while($row = mysql_fetch_array($results, MYSQL_ASSOC)) {
$dates[] = "{$row['Date']}";
$values[] = "{$row['Value']}";
}
echo "<table id='real'>";
echo "<caption>Real Prices on Zappos.com</caption>";
echo "<thead>";
echo "<tr>";
echo "<th></th>";
foreach($dates as $date) {
$date = explode('-', $date);
echo "<th>" . $date[2] . "</th>";
}
echo "</tr>";
echo "</thead>";
echo "<tbody>";
echo "<tr>";
echo "<th>" . $date[0] . "-" . $date[1] . "</th>";
foreach($values as $value) {
echo "<td>" . $value . "</td>";
}
echo "</tr>";
echo "</tbody>";
?>
Теперь вы полностью довольны?
Конечно же, здесь можно много чего «подправить» и «подкрасить». Вы можете, например, сделать «лист ожидания» из url-адресов, которые следует проверить.
Что ещё по вашему мнению здесь можно добавить или исправить? Отписываемся в комментариях к статье ...
Внимание! У вас нет прав для просмотра скрытого текста.