новости
статьи
.программирование

сделайте ваши страницы 404 интеллектуальными при помощи сопоставления метафонов

Создайте собственный обработчик сообщения об ошибке 404 для предоставления посетителям полезных ссылок и перенаправления на содержимое вашего сайта. Используйте алгоритм сопоставления метафонов (metaphone matching) и файл простых весовых оценок для перенаправления пользователей при опечатках и орфографических ошибках, а также некорректных ссылках. Настройте варианты выбора на основе содержимого вашего веб-сайта и предпочтительных для перенаправления разделах сайта. Не пропустите многочисленные ошибки во входящих URL-запросах и исправьте названия каталогов, сценариев и HTML-страниц, имеющихся в них.

Существует много учебных руководств, демонстрирующих, как создать эффективно действующую страницу 404. Большинство из них предлагает статические ссылки, ведущие на общие разделы вашего сайта, такие как стартовая страница, страница материалов для загрузки или поисковый механизм при его наличии. Проблема стандартной страницы 404 заключается в том, что она не учитывает причину, по которой пользователь зашел на сайт. В данной статье рассказывается, как реализовать механизм формирования предположений и описывается метод предоставления полезных ссылок для перенаправления, которые основаны на содержимом веб-сайта.

Современные обработчики 404 ошибки позволяют предоставлять несколько ссылок для всех ошибок, например, указывая пользователям каталог сайта. Орфографические корректоры, такие как mod_speling (да-да, здесь именно одна буква "l") можно использовать для исправления ошибок в словах словаря, что может помочь пользователю попасть на правильную страницу. Приведенный здесь исходный код поможет вам построить механизм создания предложений для обработки слов не из словаря и ссылок на каталоги на основе содержимого веб-сайта.

Допустим, например, что вы услышали название веб-страницы во время телеконференции и пробуете ссылку blegs/DavSmath.html. В данной ситуации имеющиеся модули орфографической коррекции не смогут предоставить полезную ссылку. Используя исходный код из этой статьи, вы сможете сгенерировать страницу 404, предлагающую правильный вариант адреса страницы – /blogs/DaveSmith.html.

требования

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

Приведенные Perl- и CGI-сценарии работают на различных версиях UNIX и Windows. Хотя в данной статье используется Apache и CGI-сценарий для механизма формирования предложений, встроенные инструментальные средства должны работать с большинством веб-серверов. Для сопоставления метафонов (metaphone) в данной статье используется модуль Майкла Шверна (Michael Schwern) Text::Metaphone. Установите модуль Text::Metaphone с любого зеркала CPAN, и вы будете готовы начать работу.

страницы веб-сервера и коды метафонов

Главным методом, который мы будем использовать для предложения альтернатив при опечатках и орфографических ошибках будет сопоставление метафонов. Алгоритм Metaphones, аналогично Soundex и другим подобным алгоритмам, использует алфавитно-цифровой код для представления вербального произношения слова. Однако, в отличие от Soundex, при создании кодов метафонов учитывалось лингвистическое разнообразие произношения в английском языке. Следовательно, средний код метафона является намного более точным представлением данного слова и идеальной основой для построения библиотеки предложений.

Рассмотрим следующий список файлов в примере каталога веб-сервера.

./index.html
./survey.html
./search_tips.html
./about.html
./how.html
./why.html
./who.html
./NathanHarrington.html
./blogs/NathanHarrington.html
./blogs/DaveSmith.html
./blogs/MarkCappel.html


При работе с этим набором статических HTML-файлов мы будем использовать программу buildMetaphoneList.pl для создания метафонов для каждого имени файла с расширением .html.

#!/usr/bin/perl -w
# buildMetaphoneList.pl - / разделить имя файла, вес 0, метафоны

use strict;
use File::Find;
use Text::Metaphone;

find(\&htmlOnly,".");

sub htmlOnly
{
if( $File::Find::name =~ /\.html/ )
{
my $clipFname = $File::Find::name;
$clipFname =~ s/\.html//g;
my @slParts = split '/', $clipFname;
shift(@slParts);
print "$File::Find::name ### 0 ### ";
for( @slParts ){ print Metaphone($_) . " " }
print "\n";
}#если соответствующий .html-файл

}#htmlOnly sub


Программа buildMetaphoneList.pl обрабатывает файлы только с расширением .html, удаляет .html из названия, затем генерирует метафоны для каждой части полного имени пути. Скопируйте программу buildMetaPhoneList.pl в корневой каталог вашего веб-сервера и выполните команду perl buildMetaphoneList.pl > metaphonesScore.txt. Для файлов из представленного ранее списка содержимое соответствующего файла metaphonesScore.txt показано ниже.

./index.html ### 0 ### INTKS
./survey.html ### 0 ### SRF
./search_tips.html ### 0 ### SRXTPS
./about.html ### 0 ### ABT
./how.html ### 0 ### H
./why.html ### 0 ### H
./who.html ### 0 ### H
./NathanHarrington.html ### 0 ### N0NHRNKTN
./blogs/NathanHarrington.html ### 0 ### BLKS N0NHRNKTN
./blogs/DaveSmith.html ### 0 ### BLKS TFSM0
./blogs/MarkCappel.html ### 0 ### BLKS MRKKPL


В каждой строке имеется реальная ссылка относительно корневого каталога веб-сервера, вес по умолчанию и код метафона. Обратите внимание на то, что how.html, why.html и who.html имеют один и тот же код метафона. Для исправления этой неоднозначности измените поле веса, чтобы программа предложения ссылок предоставляла ссылки в желаемом порядке. Например, измените записи с кодом метафона "H" на:./how.html ### 100 ### H

./why.html ### 50 ### H
./who.html ### 0 ### H


Таким образом задается прямая сортировка ссылок, при этом остается возможность последующих модификаций значений веса. Большие значения весов удобны, т.к. учитывают возможность последующей вставки файлов с одинаковыми кодами метафона, но с разными весами. Например, добавляя файл hoo.html в список, можно было бы использовать вес 25, чтобы данная ссылка располагалась выше записи who.html и ниже записи why.html. Вы можете также использовать поле значений веса, чтобы различать файлы с одинаковым именем, но из разных каталогов. Измените вес в строке ./NathanHarrington.html на 100, например, и при запросе страницы nathenHorrington.html в списке отобразится ссылка на ./NathanHarrington.html перед ./blogs/NathanHarrington.html.

При выборе весов ваших файлов учитывайте статистические и логические компоненты доступа вашего веб-сайта. Пользователи могут чаще запрашивать страницу why.html согласно log-файлам, но если вы знаете, что более важной для них является страница how.html, просто укажите соответствующие веса для корректной сортировки.

создание CGI-обработчика 404

Имея соответствующие метафоны, сгенерированные вместе со своими весовыми коэффициентами, мы можем создать действующий модуль выдачи предложений. Обычно сообщение об ошибке 404 выдается из-за опечаток в ссылке или из-за неправильности самой ссылки. Предложения, генерируемые приведенным ниже кодом, будут создаваться при выполнении трех основных тестов: соответствие заданной структуре каталогов, соответствие комбинированному метафону и соответствие "включению", когда все остальные тесты неудачны. Эти три теста предназначены для обработки большинства ошибок 404. Начало Perl-сценария MetaphoneSuggest CGI приведено ниже.

#!/usr/bin/perl -w
# MetaphoneSuggest - предлагает ссылки для опечаток и других ошибок из 404
use strict;
use CGI::Pretty ':standard'; #standard cgi stuff
use Text::Metaphone;

my @suggestLinks = (); # список предлагаемых ссылок
my %mt = (); # имя файла, вес, хэш кодов метафонов
my $origLink = substr($ENV{REDIRECT_URL},1); # удалить ведущие /
$origLink =~ s/\.html//g; # удалить замыкающий .html

open(MPH,'metaphonesScore.txt') or die "can't open metaphones";
while(my @slPart = split '###', <MPH>)
{
$slPart[0] =~ s/ //g; #удалить замыкающие пробелы
$mt{$slPart[0]}{ score } = $slPart[1];
$mt{$slPart[0]}{ metaphones } = $slPart[2];
}
close(MPH);


После обычных включений библиотек и объявлений переменных код будет загружать текст 404, а также метафоны, созданные при помощи программы buildMetaphoneList.pl. Теперь мы готовы перейти к логике основной программы, как показано ниже.

push @suggestLinks, sortResults( directorySplitTest( $origLink ) );
push @suggestLinks, sortResults( combinedTest( $origLink ) );
push @suggestLinks, sortResults( containsTest( $origLink ) );

my %seen = ();
@suggestLinks = grep{ ! $seen{$_}++ } @suggestLinks ;

print header;
print qq{Error 404: The file requested [$ENV{REDIRECT_URL}] is unavailable.<BR >};
next if( @suggestLinks == 0 );

print qq{Please try one of the following pages:<BR >};
for my $link( @suggestLinks ){
$link = substr($link,index($link,'./')+1);
print qq{<a href="$link">$link</a><BR >};
}


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

Три команды сортировки, помещенные в один массив результатов, предназначены для создания упорядоченного и отсортированного по номеру списка предложений. Весьма вероятно, что при возникновении 404-й ошибки наличие разделителей каталогов говорит о том, что искомая веб-страница находится как минимум на один уровень вниз по дереву каталогов. Возьмем, к примеру, запрос страницы bloggs/nathenherringtoon.html. Вызов directorySplitTest создаст отсортированный список страниц, имеющих совпадение метафонов для BLKS и N0NHRNKTN в соседних по уровню вложенности каталогах. Такая стратегия обеспечивает необходимое различие между файлами в корневом каталоге, например, blogs.html и nathanharrington.html, и страницами с полным именем пути blogs/nathanharrington.html. В приведенном ниже листинге показано содержимое подпрограммы directorySplitTest.

sub directorySplitTest
{
my @matchRes = ();
my $inLink = $_[0];
for my $fileName ( keys %mt )
{
my @inLinkMetas = ();
# обработать каждую часть метафонов как каталог
for my $inP ( split '\/', $inLink ){ push @inLinkMetas, Metaphone($inP) }
my @metaList = split ' ', $mt{$fileName}{metaphones};
next if( @metaList != @inLinkMetas );
my $pos = 0;
my $totalMatch = 0;
for( @metaList )
{
$totalMatch++ if( $metaList[$pos] =~ /(\b$inLinkMetas[$pos]\b)/i );
$pos++;
}#цикл по meatlist

# проверить, есть ли совпадение в каждой части метафонов
next if( $totalMatch != @metaList );
push @matchRes, "$mt{$fileName}{score} ## $fileName";

}#цикл по ключам в хэше метафонов

return( @matchRes );

}#directorySplitTest


После directorySplitTest комбинированный тест будет проверять случаи, в которых метафоны смешаны друг с другом, не обращая внимания на структуру каталогов. Это полезно для исправления таких ошибок 404, которые вызваны наличием в именах файлов пробелов, символов косой черты, обратной косой черты, двоеточия и других непроизносимых символов. Например, если был запрос 404 для blogs_nathanherrington.html, directorySplitTest не даст результата, зато combinedTest найдет, что метафоны, сгенерированные этой 404, являются точным соответствием blogs/NathanHarrington.html при их комбинировании. Опять же, эти предложения имеют меньший приоритет, чем соответствие каталогов, поэтому их отсортированные результаты помещаются в массив suggestLinks после directorySplitTest. В следующем листинге приведена подпрограмма combinedTest.

sub combinedTest
{
my @matchRes = ();
my $inLink = $_[0];
for my $fileName ( keys %mt )
{
my $inLinkMeta = Metaphone($inLink);
# смешать все ключи вместе, удаляя пробелы и замыкающие символы новой строки
my $metaList = $mt{$fileName}{metaphones};
$metaList =~ s/( |\n)//g;
next if( $metaList !~ /(\b$inLinkMeta\b)/i );
push @matchRes, "$mt{$fileName}{score} ## $fileName";
}#цикл по ключам имени файла в хэше метафонов

return(@matchRes);
}#combinedTest


После combinedTest делается последняя попытка поиска соответствий на основе расширенного поиска включений (contains search). Если метафон текущей ссылки 404 есть где-нибудь в любом из доступных метафонов в metaphoneScores.txt, мы будем добавлять его в список предложений. Поиск включений предназначен для незавершенных URL. Страницы nathan.html нигде нет, но хорошим предложением могли бы быть страницы
/NathanHarrington.html и /blogs/NathanHarrington.html, и они сортируются по весу и добавляются в массив suggestLinks. Обратите внимание на то, что такой подход будет также генерировать предложения NathanHarrington.html для односимвольного метафона whoo.html. Поскольку метафон NathanHarrington.html содержит "H", он будет добавлен в список предложений. Для изменения такого поведения можно предусмотреть учет минимальных длин совпадающих метафонов или ограничить число совпадающих включений.

Подпрограммы sortResults и containsTest:

sub sortResults
{
# просто процедура для сортировки массива записей 'score ## filename'
my @scored = @_;
my @idx = (); #временный индекс для сортировки
for my $entry( @scored ){
# создать индекс весовых коэффициентов
my $item = substr($entry,0,index($entry,'##'));
push @idx, $item;
}

# отсортировать индекс весовых коэффициентов
my @sorted = @scored[ sort { $idx[$b] <=> $idx[$a] } 0 .. $#idx ];

return( @sorted );

}#sortResults

sub containsTest
{
my @matchRes = ();
my $inLink = $_[0];
for my $fileName ( keys %mt )
{
my $inLinkMeta = Metaphone($inLink);
my $metaList = $mt{$fileName}{metaphones};
next if( $metaList !~ /$inLinkMeta/i );
push @matchRes, "$mt{$fileName}{score} ## $fileName";
}#цикл по ключам имен файлов в хэше метафонов
return(@matchRes);

}#containsTest


изменение файла Apache httpd.conf

Сценарий MetaphoneSuggest является сценарием cgi-bin, вызываемым из Apache. Чтобы вместо страницы ошибки 404 выполнялся сценарий
MetaphoneSuggest, необходимо внести изменения в файл httpd.conf. Например, если ваш файл httpd.conf по умолчанию имеет раздел:

# Настраиваемые ответы на ошибки могут быть трех разновидностей:
# 1) обычный текст 2) локальные перенаправления 3) внешние перенаправления
#
# Некоторые примеры:
#ErrorDocument 500 "The server made a boo boo."
#ErrorDocument 404 /missing.html
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
#ErrorDocument 402 http://www.example.com/subscription_info.html


вставьте строку

ErrorDocument 404 "/cgi-bin/MetaphoneSuggest"

после закомментированных строк ErrorDocument. Убедитесь в том, что файлы MetaphoneSuggest и metaphonesScore.txt находятся в каталоге <document_root>/cgi-bin/ вашего Web-сервера. Выполните команду перезапуска сервера с полномочиями root /usr/local/apache2/bin/apachectl restart (например), и вы будете готовы начать предоставлять разумные предложения вместо тупиковых ошибок.

варианты реализации и практические соображения

При использовании инструментальных средств, описанных в программе MetaphoneSuggest, помните о том, что страница 404 - это состояние ошибки. Предоставляйте только несколько альтернатив и не усложняйте дизайн. Спросите у знатоков веб-дизайна, почему они не предоставляют автоматические предложения ссылок, или посоветуйтесь, как лучше реализовать средство предложения ссылок на вашем сайте.

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



Натан Хэррингтон, разработчик приложений, IBM
обсудить статью
© сетевые решения
.
.