суббота, 26 февраля 2011 г.

Парсинг HTML: путь Ктулху!

Данная статья является переводом статьи Parsing HTML The Cthulhu Way Джефа Эфтвуда. 

Каждый программист в независимости от опыта понимает, что парсинг HTML при помощи регулярных выражений считается плохой идеей. Насколько плоха эта идея? Это сразу становится очевидным после рассмотрения одного случая, когда один из пользователей StackOverFlow.com дошел до грани безумия (текст по ссылке на английском языке): 

"Вы не можете парсить HTML используя регулярные выражения. Regex не является средством, которое позволяет корректно парсить HTML. Как я уже много раз отвечал на вопросы связанные с парсингом HTML, использование regex не позволяет вам полностью обработать HTML и учесть все нюансы этого языка разметки. 

Регулярные выражения - это не достаточно мощное средство для анализа конструкций присутствующих в HTML. HTML не является регулярным языком и следовательно не может быть обработан при помощи регулярных выражений. Regex не разработаны для того, что бы разбивать HTML на части, которые имеют смысл. Сколько раз я уже отвечаю, но чувствую, что это никогда не кончиться. Даже расширенные нерегулярные regex в Perl не предназначены для того, что бы парсить HTML. Вы никогда меня не поломаете. HTML - достаточно сложный язык для того, что бы его можно было парсить при помощи regex. 

Только Jon Skeet не может парсить HTML при помощи regex. Каждый раз когда вы пытаетесь парсить HTML при помощи регулярных выражений - ребенок плачет кровью девственниц и русские хакеры взламывают ваше веб-приложение. Парсинг HTML при помощи regex вызывает грешные души в царство живых. Regex и HTML вместе сочетаются также как и любовь, брак, а также ритуальное детоубийство. Тег <center> не будет сохранятся вечно - он уже мертв. Использование regex и HTML - это сила, которая при использовании на одном концептуальном уровне, просто вынесет ваш мозг вдребезги! Если вы парсите HTML при помощи regex вы приводите к гибели всех нас, которые бесчеловечно трудятся для одного языка, который не может быть выражен в рамках базовых многоязычных конструкций." 

И это правильно, если вы пытаетесь парсить HTML при помощи regex, то вы поддаетесь искушениям темного бога Ктулху... 


Это конечно же все весело, но это очень важно, что эти слова имеют смысл и родились из очень реального разочарования (текст по ссылке на английском языке). 

Я уже слышал этот аргумент. Обычно я слышу это как обоснование следующего кода:

# pull out data between tags
($table_data) = $html =~ /(.*?)<\/td>/gis; 

"Но это работает!" - они говорят. 
"Это легко!" 
"Это быстро!"
"Это хорошая работа."

Я ругаю их, что бы они были ленивыми. Вы должны быть ленивы как программист. Парсинг HTML - решенная проблема. Вы не должны решать ее. Вы всего лишь должны быть ленивы. Будьте ленивы, используйте CPAN и HTML::Sanitizer. Ваше программирование будет значительно более легким занятием. Ваш код будет расширяем. Вы не должны сидеть и вручную писать регулярные выражения. Ваш код будет более надежный. Вы не должны будете заниматься отладкой все время из-за ошибок, которые возникают, если HTML "поломает" ваши регулярные выражения. 

Новички программирования сильно удивляются, когда узнают, что парсинг HTML при помощи regex это - путь Ктулху, вместо использования необходимых библиотек, как поступил бы разумный человек или опытный программист. Это означает, что это обсуждение будет постоянно продолжаться на StackOverFlow. Выше написанный пост, которому уже 5 лет, может обсуждаться так, как будто он написан еще вчера, я думаю это позволительно, учитывая степень важности данной проблемы.

Как я уже сказал это хорошо понимаемый феномен в многих кругах программистов. Однако, я был удивлен, когда увидел в комментариях поддержку парсинга HTML при помощи регулярных выражений, опытными программистами. Я имею ввиду, что они желали слушать зов Ктулху и им это нравилось.

У многих программ нет необходимости предвидеть весь универсум HTML при парсинге. На самом деле, такой подход может быть в край неверен, если программа будет изменятся из простого скрипта до коммерческого продукта, где поддержка стоит время, а время - это деньги. Расходы ресурсов всегда (ой, я имею ввиду часто, я слишком обобщаю) должны учитываться при разработке программного обеспечения. 


Кроме того, жесткие ограничение никак не должны быть связаны с HTML ограничениями. Они должны быть такие простые как "работа с этими наборами веб-страниц", "работа с данными с этих веб-страниц", "работать для 98% пользователей 98% времени" или даже "О, нет! Мы должны сделать эту работу за час, сделай все, что сможешь!". 

Мы живем в мире полном PHP программистами новичками, которые делают то, что приходит в их коллективные головы в первую очередь и каждый день в мире рождается еще большее количество новичков PHP программистов. Мы здесь имеем дело с постоянной проблемой образования. Настоящий враг это - не регулярные выражение (или, например, goto), а невежество. Преступление совершается уже тогда, когда нет других альтернатив.

Таким образом, если я захочу парсить HTML при помощи regex, то я четко понимаю, что:
  • Это очень плохая идея. 
  • Если вы не дисциплинированы и строго себя не ограничиваете, то парсинг HTML при помощи regex приведет вас к безумию, а Ктулху это любит!
  • Я очень четко осознаю, что причина использования regex для парсинга HTML в данном сценарии (полу) оправдана. 
Я думаю, что полностью ограничить парсинг HTML при помощи регулярных выражений, это тоже самое, что решать простую тривиальную задачу парсинга HTML при помощи какого-нибудь огромного движка. Лучше понимать инструменты, их сильные и слабые стороны, чем просто подчинятся догмам. 

Так вот, использование регулярных выражений для парсинга HTML это в основном плохая идея. Мы должны каждому новичку программисту заложить эту мысль. Даже если эта работа не имеет конца. Но мы также должны научить видеть большое различие между парсингом HTML и парсингом пары строчек текста и также, что бы они могли объяснять какой подход к решению задачи правильный и почему. 

Какой бы метод вы не выбрали, никогда не открывайте тег <cthulhu> ради всего человечества. 

Комментариев нет:

Отправить комментарий