Подтвердить что ты не робот

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

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

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

Истории доступны с помощью URL-адресов, например:

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

  • Для правильной обработки 404 у вас есть перенаправление ErrorDocument в конфигурации vhost. Моя выглядит так: ErrorDocument 404 /404.php;
  • При наличии 404 Apache вызовет /404.php со всеми аргументами (какой плохой URL и т.д., dump $_SERVER, чтобы увидеть это). Вы должны проверить, есть ли только два выражения в URL / i.e. 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> 

Ответ 2

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

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

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

Ответ 3

Если вы знаете, какие могут быть возможные правильные 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 от одного и того же реферера, (и не можете заставить их изменить ссылку), возможно, стоит просто поставить статический переписать в этом случае.

Ответ 4

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

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

Я предпочитаю идентификатор, хотя.

Ответ 5

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

Ответ 6

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

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