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