Stack Overflow如何生成其SEO友好的URL?
什么是一个好的完整正则表达式或者其他带有标题的过程:
How do you change a title to be part of the URL like Stack Overflow?
然后变成
how-do-you-change-a-title-to-be-part-of-the-url-like-stack-overflow
在StackOverflow上的SEO友好URL中使用的是什么?
我正在使用的开发环境是Ruby on Rails,但是如果还有其他一些特定于平台的解决方案(.NET,PHP,Django),我也希望看到它们。
我确信我(或者其他读者)会在不同的平台上遇到相同的问题。
我正在使用自定义路由,我主要想知道如何将字符串更改为所有特殊字符都被删除,全部为小写字母并替换所有空格。
解决方案
回答
我们将需要设置一个自定义路由,以将URL指向将处理该URL的控制器。由于我们使用的是Ruby on Rails,因此这里是使用其路由引擎的介绍。
在Ruby中,我们将需要一个已经知道的正则表达式,这是要使用的正则表达式:
def permalink_for(str) str.gsub(/[^\w\/]|[!\(\)\.]+/, ' ').strip.downcase.gsub(/\ +/, '-') end
回答
我不熟悉Ruby on Rails,但以下是(未经测试的)PHP代码。如果发现有用,可以将其快速转换为Ruby on Rails。
$sURL = "This is a title to convert to URL-format. It has 1 number in it!"; // To lower-case $sURL = strtolower($sURL); // Replace all non-word characters with spaces $sURL = preg_replace("/\W+/", " ", $sURL); // Remove trailing spaces (so we won't end with a separator) $sURL = trim($sURL); // Replace spaces with separators (hyphens) $sURL = str_replace(" ", "-", $sURL); echo $sURL; // outputs: this-is-a-title-to-convert-to-url-format-it-has-1-number-in-it
我希望这有帮助。
回答
我对Ruby或者Rails的了解不多,但是在Perl中,我会这样做:
my $title = "How do you change a title to be part of the url like Stackoverflow?"; my $url = lc $title; # Change to lower case and copy to URL. $url =~ s/^\s+//g; # Remove leading spaces. $url =~ s/\s+$//g; # Remove trailing spaces. $url =~ s/\s+/\-/g; # Change one or more spaces to single hyphen. $url =~ s/[^\w\-]//g; # Remove any non-word characters. print "$title\n$url\n";
我只是做了一个快速测试,它似乎可以工作。希望这相对容易翻译成Ruby。
回答
假设模型类具有title属性,则可以简单地覆盖模型中的to_param方法,如下所示:
def to_param title.downcase.gsub(/ /, '-') end
这个Railscast插曲包含所有详细信息。我们还可以使用以下方法确保标题仅包含有效字符:
validates_format_of :title, :with => /^[a-z0-9-]+$/, :message => 'can only contain letters, numbers and hyphens'
回答
那有趣的角色呢?你打算怎么办?乌姆劳人?标点?这些需要考虑。基本上,我将使用白名单方法,而不是上面的黑名单方法:描述我们将允许哪些字符,将哪些字符转换(转换为什么?),然后将其余字符更改为有意义的东西("") 。我怀疑我们是否可以在一个正则表达式中执行此操作?为什么不仅仅遍历字符?
回答
Brian的Ruby代码:
title.downcase.strip.gsub(/\ /, '-').gsub(/[^\w\-]/, '')
downcase
将字符串转换为小写字母,strip
除去前导和尾随的空格,第一个gsub
调用全局地用破折号代替空格,第二个`gsub'除去所有不是字母或者破折号的东西。
回答
这是我们的方法。请注意,边缘条件可能比我们乍看之下要多。
这是第二个版本,已推出,性能提高了5倍(是的,我对其进行了基准测试)。我认为我会对其进行优化,因为该功能每页可以被调用数百次。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/// <summary> /// Produces optional, URL-friendly version of a title, "like-this-one". /// hand-tuned for speed, reflects performance refactoring contributed /// by John Gietzen (user otac0n) /// </summary> public static string URLFriendly(string title) { if (title == null) return ""; const int maxlen = 80; int len = title.Length; bool prevdash = false; var sb = new StringBuilder(len); char c; for (int i = 0; i < len; i++) { c = title[i]; if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) { sb.Append(c); prevdash = false; } else if (c >= 'A' && c <= 'Z') { // tricky way to convert to lowercase sb.Append((char)(c | 32)); prevdash = false; } else if (c == ' ' || c == ',' || c == '.' || c == '/' || c == '\' || c == '-' || c == '_' || c == '=') { if (!prevdash && sb.Length > 0) { sb.Append('-'); prevdash = true; } } else if ((int)c >= 128) { int prevlen = sb.Length; sb.Append(RemapInternationalCharToAscii(c)); if (prevlen != sb.Length) prevdash = false; } if (i == maxlen) break; } if (prevdash) return sb.ToString().Substring(0, sb.Length - 1); else return sb.ToString(); }
要查看被其替换的先前版本的代码(但在功能上等效,并且快5倍),请查看此帖子的修订历史记录(单击日期链接)。
同样,可以在这里找到RemapInternationalCharToAscii
方法的源代码。
回答
从好的方面来说,这是WordPress中的PHP函数实现的...我想WordPress是使用花哨链接的较流行平台之一。
function sanitize_title_with_dashes($title) { $title = strip_tags($title); // Preserve escaped octets. $title = preg_replace('|%([a-fA-F0-9][a-fA-F0-9])|', '------', $title); // Remove percent signs that are not part of an octet. $title = str_replace('%', '', $title); // Restore octets. $title = preg_replace('|---([a-fA-F0-9][a-fA-F0-9])---|', '%', $title); $title = remove_accents($title); if (seems_utf8($title)) { if (function_exists('mb_strtolower')) { $title = mb_strtolower($title, 'UTF-8'); } $title = utf8_uri_encode($title, 200); } $title = strtolower($title); $title = preg_replace('/&.+?;/', '', $title); // kill entities $title = preg_replace('/[^%a-z0-9 _-]/', '', $title); $title = preg_replace('/\s+/', '-', $title); $title = preg_replace('|-+|', '-', $title); $title = trim($title, '-'); return $title; }
此功能以及某些支持功能可以在wp-includes / formatting.php中找到。
回答
有一个名为PermalinkFu的小型Ruby on Rails插件可以做到这一点。转义方法将转换为适合URL的字符串。看一下代码;该方法非常简单。
要删除非ASCII字符,它使用iconv库将其从'utf-8'转换为'ascii // ignore // translit'。然后将空格变成破折号,将所有内容缩小写,等等。
回答
我们还可以使用此JavaScript函数以形式形式生成子弹(该子弹基于Django /从Django复制):
function makeSlug(urlString, filter) { // Changes, e.g., "Petty theft" to "petty_theft". // Remove all these words from the string before URLifying if(filter) { removelist = ["a", "an", "as", "at", "before", "but", "by", "for", "from", "is", "in", "into", "like", "of", "off", "on", "onto", "per", "since", "than", "the", "this", "that", "to", "up", "via", "het", "de", "een", "en", "with"]; } else { removelist = []; } s = urlString; r = new RegExp('\b(' + removelist.join('|') + ')\b', 'gi'); s = s.replace(r, ''); s = s.replace(/[^-\w\s]/g, ''); // Remove unneeded characters s = s.replace(/^\s+|\s+$/g, ''); // Trim leading/trailing spaces s = s.replace(/[-\s]+/g, '-'); // Convert spaces to hyphens s = s.toLowerCase(); // Convert to lowercase return s; // Trim to first num_chars characters }
回答
T-SQL实现,改编自dbo.UrlEncode:
CREATE FUNCTION dbo.Slug(@string varchar(1024)) RETURNS varchar(3072) AS BEGIN DECLARE @count int, @c char(1), @i int, @slug varchar(3072) SET @string = replace(lower(ltrim(rtrim(@string))),' ','-') SET @count = Len(@string) SET @i = 1 SET @slug = '' WHILE (@i <= @count) BEGIN SET @c = substring(@string, @i, 1) IF @c LIKE '[a-z0-9--]' SET @slug = @slug + @c SET @i = @i +1 END RETURN @slug END
回答
如果我们使用的是Rails edge,则可以依赖Inflector.parametrize,这是文档中的示例:
class Person def to_param "#{id}-#{name.parameterize}" end end @person = Person.find(1) # => #<Person id: 1, name: "Donald E. Knuth"> <%= link_to(@person.name, person_path(@person)) %> # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
另外,如果我们需要在早期版本的Rails中处理更多的异国字符,例如重音符号(phmre),则可以混合使用PermalinkFu和DiacriticsFu:
DiacriticsFu::escape("éphémère") => "ephemere" DiacriticsFu::escape("r?ksm?rg?s") => "raksmorgas"
回答
不不不。你们都非常错。除了变音符之类的东西外,我们到那里去了,但是亚洲字符呢(Ruby开发人员因为不考虑他们的nihonjin弟兄而感到羞耻)。
Firefox和Safari都在URL中显示非ASCII字符,坦率地说,它们看起来很棒。很高兴支持" http://somewhere.com/news/read/"之类的链接。
因此,这里有一些PHP代码可以做到这一点,但是我只是编写了它,并且没有对其进行压力测试。
<?php function slug($str) { $args = func_get_args(); array_filter($args); //remove blanks $slug = mb_strtolower(implode('-', $args)); $real_slug = ''; $hyphen = ''; foreach(SU::mb_str_split($slug) as $c) { if (strlen($c) > 1 && mb_strlen($c)===1) { $real_slug .= $hyphen . $c; $hyphen = ''; } else { switch($c) { case '&': $hyphen = $real_slug ? '-and-' : ''; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': $real_slug .= $hyphen . $c; $hyphen = ''; break; default: $hyphen = $hyphen ? $hyphen : ($real_slug ? '-' : ''); } } } return $real_slug; }
例子:
$str = "~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 コリン ~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 トーマス ~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 アーノルド ~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04"; echo slug($str);
输出:
-和-和-
"与"是因为&更改为"与"。