我需要解析一个URL。我目前正在使用urlparse.ulparse()和urlparse.wurlsplit().
问题是,当"netloc"(主机)不存在该方案时,我无法从URL中获取它。我的意思是,如果我有以下网址:
www.amazon.com/Programming Python Mark Lutz/dp/0596158106/ref=sr_1_1?ie=UTF8&qid=1308060974&sr=8-1
我无法获取netloc:amazon.com
根据python文档:
遵循中的语法规范RFC 1808,urlparse识别netloc只有由"//"。否则,假定输入作为相对URL,从而开始带有路径组件。
所以,这是故意的。但是,我仍然不知道如何从那个URL获取netloc。
我想我可以检查这个方案是否存在,如果不存在,那么添加它,然后解析它。但这个解决方案似乎并不好。
你有更好的主意吗?
编辑:谢谢你的回答。但是,我不能做科里和其他人提出的"启动"的事情。Becuse,如果我得到一个带有其他协议/方案的URL,我会把它搞砸的。参见:
如果我得到这个网址:
ftp://something.com
有了建议的代码,我会在开头添加"http://",然后把它搞砸。
我找到的解决方案
if not urlparse.urlparse(url).scheme:
url = "http://"+url
return urlparse.urlparse(url)
需要注意的事项:
我先做一些验证,如果没有给出方案,我认为它是http://
看起来需要指定获取netloc的协议。
如果它不存在,添加它可能看起来像这样:
import urlparse
url = 'www.amazon.com/Programming-Python-Mark-Lutz'
if '//' not in url:
url = '%s%s' % ('http://', url)
p = urlparse.urlparse(url)
print p.netloc
有关该问题的详细信息:https://bugs.python.org/issue754016
文档中有这个确切的例子,就在粘贴的文本下面。如果没有添加"//",则会得到您想要的内容。如果你不知道它是否有协议和"//",你可以使用正则表达式(甚至只是看看它是否已经包含"//")来确定是否需要添加它。
你的另一个选择是使用split("/")并获取它返回的列表的第一个元素,这只有在url没有协议或"//"时才有效。
EDIT(为将来的读者添加):用于检测协议的正则表达式类似于re.match('(?:http|ftp|https)://', url)
如果协议是始终http,则只能使用一行:
return "http://" + url.split("://")[-1]
更好的选择是如果协议通过,则使用该协议:
return url if "://" in url else "http://" + url
来自文档:
根据RFC 1808中的语法规范,urlparse只有在"//"正确引入netloc时才能识别它。否则,输入被假定为相对URL,并因此以路径组件开始。
所以你可以做:
In [1]: from urlparse import urlparse
In [2]: def get_netloc(u):
...: if not u.startswith('http'):
...: u = '//' + u
...: return urlparse(u).netloc
...:
In [3]: get_netloc('www.amazon.com/Programming-Python-Mark-Lutz/dp/0596158106/ref=sr_1_1?ie=UTF8&qid=1308060974&sr=8-1')
Out[3]: 'www.amazon.com'
In [4]: get_netloc('http://www.amazon.com/Programming-Python-Mark-Lutz/dp/0596158106/ref=sr_1_1?ie=UTF8&qid=1308060974&sr=8-1')
Out[4]: 'www.amazon.com'
In [5]: get_netloc('https://www.amazon.com/Programming-Python-Mark-Lutz/dp/0596158106/ref=sr_1_1?ie=UTF8&qid=1308060974&sr=8-1')
Out[5]: 'www.amazon.com'
您是否考虑过只检查url开头是否存在"http://",如果不存在则添加它?另一个解决方案是,假设第一部分实际上是netloc,而不是相对url的一部分,那么只需获取第一个"/"之前的所有内容,并将其用作netloc。
这一行就可以了。
netloc = urlparse('//' + ''.join(urlparse(url)[1:])).netloc