将URL转换为一种标准格式

时间:2018-08-04 13:00:59

标签: php url

以下是一些URL:

http://sub.example.com/?feed=atom&hello=world
http://www.sub.example.com/?feed=atom&hello=world
http://sub.example.com/?hello=world&feed=atom
http://www.sub.example.com/?hello=world&feed=atom
http://www.sub.example.com/?hello=world&feed=atom
http://www.sub.example.com/?hello=world&feed=atom#123

如您所见,它们全都指向相同的页面,但URL格式不同。这是另外两个基本示例:

http://example.com/hello/
http://example.com/hello

两者都一样。

我想将URL 转换一种标准格式,以便在将URL存储在数据库中时,可以轻松地检查URL字符串是否已存在于数据库中。数据库。

由于可以采用多种方式设置URL的格式,这令人感到困惑。

将URL转换为一种标准格式的确定性方法是什么?也许parse_url()路线...?

编辑

如评论中所概述的,没有针对此问题的确定性解决方案,但目的是在不“检索” 情况下尽可能接近我们拥有的页。在发布赏金答案之前,请先阅读评论。

9 个答案:

答案 0 :(得分:1)

parse_url之后,

  1. 域名
  2. 中删除www前缀
  3. 如果路径不为空,请从其末尾删除斜杠
  4. 按查询名称的字母顺序对它们进行排序-如果有的话

组合这些部分以获得规范的URL。

答案 1 :(得分:1)

我对报告配置保存功能有同样的问题。在我们的系统中,用户可以设计自己的销售报告(例如Jira的JQL);为此,我们使用get params作为条件,并使用片段标识符(在#之后)作为布局设置,如下所示:

http://example.com/report.php?since=20180101&until=20180806#sort=amount&color=blue

对于我们的系统,如果先将参数设置为“直到”而不是“开始”,则获取参数或#参数之后的顺序也无关紧要,因此对我们来说是相同的请求。

考虑到这一点,子域不在讨论之列,因为您必须使用重写技术(例如Apache中的301的mod_rewrite)来解决此问题,或者创建域异常池以在软件级别执行此操作。另外,不同的域可以指向不同的网站,因此您必须确定是否是一个好主意;在subdos中,“ www”很容易找出来,但是在其他情况下,它将浪费您时间。

服务器端可以帮助在查询部分获取变量。例如,在PHP中,您可以使用函数parse_str和$ _SERVER ['QUERY_STRING']获取数组,然后,您将需要使用asort()命令对其进行最终比较,以比较是否有相同的请求(array_diff函数)。

不幸的是,服务器端不是一种选择,因为它无法获取哈希(#)内容,而且我们仍然没有考虑其他问题,例如包含的脚本名,协议或端口:

http://www.sub.example.com/index.php?hello=world&feed=atom
https://www.sub.example.com/?hello=world&feed=atom
http://www.sub.example.com:8081/?hello=world&feed=atom

以我个人的经验,最接近的解决方案是JavaScript,用于处理url,将查询部分解析为数组,对其进行比较并使用片段标识符进行相同的操作。如果需要在服务器端使用它,则必须在每个加载页面后跟随一个ajax请求,以将该数据发送到服务器。

对于我的回答长度,我们事先表示歉意,但这是我必须解决的同样问题。问候!

从URL获取协议,域和端口 Get protocol, domain, and port from URL

如何获取JavaScript中的查询字符串值? How can I get query string values in JavaScript?

如何从URL获取片段标识符(哈希号后的值)? How do I get the fragment identifier (value after hash #) from a URL?

答案 2 :(得分:1)

将首选的<link rel="canonical" ... >标签添加到HTML标头中是唯一可靠的解决方案,以便将唯一的内容引用到单个SEF URL中。请参阅Google关于Consolidate duplicate URLs的文档,该文档可能比我以往所能回答的问题更加自动和可靠。

在不解析服务器的.htaccess重写规则或HTML标头的情况下,能够知道规范URL或解析一堆外部URL的想法似乎并不适用(原因是因为维护一个带有URL别名的表,该别名随后不允许猜测如何重写HTTP请求。

这个问题可能属于https://webmasters.stackexchange.com/search?q=cannonical

答案 3 :(得分:1)

由于问题被标记为“ PHP”,因此我假设您在后端。

您有足够的答案可以比较 URL (协议,主机,端口,路径,请求参数列表),其中路径区分大小写,协议和主机不区分大小写。严格来说,更改请求参数的顺序也会更改URL。

我的印象是,您希望通过服务器所服务的 RESOURCE 来区分(http://www.sub.example.com/http://sub.example.com/服务相同的资源,或者... / hello服务于服务器与... / hello /)相同的资源

提供哪些资源,您应该完全了解后端级别,因为您(后端)知道您正在提供什么。找到该资源的完美ID并使用它。

PS:URL并不是一个好的标识符。但是,如果您必须使用它,只需使用经过清理的版本(出于您的目的进行清理=>清理到您首选的主机,在路径末尾去除或添加斜杠,从路径中删除/../之类的东西(无论如何安全性问题),不管您的目的是什么,请求参数都以特定顺序排列。

最好的问候,iPirat

答案 4 :(得分:1)

使用重复的URL就是这种情况,您可以通过使用URL工厂将所有不合适的URL重定向到正确的URL来避免这种重复的URL。

这篇文章也解释了同样的事情:

https://www.tinywebhut.com/remove-duplicate-urls-from-your-website-38

指向同一页面的所有其他URL都被重定向到301的正确版本。

这是搜索引擎优化(SEO)的最佳做法。在这里,我将给您提供一些示例。

您可以考虑此网站的URL,例如此页面的错误链接

https://stackoverflow.com/questions/51685850
https://stackoverflow.com/questions/51685850/convert-url-into-one-s
https://stackoverflow.com/questions/51685850/

如果您转到此页面的上述错误网址,您将被重定向到正确的网址,即

https://stackoverflow.com/questions/51685850/convert-url-into-one-standard-format

如果您更改了此问题的标题,则所有其他URL都将被重定向到301,以正确的URL。这里的想法是301重定向,它告诉搜索引擎用新的URL替换旧的URL,否则搜索引擎会找到提供相同内容的不同URL。

这里真正的问题是问题的编号51685850。该ID用于根据数据库中的信息创建正确的URL。使用提供的链接中的文章中创建的URL工厂,您甚至不需要将URL存储在数据库中。

您可以在此处阅读有关重复内容的更多信息:

https://moz.com/learn/seo/duplicate-content

同样的规则也适用于tinywebhut.com,错误的URL是

https://www.tinywebhut.com/remove-duplicate-38
https://www.tinywebhut.com/some-text-38
https://www.tinywebhut.com/remove-duplicate-urls-from-your-website-38/

在上述URL中,ID附加到URL的末尾38,并且如果您转到这些URL中的任何一个,您将被重定向到301的正确版本,即< / p>

https://www.tinywebhut.com/remove-duplicate-urls-from-your-website-38

由于本文已经完成了此操作,因此我没有做任何功能来解释这一点:

https://www.tinywebhut.com/remove-duplicate-urls-from-your-website-38

您可以通过几个非常简单的功能实现目标,并且可以应用相同的想法删除其他重复的URL,例如/about.php/about/about.php/,{{1 }} 等等。为此,您只需要为现有功能添加一些代码即可。

一种替代方法是添加规范标记,例如,即使您有多个URL可以访问同一页面,您也只需应用规范标记并将链接添加到正确的URL。

/about/

通过这种方式,您告诉搜索引擎应该将多个URL视为一个,并且搜索引擎会在其搜索结果中添加规范标记中使用的链接。您可以在此处阅读有关规范化的更多信息:

https://moz.com/learn/seo/canonicalization

但摆脱重复内容的最佳方法仍然是301重定向。如果您像我一开始所说的那样进行了301重定向,那么所有问题都会得到解决,而不会感到意外。

答案 5 :(得分:1)

我的原始答案假设页面都归OP所有,如“您所看到的,它们都指向完全相同的页面,但URL格式不同...”这一行。我正在调整答案以处理多个选项,并添加了您可以对URL做出的假设以及对URL不能做出的假设的列表。

正如其他人指出的那样,如果您不知道页面相同,则没有明确的简单答案。但是,如果遵循这些假设,则应该安全地标准化一些内容:

CAN ASSUME

  • 具有相同值的查询字符串指向相同位置,而不管顺序如何。示例:https://example.com/?fruit=apple&color=redhttps://example.com/?color=red&fruit=apple

  • 可以遵循
  • 301重定向到特定来源。如果您收到301重定向响应,请遵循重定向并使用该URL。您可以放心地假设,如果URL实际上确实指向同一页面,并且页面排名得到了优化,那么您可以关注它。

  • 如果HTML中只有一个<link rel="canonical">标签,那么该标签也可以用于覆盖规范链接(原因请参见下文)。

无法假设

如果您拥有该网站

以所需的URL格式的第一部分重定向所有流量:是否要www.example.comexample.comsub.example.com?是否要使用斜杠?首先使用服务器规则或PHP进行重定向。这对于搜索页面排名(如果对您而言很重要)也非常有用。

例如:

if (!$_SERVER['HTTPS'] || 'example.com' !== $_SERVER['HTTP_HOST'] || rtrim($_SERVER['PHP_SELF'], '/') !== $_SERVER['PHP_SELF']) {
    header('HTTP/1.1 301 Moved Permanently'); 
    header('Location: '. 'https://example.com/'.rtrim($_SERVER['PHP_SELF']), '/'));
    exit;
}

最后,要管理所有其他SEO问题,您可以添加以下HTML标签:

`<link rel="canonical" href="<?php echo $url; ?>">`

无论您是否拥有网站,都可以标准化查询顺序

即使您不控制站点,也可以假定查询顺序无关紧要。为了对此进行标准化,请查询并重建参数,然后将其附加到规范化的URL。

function getSortedQuery() 
{
    $url = [];
    parse_str($_SERVER['QUERY_STRING'], $url);
    ksort($url);
    return http_build_query($url);
}

$url = $_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?'.getSortedQuery();

另一种选择是获取页面内容,查看是否有<link rel="canonical">字符串,然后使用该字符串记录数据。这会花费更多,因为它需要整个页面加载。

要重复一遍,请确保获取301重定向,因为它们不是建议,而是关于最终结果URL的指令。

一个最终建议

我可能建议使用两列,一列是“ canonical_url”,另一列是“ effective_url”。有时,URL有效,然后在以后变为301重定向。这只是我的看法,但我想知道这些事情。

答案 6 :(得分:1)

所有答案都有重要信息。假设您使用的是类似Apache的服务器,对于URL位,我将使用.htaccess(或者,最好是,如果您可以更改-等效的服务器Apache配置文件)来进行重写。举个简单的例子:

RewriteEngine on
RewriteBase /

RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteRule (.*) http://example.com/$1 [R=Permanent]

在此示例中,“ R=Permanent”确实进行了重定向。这通常不是什么大问题,因为a)它告诉浏览器记住重定向,并且b)您的内部链接可能是相对的,因此协议(http或https)和服务器(example.com或其他)都得以保留。因此,通常,重定向将是每个会话一次或更短的时间-IMO为了避免在PHP中完成所有这些操作花了很长时间。

我想您也可以用它来重写查询位的顺序,尽管当查询位很重要时,我倾向于(不建议您这样做,只是说')将它们添加到我的路径中(例如,重写“ .../blah/atom”到“ .../blah.php?feed=atom”)。无论如何,都有大量的重写技巧,我建议您在中阅读它们。  Apache mod_rewrite

如果您确实选择了这种方法,请务必仔细考虑您要发生的事情-一旦开始使用URL进行处理,通常就会长时间停留在您的决策中。

答案 7 :(得分:0)

正如一些人指出的那样,尽管您显示的URL当前可能指向相同的内容,但无法确定将来是否会出现。协议或主机名的更改都可以为您提供不同的内容集,即使example.comwww.example.com,即使由同一IP的同一台计算机提供服务也是如此。虽然不常见,但可能会发生...

因此,如果我要维护URL列表,则将存储协议,主机名,目录路径,文件名(如果存在)(也就是“在问号前的最后一个斜杠之后出现的所有内容”),并按GET参数的键/值对

然后不要忘记,您可以转到https://www.google.com,但不带任何协议和主机名...

答案 8 :(得分:-1)

避免在url中传递参数。使用JSON将参数传递到网页。