web-dev-qa-db-fra.com

Changer le nom d'hôte dans une URL

J'essaie d'utiliser python pour changer le nom d'hôte dans une URL, et je joue avec le module urlparse depuis un certain temps maintenant sans trouver de solution satisfaisante. Par exemple, considérez l'URL:

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

Je voudrais remplacer "www.google.dk" par ex. "www.foo.dk", j'obtiens donc l'url suivante:

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

Donc, la partie que je veux remplacer est ce que urlparse.urlsplit appelle le nom d'hôte. J'avais espéré que le résultat de urlsplit me permettrait d'apporter des modifications, mais le type résultant ParseResult ne me le permet pas. Si rien d'autre, je peux bien sûr reconstruire la nouvelle URL en ajoutant toutes les parties avec +, mais cela me laisserait un code assez laid avec beaucoup de conditions pour obtenir ": //" et ":" aux bons endroits .

39
Endling

Vous pouvez utiliser la fonction urllib.parse.urlparse et la méthode 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='')

Si vous utilisez Python 2, remplacez urllib.parse Par urlparse.

ParseResult est une sous-classe de namedtuple et _replace est une méthode namedtuple qui:

renvoie une nouvelle instance du Tuple nommé remplaçant les champs spécifiés par de nouvelles valeurs

[~ # ~] mise à jour [~ # ~] :

Comme l'a dit @ 2rs2ts dans l'attribut commentaire netloc comprend un numéro de port.

Bonne nouvelle: ParseResult possède les attributs hostname et port. Mauvaise nouvelle: hostname et port ne sont pas membres de namedtuple, ce sont des propriétés dynamiques et vous ne pouvez pas faire parsed._replace(hostname="www.foo.dk"). Ça va jeter une exception.

Si vous ne voulez pas diviser sur : Et que votre URL a toujours un numéro de port et n'a pas username et password (ce sont des URL comme " https: // nom d'utilisateur: [email protected]: 80/barbaz ") vous pouvez faire:

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

Vous pouvez profiter de urlsplit et urlunsplit de 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'

Comme l'indique la documentation, l'argument passé à urlunsplit() "peut être un élément à cinq éléments itérable", donc le code ci-dessus fonctionne comme prévu.

16
linkyndy

Utilisation des méthodes urlparse et urlunparse du module 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)

Production:

https://www.google.dk:80/barbaz
https://www.foo.dk:80/barbaz
5
Omid Raha

Je recommanderais également d'utiliser urlsplit et urlunsplit comme la réponse de @ linkyndy, mais pour Python3 ce serait:

>>> 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'
2
eLRuLL

Un simple remplacement de chaîne de l'hôte dans le netloc fonctionne également dans la plupart des cas:

>>> 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'

Cela ne fonctionnera pas si, par hasard, le nom d'utilisateur ou le mot de passe correspond au nom d'hôte. Vous ne pouvez pas limiter str.replace pour remplacer uniquement la dernière occurrence, nous pouvons donc utiliser le fractionnement et la jointure:

>>> p = urlparse.urlparse('https://www.google.dk:[email protected]:80/barbaz')
>>> new_netloc = 'www.foo.dk'.join(p.netloc.rsplit(p.hostname, 1))
>>> p._replace(netloc=new_netloc).geturl()
'https://www.google.dk:[email protected]:80/barbaz'
2
David Morley

Vous pouvez toujours faire cette astuce:

>>> 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'
1
Facundo Batista

Pour remplacer simplement l'hôte sans toucher au port utilisé (le cas échéant), utilisez ceci:

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)

impressions

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

Si vous n'avez donné aucun port, cela fonctionne aussi bien.

Si vous préférez le _replace comme Nigel l'a souligné, vous pouvez utiliser ceci à la place:

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