Научный консалтинг
Главная
Контакты
Номер телефона
Как мы работаем
Гарантии
Условия
Цены

Последнее обновление:

Не используйте библиотеку simple_html_dom.php

Это библиотека предназначена для работы с HTML-содержимым при помощи DOM, т.е. по аналогии с javascript. Известно, что, если не принять специальных мер, язык РНР воспринимает код html точно также, как и любой другой текст – в виде константы типа string определенной длины. Чтобы с текстом (кодом) html можно было бы работать, используя модель DOM, нужны те или иные приемы.

Одним из них и является библиотека simple_html_dom.php. Ее можно подключить в любом месте файла рнр, например, следующим образом:

include($_SERVER['DOCUMENT_ROOT'].'/path/simple_html_dom.php');

После чего ее можно использовать. Да, можно. Не, не нужно.

Объем этой библиотеки занимает 63,5 КБайт. Вроде бы, немного. Число строк внутри ее файла – всего-то 1700 с небольшим. Казалось бы, ерунда. Однако, она существенно замедляет работу программ.

Пример

Рассмотрим простейший пример, из которого это видно. Поставим задачу:

Найти в конце некоего файла html последний тег <span> (имеющий id=”counter_comm” и вывести на экран его содержимое (т.е. текст, который он содержит).

В javascript эта задача вполне знакомая и решается в пару строк. На РНР, в принципе, все не намного сложнее.

Вот программный код, использующий библиотеку simple_html_dom.php:

$tim[1] = microtime(true);
  $id_comm = 0;
  $text = str_get_html($file_html);
  if(is_object($text->find('span[id=counter_comm]',0))){
     $id_comm = $text->find('span[id=counter_comm]',0)->plaintext;
     echo "id_comm: ".$id_comm;
  }else{
     $file_html = '<div class="com"><div id="number_comm__">Значение счетчика <span id="counter_comm">0</span></div></div>';
  }

Вначале этот код считывает текущее время в секундах с высокой точностью, заносит его в массив $tim[]. После чего ищет в текстовой переменной $file_html тег, имеющий указанный id и, если найдет, выводит его текстовое значение. Если же не найдет – то добавляет соответствующие html-теги со значением счетчика, равным нулю.

Однако, данный задачу вполне можно решить, используя чистый РНР, без этой библиотеки. Благо, РНР, как и javascript, вполне умеет работать с DOM. Надо лишь дать ему понять, что обрабатывается не просто текстовая (string) константа, а, именно – код html:

$tim[2] = microtime(true);
   $id_comm1 = 0;
       $domdocument = new domDocument('1.0', Encoding);
       $domdocument->loadXML(XMLHead."<html><body>".mb_convert_encoding($file_html, "cp1251", "utf-8")."</body></html>");
       $span_counter = $domdocument->getElementsByTagName("span");
// Получаем узел - последний тег <span> (т.е. тот, в котором находится счетчик)
   
$number = $span_counter->item($span_counter->length-1);
// Общее число счетчика (определяется по текстовому значению последнего тега <span> в файле ***-comments.html)
   
$id_comm1 = $number->lastChild->nodeValue;
   echo "id_comm1: ".$id_comm1;
if($id_comm1 == 0)

   $file_html = '<div class="com"><div id="number_comm__">Значение счетчика <span id="counter_comm">0</span></div></div>';
$tim[3] = microtime(true);

Как и ранее, записываем в указанный массив новое текущее время (которое совпадает с моментом окончания работы предпоследнего кода и начала работы последнего).

Затем указываем РНР, что имеем дело с html. Переменная $domdocument будет содержать html-код в соответствии с моделью DOM.

Точно также, как и в предыдущем случае, если число в последнем теге <span> равно нулю или он вовсе отсутствует, то в файл добавляются соответствующие теги, задающее значение счетчика, равное нулю.

После чего определяем конечное время – момент, когда второй код прекращает работу. Вывод времен работы обоих кодов осуществлялся следующим образом:

echo "time: ".($tim[2]-$tim[1])." ".($tim[3]-$tim[2]);

Примечание: Здесь используются константы, имеющие следующие значения:

// Стандартная кодировка документа

define('Encoding', 'windows-1251');

// Заголовок XML-документа

define('XMLHead', "<?xml version='1.0' encoding='".Encoding."'?>");


Как видим, объем кода практически тот же самый – в обоих случаях.

Сравниваем быстродействие

Оба программных кода тестировались на файле размером 184 Кбайт на локальном компьютере достаточно высокой производительности.

И вот каковы типичные результаты:

time: 0.17655420303345 0.010126829147339

time: 0.19093608856201 0.010679006576538

Видно, что разница есть. Первый код работает дольше второго – более, чем в 17 раз. Хотя, вроде бы – та же самая задача, тот же самый файл, тот же самый компьютер, и тот же самый РНР. Да и выполняются оба кода – один за другим.

А, так, может, как-то влияет кэширование? Для проверки этого предположения – поменяем местами указанные коды. Т.е. теперь вначале будет работать код без библиотеки, а потом – с библиотекой. Вот реультаты времени работы:

time: 0.012299060821533 0.18253898620605

time: 0.011257886886597 0.18212008476257

Что же, компьютер – не обманешь. Все равно тот код, который использует библиотеку, работает медленнее, как минимум, в 17 раз.

Самое интересное, что данная библиотека даже не дает никакой особой легкости для программиста. К с ее помощью, так и без нее – все равно не обойтись без написания программного кода, повторимся, примерно одинакового объема. Вот, для сравнения, те же данные, полученные при запуске указанных выше программных кодов на сервере:
time: 0.01199197769165 0.06469202041626

Код с библиотекой работает на севере почти в 3 раза быстрее (чем на локальном компьютере). Однако, тем не менее, все равно по быстроте проигрывает - почти в 6 раз. Так к тому же, замечено, что эта библиотека еще и способна неконтролируемо изменить код html, который обрабатывается при помощи нее. Например, она способна убрать все символы переноса строк, превращая код в нечто нечитаемое.

Отметим, что лишь ОДНА операция – поиска соответствующего тега <span> и считывание его текстового содержимого (что потребовала аж целых три вызова библиотечных функций) потребовали время, равное почти 0,2 секунды на локальном компьютере (свыше 0,05 с на сервере). А если таких операций будет на три, а 33? Или 333?... А если объем обрабатываемого кода html будет увеличен раз в 100? В таком случае – это уже будет не сайт, а тормозящая, поедающая ресурсы сервера, никому не нужная, а то и раздражающая пользователей – игрушка. После чего появятся посты где-нибудь на хабрахабре о «ненужности» языка РНР. А также о желании попробовать что-то «новое».

Так зачем и кому может понадобиться библиотека simple_html_dom.php?

Не в обиду ее разработчику, но, честно говоря, не знаю. Разве что, для того, чтобы реализовать довольно эффективный замедлитель работы программ на РНР (хотя, как видите, замедление-то осуществляется всего в 3...17 раз, все же; ведь не два-три порядка). И потом писать письма заказчикам (употребляя в них разного рода жаргонные «термины», используемые на компьютерных форумах и делая вид, что, мол, обижаемся из-за того, что заказчик, мол, такой «непонятливый»).

Хотя, может, для кого это будет новостью, но все же стоит высказать: заказчик вообще не обязан быть понятливым. Все, что он ДОЛЖЕН – это четко сформулировать задачу, решение которой для него требуется. Ну и, оплатить оговоренную стоимость за выполненную работу.

Письма на предмет того, что РНР, якобы, «мертвый» язык, медленный и т.п. И вообще, мол, если заказчик желает, чтобы все работало быстро, надо, типа того, весь его сайт переделывать, переводить на «более эффективный язык» (который по производительности может быть даже хуже). Или - переносить сайт на более скоростной хостинг.

Однако, как видим, язык РНР может работать быстро, главное, НЕ использовать ненужные библиотеки. Впрочем, на вкус и цвет = как говорится. Если кому по душе эта или иные аналогичные библиотеки - конечно, используйте на здоровье.

Комментарии:
Научный Консалтинг02.02.2022 18:54РедактироватьУдалить
Кроме того, оказалось, что эта библиотека неспособна корректно работать с DOM при размере строки, немного превышающей по размеру всего 660 кБ. Ведь это - не столь и много. Однако, тем не менее. В частности, проблема возникла в функции find(). Вид ошибки - невозможно преобразовать строку в объект DOM. Кстати, вполне возможно, что эта библиотека даст сбой даже при меньшем объеме строки - мы не проверяли. Тогда как применение, например, стандартных функций языка РНР, типа loadXML, getElementById, getElementsByTagName и т.д. со строкой указанного размера работает вполне корректно. Это лишь, увы, подтверждает ранее сделанный вывод. Да, код библиотеки simple_html_dom.php красиво написан (конечно же, соблюдены стандарты языка PHP, типа PZR_12), реализация этой библиотеки вся такая современная и объектно-ориентированная (ну, потому и медленная, чудес-то не бывает). Но, при мало-мальски серьезной работе - банальный и позорный отказ.
Всего комментариев: 1
Пожалуйста, не забудьте ознакомиться с правилами оставления комментариев.



Подписаться на комментарии на этой странице

Мы можем выполнить

Другие услуги
Интересная и полезная
информация