如何解析网址?
Posted
技术标签:
【中文标题】如何解析网址?【英文标题】:How to parse a URL? 【发布时间】:2011-09-04 07:48:54 【问题描述】:如果有一件事我无法理解,那就是正则表达式。
所以经过大量搜索,我终于找到了适合我需要的这个:
function get_domain_name()
aaaa="http://www.somesite.se/blah/sdgsdgsdgs";
//aaaa="http://somesite.se/blah/sese";
domain_name_parts = aaaa.match(/:\/\/(.[^/]+)/)[1].split('.');
if(domain_name_parts.length >= 3)
domain_name_parts[0] = '';
var domain = domain_name_parts.join('.');
if(domain.indexOf('.') == 0)
alert("1"+ domain.substr(1));
else
alert("2"+ domain);
它基本上把域名还给我了,反正我也可以得到域名后面的所有东西吗?在这种情况下,它将是来自aaaa
变量的/blah/sdgsdgsdgs
。
【问题讨论】:
学习正则表达式的好资源:regular-expressions.info 所以你想要的是路径,而不是域? 【参考方案1】:编辑 (2020):在现代浏览器中,您可以使用内置的 URL
Web API。
https://developer.mozilla.org/en-US/docs/Web/API/URL/URL
var url = new URL("http://www.somesite.se/blah/sdgsdgsdgs");
var pathname = url.pathname; // returns /blah/sdgsdgsdgs
您应该使用 javascript DOM API 提供的内置 URL 解析器,而不是依赖可能不可靠的*正则表达式:
var url = document.createElement('a');
url.href = "http://www.example.com/some/path?name=value#anchor";
这就是解析 URL 所需要做的一切。其他一切都只是访问解析的值:
url.protocol; //(http:)
url.hostname; //(www.example.com)
url.pathname; //(/some/path)
url.search; // (?name=value)
url.hash; //(#anchor)
在这种情况下,如果您正在寻找 /blah/sdgsdgsdgs
,您可以使用 url.pathname
访问它
基本上,您只是在 JavaScript 中创建一个链接(技术上是锚元素),然后您可以直接调用已解析的片段。 (因为您没有将它添加到 DOM,所以它不会在任何地方添加任何不可见的链接。)它的访问方式与 location
对象上的值相同。
(灵感来自this wonderful answer。)
编辑:重要说明:Internet Explorer 似乎有一个错误,它省略了此类对象的 pathname
属性上的前导斜杠。您可以通过执行以下操作对其进行规范化:
url.pathname = url.pathname.replace(/(^\/?)/,"/");
注意: *:我说“可能不可靠”,因为尝试构建或找到一个包罗万象的 URL 解析器可能很诱人,但是有很多很多的条件、边缘情况和宽容的解析技术可能没有被考虑或适当支持;浏览器可能最擅长实现这个逻辑(因为解析 URL 对它们的正确操作至关重要),所以我们应该保持简单并留给它们。
【讨论】:
一个有价值的脚注:我发现这不是一个好方法的唯一一次是如果您要解析大量链接; DOM 元素的创建比正则表达式更昂贵。在少数情况下,差异是无法区分的。在 100+ 时,它可以产生明显的效果。 关于规范化pathname
的好电话!您确定重新分配标准化的pathname
没有副作用吗?另外,我可以建议从正则表达式中删除 ()
吗?
把这个工作交给浏览器就像:我希望浏览器能正确地完成它......就像你提到的那样,IE错误可能是一个问题
JavaScript DOM 绑定标准是否涵盖了该代码? - 我还没找到。【参考方案2】:
RFC(见附录 B)提供了一个正则表达式来解析 URI 部分:
^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
12 3 4 5 6 7 8 9
在哪里
scheme = $2
authority = $4
path = $5
query = $7
fragment = $9
例子:
function parse_url(url)
var pattern = RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
var matches = url.match(pattern);
return
scheme: matches[2],
authority: matches[4],
path: matches[5],
query: matches[7],
fragment: matches[9]
;
console.log(parse_url("http://www.somesite.se/blah/sdgsdgsdgs"));
给予
Object
authority: "www.somesite.se"
fragment: undefined
path: "/blah/sdgsdgsdgs"
query: undefined
scheme: "http"
DEMO
【讨论】:
您可以通过使用非捕获组来增强正则表达式。 我认为我必须正确学习正则表达式才能理解你的帖子,尽管我相信它非常有帮助。 使用非捕获组:"^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(\\?(?:[^#]*))?(#(?:.*))?"
。仅返回方案、主机、路径、查询和片段。注意:://
不是方案的一部分,因为方案实际上可以省略。
这是涂料!感谢您链接 RFC。真正的英雄,那些作者。
另外我要补充的是,如何获取当前 URI:document.URL
以及如何解析查询:***.com/a/2091331/1069083【参考方案3】:
请注意,此解决方案不是最好的。我这样做只是为了满足 OP 的要求。我个人建议查看其他答案。
以下正则表达式将返回域和其余部分。 :\/\/(.[^\/]+)(.*)
:
-
www.google.com
/gosomething
我建议你在这里学习 RegExp 文档:http://www.regular-expressions.info/reference.html
使用你的函数:
function get_domain_name()
aaaa="http://www.somesite.se/blah/sdgsdgsdgs";
//aaaa="http://somesite.se/blah/sese";
var matches = aaaa.match(/:\/\/(?:www\.)?(.[^/]+)(.*)/);
alert(matches[1]);
alert(matches[2]);
【讨论】:
可以提醒(matches[1]);不带“www.”返回?警报(匹配[2]);是完美的!并感谢您的链接。 正是我所要求的,特别感谢! (感谢所有回复的人!) @kuroir 你不能将“接受”的解决方案重新设置为得票最多的解决方案吗?我很确定你可以做到这一点......【参考方案4】:您只需要稍微修改一下您的正则表达式。例如:
var aaaa="http://www.somesite.se/blah/sdgsdgsdgs";
var m = aaaa.match(/^[^:]*:\/\/([^\/]+)(\/.*)$/);
m 将包含以下部分:
["http://www.somesite.se/blah/sdgsdgsdgs", "www.somesite.se", "/blah/sdgsdgsdgs"]
这是相同的示例,但经过修改后将“www”分开。部分。我认为应该编写正则表达式,以便无论您是否拥有“www”,匹配都会起作用。部分。所以看看这个:
var aaaa="http://www.somesite.se/blah/sdgsdgsdgs";
var m = aaaa.match(/^[^:]*:\/\/(www\.)?([^\/]+)(\/.*)$/);
m 将包含以下部分:
["http://www.somesite.se/blah/sdgsdgsdgs", "www.", "somesite.se", "/blah/sdgsdgsdgs"]
现在检查相同的正则表达式,但网址不以“www.”开头:
var bbbb="http://somesite.se/blah/sdgsdgsdgs";
var m = .match(/^[^:]*:\/\/(www\.)?([^\/]+)(\/.*)$/);
现在你的比赛看起来像这样:
["http://somesite.se/blah/sdgsdgsdgs", undefined, "somesite.se", "/blah/sdgsdgsdgs"]
所以你可以看到它在这两种情况下都会做正确的事情。
【讨论】:
嘿!感谢回复!不,我需要第二部分没有“www”。和原版一模一样。就像你上面写的第二部分。谢谢! 编辑;我的意思是:不,我需要第二部分没有“www”。和原版一模一样。像你上面写的第三部分是完美的。谢谢!【参考方案5】:有一个很好的用于解析 URL 的 jQuery 插件:Purl。
所有正则表达式的东西都隐藏在里面,你会得到类似的东西:
> url = $.url("http://markdown.com/awesome/language/markdown.html?show=all#top");
> url.attr('source');
"http://markdown.com/awesome/language/markdown.html?show=all#top"
> url.attr('protocol');
"http"
> url.attr('host');
"markdown.com"
> url.attr('relative');
"/awesome/language/markdown.html?show=all#top"
> url.attr('path');
"/awesome/language/markdown.html"
> url.attr('directory');
"/awesome/language/"
> url.attr('file');
"markdown.html"
> url.attr('query');
"show=all"
> url.attr('fragment');
"top"
【讨论】:
【参考方案6】:自从第一次提出这个问题以来,浏览器已经走了很长一段路。您现在可以使用原生的URL 接口来完成此操作:
const url = new URL('http://www.somesite.se/blah/sdgsdgsdgs')
console.log(url.host) // "www.somesite.se"
console.log(url.href) // "http://www.somesite.se/blah/sdgsdgsdgs"
console.log(url.origin) // "http://www.somesite.se"
console.log(url.pathname) // "/blah/sdgsdgsdgs"
console.log(url.protocol) // "http:"
// etc.
请注意,IE 不支持此 API。但是,您可以使用 polyfill.io 轻松地对其进行 polyfill:
<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js?flags=gated&features=URL"></script>
【讨论】:
我很惊讶这个答案还没有收到任何赞成票!它值得更多!以上是关于如何解析网址?的主要内容,如果未能解决你的问题,请参考以下文章