Пример парсера XML файлов в базу.

Обсуждение сервиса товарной рекламы Микс-Товары
Ответить
geosub
Сообщения: 5
Зарегистрирован: 02 окт 2006, 13:23

Пример парсера XML файлов в базу.

Сообщение geosub » 02 фев 2007, 17:58

Вот мой парсер, лог его работы:

22:17:51: Начало работы
22:19:22: Получил данный XML (22996) кб.
22:19:34: Обработал XML данные
22:23:29: Сохранил товары
22:23:29: Сохранил брэнды
22:23:29: Сохранил адверты
22:23:30: Сохранил категории
22:23:30: Завершено

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


xmlParse.inc.php

Код: Выделить всё

<?php
function xml2array($contents, $get_attributes=1) {
    if(!$contents) return array();

    if(!function_exists('xml_parser_create')) {
        //print "'xml_parser_create()' function not found!";
        return array();
    }
    //Get the XML parser of PHP - PHP must have this module for the parser to work
    $parser = xml_parser_create();
    xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 );
    xml_parser_set_option( $parser, XML_OPTION_SKIP_WHITE, 1 );
    xml_parse_into_struct( $parser, $contents, $xml_values );
    xml_parser_free( $parser );

    if(!$xml_values) return;//Hmm...

    //Initializations
    $xml_array = array();
    $parents = array();
    $opened_tags = array();
    $arr = array();

    $current = &$xml_array;

    //Go through the tags.
    foreach($xml_values as $data) {
        unset($attributes,$value);//Remove existing values, or there will be trouble
        extract($data);//We could use the array by itself, but this cooler.

        $result = '';
        if($get_attributes) {//The second argument of the function decides this.
            $result = array();
            if(isset($value)) $result['value'] = $value;

            //Set the attributes too.
            if(isset($attributes)) {
                foreach($attributes as $attr => $val) {
                    if($get_attributes == 1) $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
                    /**  :TODO: should we change the key name to '_attr'? Someone may use the tagname 'attr'. Same goes for 'value' too */
                }
            }
        } elseif(isset($value)) {
            $result = $value;
        }

        //See tag status and do the needed.
        if($type == "open") {//The starting of the tag '<tag>'
            $parent[$level-1] = &$current;

            if(!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag
                $current[$tag] = $result;
                $current = &$current[$tag];

            } else { //There was another element with the same tag name
                if(isset($current[$tag][0])) {
                    array_push($current[$tag], $result);
                } else {
                    $current[$tag] = array($current[$tag],$result);
                }
                $last = count($current[$tag]) - 1;
                $current = &$current[$tag][$last];
            }

        } elseif($type == "complete") { //Tags that ends in 1 line '<tag />'
            //See if the key is already taken.
            if(!isset($current[$tag])) { //New Key
                $current[$tag] = $result;

            } else { //If taken, put all things inside a list(array)
                if((is_array($current[$tag]) and $get_attributes == 0)//If it is already an array...
                        or (isset($current[$tag][0]) and is_array($current[$tag][0]) and $get_attributes == 1)) {
                    array_push($current[$tag],$result); // ...push the new element into that array.
                } else { //If it is not an array...
                    $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
                }
            }

        } elseif($type == 'close') { //End of tag '</tag>'
            $current = &$parent[$level-1];
        }
    }

    return($xml_array);
}

?>



parser.php

Код: Выделить всё

<?
set_time_limit(360);
ignore_user_abort(1);
include("xmlParse.inc.php");

function getXml()
{


   $handle = fopen ("http://mixmarket.biz/mixml.plx?id=xxxxxxxxx", "r");

   if (!$handle)
      return;

   while (!feof ($handle))
   {
      $buffer .= fgets($handle, 4096);
   }
   fclose ($handle);

return $buffer;
}



function updateCateg($data)
{

   $data = $data[mixml][categories][category];

   _m_q("truncate table categ");
   $so = sizeof($data);
   for ($a=0;$a<$so;$a++)
   {
      $cur = $data[$a];
      $catId = $cur[attr][id];
      $parentId = $cur[attr][parentId];
      $catName = utf8win1251($cur[value]);
      _m_q("запрос на вставку в базу");

   }
return $so;

}




$xml = getXml();

$data = xml2array($xml,1);

echo "Update Advert: ";flush();
$so = updateAdvert($data);
echo " ($so) [ OK ] <br>\n";flush();

// дальше поочереди запуск функция для обработки товаров, категорий итд...

?>


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

Не судите строго, первый парсер для работы с mix. думаю в будущем сделаю его еще быстрее и лучше.

Может тут сделать обзор и тестдрайв парсеров?
И в итоге выбрать самый быстрый и менее ресурсоемкий.
Последний раз редактировалось geosub 02 фев 2007, 19:13, всего редактировалось 1 раз.

dronfin
Сообщения: 1
Зарегистрирован: 21 дек 2006, 15:28

Сообщение dronfin » 30 сен 2010, 23:27

немного изменил файл parser.

для наглядности будет виден сразу вывод информации:


Код: Выделить всё

<? 
set_time_limit(360);
ignore_user_abort(1);
include("xmlParse.inc.php");

function getXml()
{
   $handle = fopen ("http://price.mixmarket.biz/mixml.plx?id=xxxxxxxxxx", "r");
   if (!$handle)
      return;
   while (!feof ($handle))
   {
      $buffer .= fgets($handle, 4096);
   }
   fclose ($handle);
return $buffer;
}

function updateCateg($data)
{
   $data = $data[mixml][offers][offer];
   $so = sizeof($data);
   for ($a=0; $a<$so; $a++)
      { $s++ ;
      $cur = $data[$a];
      $catId = $cur[attr][id];
     $name = $cur[name];
   }
return $so;
}


$xml = getXml();
$data = xml2array($xml, 0);
$so = updateCateg($data);


?>


Меняя в строке

Код: Выделить всё

$data = xml2array($xml, 0);
0 на 1, можно переключать вывод общих строк или их параметры. Пока объеденить у меня не получилось. Но работаю над этим ..

Спасибо, geosub за рабочий код ! )

MarquusGun
Сообщения: 59
Зарегистрирован: 05 ноя 2009, 22:49

Сообщение MarquusGun » 01 окт 2010, 21:03

А с большими файлами на сколько отработает быстро? К примеру, если включить все товары своего-магазина по всем реклам, то насколько быстро отработает, включая вставку в базу. И еще бы хорошо иметь данные по машине, на которой тестировалось.

repair
Сообщения: 3
Зарегистрирован: 09 окт 2006, 14:22

Сообщение repair » 25 мар 2011, 18:59

А с большими он загибается ест-но, по Allowed memory size.

MarquusGun
Сообщения: 59
Зарегистрирован: 05 ноя 2009, 22:49

Сообщение MarquusGun » 25 мар 2011, 21:29

Я сразу не заметил. Конечно тяжко ему, ведь буфер в ОЗУ. Если прайс, скажем, метров 100 - то 100 метров в ОЗУ засунуть - надо еще умудриться.
Такие разборщики надо юзать при небольших по размеру прайсах и при небольшом числе таких небольших прайсов.

repair
Сообщения: 3
Зарегистрирован: 09 окт 2006, 14:22

Сообщение repair » 01 апр 2011, 22:20

Я "домучил" свой вариант sax парсера, на пхп. 22 мега обрабатывает за 60-65 сек, с засылкой в бд + многочислеными проверками, на стареньком атлоне 3600+. Это так, для справки.
---
Обработка:advertizers
Обработка:regions_delivery
Обработка:regions
Обработка:regions_geotarget
Обработка:adv_region_geotarget
Обработка:currencies
Обработка:brands
Обработка:categories
конец, время выполнения= 62
--
теперь осталось магазин добить.

MarquusGun
Сообщения: 59
Зарегистрирован: 05 ноя 2009, 22:49

Re: Пример парсера XML файлов в базу.

Сообщение MarquusGun » 13 июн 2011, 20:51

repair, не, нужно замерить, скажем, 250 прайсов и посомтреть на ресурсы машины во время работы (предполагается, что разборщик работает на том же хосте, на котором располагается сайт (сайты). И разбирать прайс-листы не минимальные по объему, а такие, как у викимарта, к примеру.
Я не пиписькой мерююсь, я просто хочу подсказать ориентир, на который нужно стремиться. Иначе можно загнать себя в такой тупик, выходом из которого будет лишь один способ: полная смена алгоритма парсера прайс-листа.

Ответить