Python: décortiquer une URL à l'aide d'une regex

Cette regex permet de décortiquer une URL et de nommer les différents éléments.

regexp_url = "^(?i)\
(?P<proto>(http(s)*|ftp|ssh))\
(://)\
((?P<user>\w+)(:(?P<password>\w+))?@)?\
(?P<hostname>[\w\.-]+)\
(:(?P<port>[0-9]+))?\
(?P<path>.*)?\
$"

Je l'ai mise sur plusieurs lignes pour mieux la comprendre (d'où les '\' à chaque fin de ligne).

Sur la première ligne, le groupement (?i) permet d'indiquer que la regex doit être insensible à la casse.

La seconde ligne permet de parser et mémoriser le protocole utilisé (http/https/ftp/ssh).

La quatrième ligne permet de parser et mémoriser, si besoin, le user et le password.

La cinquième ligne permet de parser et mémoriser le hostname.

La sixième ligne permet de parser et mémoriser, si besoin, le port.

Pour terminer, la septième ligne permet de parser et mémoriser, si besoin, le path.

Le couple user:password est facultatif ainsi que le port et le path.

Quelques exemples

>>> import re
>>> from pprint import pprint
>>> regexp_url = "^(?i)\
(?P<proto>(http(s)*|ftp|ssh))\
(://)\
((?P<user>\w+)(:(?P<password>\w+))?@)?\
(?P<hostname>[\w\.-]+)\
(:(?P<port>[0-9]+))?\
/\
(?P<path>.*)?\
$"
>>> pprint(re.match(regexp_url, 'https://www.google.fr/').groupdict())
{'hostname': 'www.google.fr',
 'password': None,
 'path': '/',
 'port': None,
 'proto': 'https',
 'user': None}
>>> pprint(re.match(regexp_url, 'https://mail.google.com/mail/ca/u/0/#inbox').groupdict())
{'hostname': 'mail.google.com',
 'password': None,
 'path': '/mail/ca/u/0/#inbox',
 'port': None,
 'proto': 'https',
 'user': None}
>>> pprint(re.match(regexp_url, 'http://un-site:8080/greenhis/issues/14431').groupdict())
{'hostname': 'un-site',
 'password': None,
 'path': '/greenhis/issues/14431',
 'port': '8080',
 'proto': 'http',
 'user': None}
>>> pprint(re.match(regexp_url, 'https://docs.python.org/2/library/re.html#regular-expression-syntax').groupdict())
{'hostname': 'docs.python.org',
 'password': None,
 'path': '/2/library/re.html#regular-expression-syntax',
 'port': None,
 'proto': 'https',
 'user': None}
>>> pprint(re.match(regexp_url, 'ftp://toto:1234@ftpperso.free.fr/').groupdict())
{'hostname': 'ftpperso.free.fr',
 'password': '1234',
 'path': '/',
 'port': None,
 'proto': 'ftp',
 'user': 'toto'}
>>> pprint(re.match(regexp_url, 'ftp://toto:1234@ftpperso.free.fr:21/').groupdict())
{'hostname': 'ftpperso.free.fr',
 'password': '1234',
 'path': '/',
 'port': '21',
 'proto': 'ftp',
 'user': 'toto'}
>>> pprint(re.match(regexp_url, 'ftp://toto@ftpperso.free.fr:21/').groupdict())
{'hostname': 'ftpperso.free.fr',
 'password': None,
 'path': '/',
 'port': '21',
 'proto': 'ftp',
 'user': 'toto'}
>>>

Penser à partager vos améliorations si besoin.

Les fonctions urlparse et urlsplit de la classe parse du module urllib permettent aproximativement de faire la même chose

>>> import urllib
>>> urllib.parse.urlparse('http://un-site:8080/greenhis/issues/14431')
ParseResult(scheme='http', netloc='un-site:8080', path='/greenhis/issues/14431', params='', query='', fragment='')
>>> urllib.parse.urlparse('ftp://toto:1234@ftpperso.free.fr:21/')
ParseResult(scheme='ftp', netloc='toto:1234@ftpperso.free.fr:21', path='/', params='', query='', fragment='')
>>> urllib.parse.urlsplit('ftp://toto:1234@ftpperso.free.fr:21/')
SplitResult(scheme='ftp', netloc='toto:1234@ftpperso.free.fr:21', path='/', query='', fragment='')

 

Commentaires

Bonjour, et merci pour ce partage très utile.
Je suis juste étonné que le slash de début de chemin ne fasse pas partie de la variable path. Est-ce parce qu'il sert de délimiteur après le host[:port] ?

Bonjour,

Effectivement, j'ai fait en sorte de ne pas le prendre en compte volontairement mais il est tout à fait possible de l'inclure dans la clé 'path' en supprimant de la regex la septième ligne contenant les deux caractères '/\'

J'en profite pour mettre à jour l'article.

Ajouter un commentaire

Filtered HTML

  • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.
  • Tags HTML autorisés : <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Les lignes et les paragraphes vont à la ligne automatiquement.

Plain text

  • Aucune balise HTML autorisée.
  • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.
  • Les lignes et les paragraphes vont à la ligne automatiquement.
CAPTCHA
Cette question permet de s'assurer que vous êtes un utilisateur humain et non un logiciel automatisé de pollupostage.
CAPTCHA visuel
Entrez les caractères (sans espace) affichés dans l'image.