перенаправить 404 на похожие URL-адреса

У меня есть сайт с рассказами в нем. Я могу иметь несколько типов историй в нескольких категориях, таких как:

  • дети
  • романс
  • SciFi
  • действие
  • thriler
  • квесты

Истории доступны с использованием URL-адресов, таких как:

www.example.com/action/story-name-action/ www.example.com/romance/story-name-romance/ 

и первый параметр (действие) и второй (рассказ-действие-действие) перенаправляются с помощью .htaccess с использованием правил. Эта часть работает отлично.

В последнее время я получаю несколько десятков 404 разных сайтов, и вот что я хочу сделать, но я не знаю, как:

Если кто-то набирает, например: /action/story-nme-ction , я хочу перенаправить на: action/story-name-action/

Есть ли эффективный способ реализовать это?

О человек, о человек!

То, о чем вы просите, не просто и вам нужно иметь мощный компьютер, но результаты просто потрясающие.

Вот что я предлагаю сделать:

  • Для правильной обработки 404 у вас есть перенаправление ErrorDocument в конфигурации ErrorDocument . Моя выглядит так: ErrorDocument 404 /404.php ;
  • Когда у вас есть 404, Apache вызовет /404.php со всеми аргументами (какой плохой URL и т. Д., Дамп $_SERVER чтобы увидеть это). Вы должны проверить, есть ли только два выражения в URL / ie http://mysite.com/(expr1)/(expr2)/
  • Если нет, тогда сделайте классический 404.
  • Если да, то выполните поиск SOUNDEX с MySQL (в вашем 404 Php файле). См. Образец запроса здесь .
  • Затем в этом «специальном» случае 404 сделайте предложение, например google, то есть: «вы имели в виду /action/story-name-action/ ? Если это так, щелкните по ссылке».

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

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

 mysql> SELECT * FROM job WHERE SOUNDEX( description ) LIKE SOUNDEX('Machiniste cinéma'); +-------+--------------------+ | id | description | +-------+--------------------+ | 14018 | Machiniste cinéma | +-------+--------------------+ 1 row in set (0.06 sec) mysql> SELECT * FROM job WHERE SOUNDEX( description ) LIKE SOUNDEX('Mchiniste cinéma'); +-------+--------------------+ | id | description | +-------+--------------------+ | 14018 | Machiniste cinéma | +-------+--------------------+ 1 row in set (0.06 sec) mysql> SELECT * FROM job WHERE SOUNDEX( description ) LIKE SOUNDEX('Machnste cinema'); +-------+--------------------+ | id | description | +-------+--------------------+ | 14018 | Machiniste cinéma | +-------+--------------------+ 1 row in set (0.06 sec) mysql> 

Если вы не уверены в URL-адресе, к которому пользователь действительно хотел перейти, использование перезаписи / перенаправления на определенный URL-адрес – очень плохая идея.

Взяв ваш пример, предположим, что вы хотите обрабатывать каждый случай, когда две буквы могут быть удалены, с 17 символами в последней части URL-адреса, это 17 * 16 = 272 комбинаций, в то время как может быть возможно сопоставить несколько «ложных» URL-адресов с одним регулярным выражением, вам потребуется много правил перезаписи.

Лучшим решением было бы реализовать обработчик 404 с использованием PHP (с тех пор, как вы включили этот тег в свой q), чтобы создать список (скажем) 10 лучших URL-адресов, чьи пути имеют кратчайшее левенштайнское расстояние от запрашиваемого пути, а также ссылка по умолчанию и поддерживающий текст. (Есть реализаций на основе mysql – попробуйте Google для URL-адресов). Обработчик NB должен по-прежнему возвращать статус 404. NB HTML-контент должен быть более чем минимальной длины, чтобы подавить «дружественное» сообщение MSIE.

Если вы знаете, какие могут быть возможные правильные URL-адреса, вы можете использовать:

levenshtein($givenURL, $possibleURL)

Пример из документов PHP, комментарии для краткости удалены:

 $input = 'carrrot'; $words = array('apple','pineapple','banana','orange', 'radish','carrot','pea','bean','potato'); $shortest = -1; foreach ($words as $word) { $lev = levenshtein($input, $word); if ($lev == 0) { $closest = $word; $shortest = 0; break; } if ($lev <= $shortest || $shortest < 0) { $closest = $word; $shortest = $lev; } } echo $shortest == 0 ? "Exact match found: $closest\n" : "Did you mean: $closest?\n"; 

Выходы:

Входное слово: carrrot
Возможно, вы имели в виду: carrot?

Это хорошо, когда вы думаете, что люди, возможно, пропустили письмо или добавили лишний, но это может не оправдаться, когда люди действительно не знают, как записать слово и придумали что-то творческое!

Если вы предпочитаете soundex() , взгляните на metaphone() .

Мне нравится идея использования metaphone() вместе с levenshtein() или similar_text() , поскольку она возвращает фонетическое представление слова, и вы все же хотите видеть, насколько это похоже на ваш оригинал.

Примеры:

 metaphone('name') = NM metaphone('naaaaaameeeeeeee') = NM metaphone('naiym') = NM metaphone('naiyem') = NYM 

В то время как много орфографических ошибок вернет одинаковое соответствие, последний пример показывает, что вы действительно все еще хотите найти ближайший матч с чем-то вроде levenshtein()

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

Если вы получаете одинаковый 404 от одного и того же реферера, (и не можете заставить их изменить ссылку), возможно, стоит просто поставить статический переписать в этом случае.

Существует несколько решений:

  • Определите источник ошибочных URL-адресов. Этого просто не должно быть, и я не могу представить, почему это происходит. Связаны ли другие люди с другими людьми, и они сделали опечатку (игнорируя существование копии и вставки)? Вы можете видеть, откуда это взялось (referer) и связаться с ними?
  • Добавьте идентификатор в URL-адрес, так /action/123/story-name-action , где вы просматриваете статью по идентификатору, а не по его названию (бонус: добавляет возможность создания нескольких историй одной категории с тем же названием )
  • Сделайте нечеткий поиск по названию, используя что-то вроде soundex , и перенаправьте пользователя на наиболее подходящий заголовок или покажите обзорную страницу с похожими названиями, такими как @symcbean.

Я предпочитаю ID ID.

Мы перенаправляем на страницу поиска URL-адрес, например, наш поиск имеет «предлагаемую» функцию.

Поскольку значения (предположительно) вытягиваются из MySQL на основе заголовка, вы можете поместить индекс FULLTEXT в столбец заголовка и использовать функцию MATCH() MySQL, чтобы найти наиболее релевантное соответствие и перенаправить пользователя на это.

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