更改网址中的主机名

时间:2014-02-07 13:20:43

标签: python url

我正在尝试使用python来更改url中的主机名,并且已经在使用urlparse模块一段时间而没有找到满意的解决方案。例如,请考虑网址:

https://www.google.dk:80/barbaz

我想将“www.google.dk”替换为“www.google.dk”。 “www.foo.dk”,所以我得到以下网址:

https://www.foo.dk:80/barbaz

所以我要替换的部分是urlparse.urlsplit所指的主机名。我曾希望urlsplit的结果会让我进行更改,但结果类型ParseResult不允许我这样做。如果没有别的我当然可以通过将所有部分与+一起附加来重建新的url,但是这会给我留下一些非常丑陋的代码以及很多条件,以便在正确的位置获得“://”和“:”

7 个答案:

答案 0 :(得分:69)

您可以使用urllib.parse.urlparse函数和ParseResult._replace方法(Python 3):

>>> import urllib.parse
>>> parsed = urllib.parse.urlparse("https://www.google.dk:80/barbaz")
>>> replaced = parsed._replace(netloc="www.foo.dk:80")
>>> print(replaced)
ParseResult(scheme='https', netloc='www.foo.dk:80', path='/barbaz', params='', query='', fragment='')

如果您使用的是Python 2,请将urllib.parse替换为urlparse

ParseResultnamedtuple的子类,_replacenamedtuple方法:

  

返回指定元组的新实例,替换指定的字段   新值

<强>更新

正如@ 2rs2ts在评论中所说netloc属性包含一个端口号。

好消息:ParseResult具有hostnameport属性。 坏消息:hostnameport不是namedtuple的成员,它们是动态属性,您无法parsed._replace(hostname="www.foo.dk")。它会抛出异常。

如果您不希望在:上拆分,并且您的网址始终有一个端口号,而且没有usernamepassword(这就是“{{3} })你可以这样做:

parsed._replace(netloc="{}:{}".format(parsed.hostname, parsed.port))

答案 1 :(得分:15)

您可以利用Python urlsplit中的urlunspliturlparse

>>> from urlparse import urlsplit, urlunsplit
>>> url = list(urlsplit('https://www.google.dk:80/barbaz'))
>>> url
['https', 'www.google.dk:80', '/barbaz', '', '']
>>> url[1] = 'www.foo.dk:80'
>>> new_url = urlunsplit(url)
>>> new_url
'https://www.foo.dk:80/barbaz'

正如文档所述,传递给urlunsplit()“的参数可以是任何五项可迭代的”,因此上面的代码按预期工作。

答案 2 :(得分:5)

使用urlparse模块的urlunparseurlparse方法:

import urlparse

old_url = 'https://www.google.dk:80/barbaz'
url_lst = list(urlparse.urlparse(old_url))
# Now url_lst is ['https', 'www.google.dk:80', '/barbaz', '', '', '']
url_lst[1] = 'www.foo.dk:80'
# Now url_lst is ['https', 'www.foo.dk:80', '/barbaz', '', '', '']
new_url = urlparse.urlunparse(url_lst)

print(old_url)
print(new_url)

输出:

https://www.google.dk:80/barbaz
https://www.foo.dk:80/barbaz

答案 3 :(得分:2)

在大多数情况下,netloc中主机的简单字符串替换也适用:

>>> p = urlparse.urlparse('https://www.google.dk:80/barbaz')
>>> p._replace(netloc=p.netloc.replace(p.hostname, 'www.foo.dk')).geturl()
'https://www.foo.dk:80/barbaz'

如果用户名或密码与主机名匹配,则无效。您不能将str.replace限制为仅替换最后一个匹配项,因此我们可以使用split和join:

>>> p = urlparse.urlparse('https://www.google.dk:www.google.dk@www.google.dk:80/barbaz')
>>> new_netloc = 'www.foo.dk'.join(p.netloc.rsplit(p.hostname, 1))
>>> p._replace(netloc=new_netloc).geturl()
'https://www.google.dk:www.google.dk@www.foo.dk:80/barbaz'

答案 4 :(得分:2)

我建议您使用urlspliturlunsplit,例如@ linkyndy的答案,但对于 Python3 ,它会是:

>>> from urllib.parse import urlsplit, urlunsplit
>>> url = list(urlsplit('https://www.google.dk:80/barbaz'))
>>> url
['https', 'www.google.dk:80', '/barbaz', '', '']
>>> url[1] = 'www.foo.dk:80'
>>> new_url = urlunsplit(url)
>>> new_url
'https://www.foo.dk:80/barbaz'

答案 5 :(得分:1)

您总是可以做到这一点:

>>> p = parse.urlparse("https://stackoverflow.com/questions/21628852/changing-hostname-in-a-url")
>>> parse.ParseResult(**dict(p._asdict(), netloc='perrito.com.ar')).geturl()
'https://perrito.com.ar/questions/21628852/changing-hostname-in-a-url'

答案 6 :(得分:0)

要在不触及正在使用的端口(如果有)的情况下更换主机,请使用:

import re, urlparse

p = list(urlparse.urlsplit('https://www.google.dk:80/barbaz'))
p[1] = re.sub('^[^:]*', 'www.foo.dk', p[1])
print urlparse.urlunsplit(p)

打印

https://www.foo.dk:80/barbaz

如果您没有提供任何端口,这也可以。

如果你更喜欢Nigel指出的_replace方式,你可以改用它:

p = urlparse.urlsplit('https://www.google.dk:80/barbaz')
p = p._replace(netloc=re.sub('^[^:]*', 'www.foo.dk', p.netloc))
print urlparse.urlunsplit(p)