更改网址中的主机名

End*_*ing 41 python url

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

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

我想用"www.foo.dk"替换"www.google.dk",所以我得到以下网址:

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

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

Nig*_*nel 76

您可以使用urllib.parse.urlparse功能和ParseResult._replace方法:

>>> 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='')
Run Code Online (Sandbox Code Playgroud)

urllib.parse是一个子类,urlparse并且ParseResult是一种namedtuple方法:

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

更新:

正如@ 2rs2ts所说,在comment _replace属性中包含一个端口号.

好消息:namedtuplenetlocParseResult属性.坏消息:hostnameport不的成员hostname,他们的动态特性,你不能这样做port.它会抛出异常.

如果你不想分开namedtuple,你的网址总是有一个端口号而且没有(parsed._replace(hostname="www.foo.dk"):那个网址如" https:// username:password@www.google.dk:80/barbaz ")你可以做:

parsed._replace(netloc="{}:{}".format(parsed.hostname, parsed.port))
Run Code Online (Sandbox Code Playgroud)

  • `_replace`是`namedtuple`公共API的一部分.它只是以下划线开头,以避免与字段名称冲突. (31认同)
  • 使用私有方法`_replace`感觉不对. (8认同)
  • 注意 - `netloc` 还包括用户名和密码。如果您解析类似“https://user:hunter2@example.com:444/path”的内容,您的“netloc”将是“user:hunter2@example.com:444”。 (2认同)

lin*_*ndy 16

您可以充分利用urlsplit,并urlunsplit从Python的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'
Run Code Online (Sandbox Code Playgroud)

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


Omi*_*aha 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)
Run Code Online (Sandbox Code Playgroud)

输出:

https://www.google.dk:80/barbaz
https://www.foo.dk:80/barbaz
Run Code Online (Sandbox Code Playgroud)


小智 5

在大多数情况下,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'
Run Code Online (Sandbox Code Playgroud)

如果用户名或密码偶然与主机名匹配,这将不起作用。你不能限制 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'
Run Code Online (Sandbox Code Playgroud)

  • @gb:_replace 在 NamedTuple 中不是私有的。它是 API 的一部分:https://docs.python.org/2/library/collections.html#collections.namedtuple (5认同)

eLR*_*uLL 5

我也建议使用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'
Run Code Online (Sandbox Code Playgroud)