我正在尝试使用python来更改url中的主机名,并且已经在使用urlparse模块一段时间而没有找到满意的解决方案。例如,请考虑网址:
https://www.google.dk:80/barbaz
我想将“www.google.dk”替换为“www.google.dk”。 “www.foo.dk”,所以我得到以下网址:
所以我要替换的部分是urlparse.urlsplit所指的主机名。我曾希望urlsplit的结果会让我进行更改,但结果类型ParseResult不允许我这样做。如果没有别的我当然可以通过将所有部分与+一起附加来重建新的url,但是这会给我留下一些非常丑陋的代码以及很多条件,以便在正确的位置获得“://”和“:”
答案 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
。
ParseResult
是namedtuple
的子类,_replace
是namedtuple
方法:
返回指定元组的新实例,替换指定的字段 新值
<强>更新强>:
正如@ 2rs2ts在评论中所说netloc
属性包含一个端口号。
好消息:ParseResult
具有hostname
和port
属性。
坏消息:hostname
和port
不是namedtuple
的成员,它们是动态属性,您无法parsed._replace(hostname="www.foo.dk")
。它会抛出异常。
如果您不希望在:
上拆分,并且您的网址始终有一个端口号,而且没有username
和password
(这就是“{{3} })你可以这样做:
parsed._replace(netloc="{}:{}".format(parsed.hostname, parsed.port))
答案 1 :(得分:15)
您可以利用Python urlsplit
中的urlunsplit
和urlparse
:
>>> 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
模块的urlunparse
和urlparse
方法:
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)
我建议您使用urlsplit
和urlunsplit
,例如@ 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)