Допилить php-скрипт для записи сграбленных цен в базу MySQL

Тема в разделе "PHP", создана пользователем sunny8u, 11 фев 2013.

  1. sunny8u

    sunny8u

    Регистрация:
    21 окт 2012
    Сообщения:
    66
    Симпатии:
    62
    Вот в этой теме начинала обсуждение о поиске модуля для парсинга цен по заранее заданным в поле 'location' ссылкам и их последующей записи в поле 'cost'.

    В итоге, получился приведённый ниже php-скрипт. Но где-т я накосячила=((
    А из-за почти полного незнания php не могу понять, что неправильно=((

    Логика работы скрипта следующая:

    1. Подключиться к MySQL-базе.
    2. Получить значения переменной 'location' из таблицы 'product' (это ссылки, с которых нужно парсить цену).
    3. Задать 'location' как ключ .
    4. Задать регулярное выражение для парсинга цены.
    5. Результат парсинга цены записать в поле 'cost' таблицы 'product' в базе MySQL.
    6. Отключиться от MySQL.

    Этот скрипт будет вызываться из админки по нажатию кнопки "Обновить цены".

    Код:
    <?php
     
    // Подключаемся к БД
     
    $host="localhost";
    $user="username";
    $password="password";
    $db="dbname";
    $connection = mysql_connect($host, $user, $password) or die("MySQL сервер недоступен!".mysql_error());
    mysql_select_db($db) or die("Нет соединения с БД".mysql_error());
     
    // Формируем и отправляем запрос на извлечение переменных таблицы 'product'. Результат запишется в $result
     
    $query = 'SELECT * FROM `product`';
    $result = mysql_query($query)
    or trigger_error(mysql_errno() . ' ' .
    mysql_error() . ' query: ' . $sql);
     
    // проверяем вернулась хотя бы 1 строка или нет
    if (mysql_num_rows($result) > 0) {
     
    // вытаскиваем одну за другой строки, помещаем в $row
    $ind = 0;
    while ($row = mysql_fetch_assoc($result)) {
     
    // строка вернулась в виде ассоциативного массива
    echo "model = {$row['location']} <br>";
    $dataArr[$row['location']] = ''; // location как ключ в паре ключ/значение.
    }
    } else {
    echo 'Ошибка вывода значений';
    }
     
    mysql_close($connection);
     
    $regex = '|<span class="" id="sku-price">(.*?)</span>|si'; // Задаём регулярное выражение для парсинга цены
     
    $success = True;
     
    foreach( $dataArr as $key => $value )
    {
    $ch = curl_init (); // инициализация
    curl_setopt ($ch , CURLOPT_URL , $dataArr[$key]); // адрес страницы для скачивания
    curl_setopt ($ch , CURLOPT_USERAGENT , "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.7.12) Gecko/20050919 Firefox/1.0.7"); // каким браузером будем прикидываться
    curl_setopt ($ch , CURLOPT_RETURNTRANSFER , 1 ); // нам нужно вывести загруженную страницу в переменную
    $content = curl_exec($ch); // скачиваем страницу
     
    if (False === $content)
    {
    // $success = False;
    // break;
    continue; // Не вышло в этот раз, ну и фиг с ним
    }
     
    // Задаём регулярное выражение для парсинга цены
    preg_match($regex, $content, $ok);
     
    //$dataArr[$key] = $ok[1];
    $resArr[$key] = $ok[1];
    }
     
    // Если ошибок не было, то массив содержит пары URL/Полученные данные. Их надо запихать обратно в базу
     
    if ($success)
    {
    $connection = mysql_connect($host, $user, $password) or die("MySQL сервер недоступен!".mysql_error());
    mysql_select_db($db) or die("Нет соединения с БД".mysql_error());
     
    // Параметризованный запрос для предотвращения SQL Injection
    $stmt = $pdo->prepare('UPDATE product SET cost = :cost WHERE location = :location');
     
    // $updTpl = 'UPDATE product SET cost = "%cost" WHERE location = %s';
    foreach( $resArr as $key => $value ){
    $stmt->execute(array(':cost' => $value, ':location' => $location));
    }
    mysql_close($connection);}
    else {
    echo 'Не удалось записать в базу';
    // Ошибка записи в базу MySQL
    }
    
    НО! где-то на этапе между парсингом цены и записью полученного значения в базу данных происходит ошибка и в итоге, поле 'cost' не изменяется.
    Причем, к базе MeSQL подключается совершенно однозначно, значения получает.
    Также в отдельном файле работает парсинг цены (на конкретной прописанной странице .html, а не на переменной).

    Привожу пример кода, с которым скрипт без проблем получает значение цены с использованием данного регулярного выражения:
    Код:
    <?php
     
    $ch = curl_init (); // инициализация
    curl_setopt ($ch , CURLOPT_URL , 'http://www.sait.com/blablabla.html'); // адрес страницы для скачивания
    curl_setopt ($ch , CURLOPT_USERAGENT , "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.7.12) Gecko/20050919 Firefox/1.0.7"); // каким браузером будем прикидываться
    curl_setopt ($ch , CURLOPT_RETURNTRANSFER , 1 ); // нам нужно вывести загруженную страницу в переменную
    $content = curl_exec($ch); // скачиваем страницу
     
    $regex = '|<span class="" id="sku-price".*?>(.*?)</span>|si'  ; // Задаём регулярное выражение для парсинга цены
     
      preg_match($regex, $content, $ok);
    		echo $ok[1];
     
    		?>
    Помогите, пожалуйста, разобраться!
     
  2. alexsofdev

    alexsofdev

    Регистрация:
    13 янв 2013
    Сообщения:
    239
    Симпатии:
    46
    Хехе, у меня есть такой же скрипт. И кстати говоря, regex не самое лучшее решение. Я юзал Zend_Dom_Query, поскольку это почти полный аналог языка css-селекторов. Соответственно вместо:

    Код:
    '|<span class="" id="sku-price".*?>(.*?)</span>|si'
    
    Можно писать простой запрос

    Код:
    query("span#sku-price")
    
    И честно говоря, мне крайне интересует интеграция этого чуда в карточку товара. Вы этим занимаетесь или тоже какое-то отдельное решение?
     
  3. sunny8u

    sunny8u

    Регистрация:
    21 окт 2012
    Сообщения:
    66
    Симпатии:
    62
    Спасибо за подсказку! Сейчас попробую изменить... У вас, я так понимаю, работает=)

    А насчет интеграции пока думаю, над этим. Но почему-то уверена, что всё получится. Как только разберусь с самим скриптом, буду думать дальше:smile:
    --- добавлено: 11 фев 2013 в 12:35 ---
    Не работает:frown:
    А можете своим скриптом поделиться? Может, проблема всё-таки в другом...
     
  4. alexsofdev

    alexsofdev

    Регистрация:
    13 янв 2013
    Сообщения:
    239
    Симпатии:
    46
    Конечно не работает, я же просто кусочек кода показал для демонстрации того что селекторы проще. Вот кусок кода, который отвечает за получение цены:

    Код:
    		$html = @file_get_contents($articlesCompetitor->url);
    		if( !$html )
    			throw new Exception("Отсутствует страница" );
    		
    		$zdQuery = new Zend_Dom_Query($html);		
    		$elements = $zdQuery->query($competitor->selector);
    		if( !count($elements) )
    			throw new Exception("Отсутствует цена" );
    		
    		$price = 0;
    		foreach( $elements as $element ) {
    			$price = $this->CleanupPrice( $element->nodeValue );
    			break; // интересует только первый элемент
    		}
    
    но это поможет только знающему. А лично вам, учитывая "А из-за почти полного незнания php не могу понять, что неправильно=((", это врядли пригодится :Smile:.

    Если никто из местных не согласится помочь, то жду в личке, обсудим мои корыстные условия.
     
    sunny8u нравится это.
  5. saxum2010

    saxum2010

    Регистрация:
    6 фев 2013
    Сообщения:
    111
    Симпатии:
    34
    Вроде слабое место в регулярке

    $regex = '|<span class="" id="sku-price".*?>(.*?)</span>|si'

    попробуйте заменить на

    $regex = '|id="sku-price"(.*?)>(.*?)</span>|si'
     
    sunny8u нравится это.
  6. sunny8u

    sunny8u

    Регистрация:
    21 окт 2012
    Сообщения:
    66
    Симпатии:
    62
    Спасибо, но не помогло:frown:
    Ладно, еще помучаюсь, и там посмотрим...