À l'ère d'Internet, l'URL (Uniform Resource Locator) est l'adresse de base qui indique l'emplacement d'une information. Dans divers domaines tels que le développement web ou l'analyse de données, il est souvent nécessaire de travailler avec des URL, parfois en extrayant uniquement certaines parties (ex : domaine, chemin, paramètres de requête) plutôt que l'URL entière. C'est là que la fonction urlparse() du module urllib.parse s'avère un outil puissant.

Dans cet article, nous allons explorer l'utilisation de base de la fonction urlparse(), la signification et les cas d'utilisation de la propriété .netloc, ainsi que les diverses propriétés de l'objet ParseResult qu'elle retourne.


1. Qu'est-ce que urlparse() ?



urlparse() est une fonction qui divise une chaîne d'URL selon les normes RFC 1738 (Universal Resource Locators in WWW) et RFC 3986 (Uniform Resource Identifier (URI): Generic Syntax) en plusieurs composants. Chacun de ces composants est renvoyé dans un objet spécial appelé ParseResult.

Utilisation de base

La fonction urlparse() s'utilise en l'importnant depuis le module urllib.parse.

from urllib.parse import urlparse

url = 'https://user:pass@www.example.com:8080/path/to/resource?name=Alice&age=30#section1'
parsed_url = urlparse(url)

print(parsed_url)
# Sortie : ParseResult(scheme='https', netloc='user:pass@www.example.com:8080', path='/path/to/resource', params='', query='name=Alice&age=30', fragment='section1')

L'objet parsed_url peut être accessible à la fois par index comme un tuple et par les propriétés nommées (named attribute). La seconde méthode est beaucoup plus lisible.


2. Propriétés principales de l'objet ParseResult

L'objet ParseResult retourné par urlparse() a les propriétés suivantes.

scheme

  • Signification : Représente la partie protocole de l'URL. (http, https, ftp, mailto, etc.)

  • Exemple : 'https'

netloc (localisation réseau)

  • Signification : Inclut le nom d'hôte (domaine), le numéro de port, et éventuellement les informations d'authentification de l'utilisateur (user:pass@).

  • Exemple : 'user:pass@www.example.com:8080'

  • Utilisation : Utile pour extraire uniquement le domaine d'un service web spécifique ou pour vérifier le numéro de port pour la connexion réseau. Nous traiterons cela plus en détail par la suite.

path

  • Signification : Représente le chemin vers une ressource spécifique sur le serveur web.

  • Exemple : '/path/to/resource'

params (paramètres de chemin)

  • Signification : Paramètres de chemin séparés par un point-virgule (;). Bien que définis par la RFC, ils ne sont presque pas utilisés dans le web moderne, où principalement des requêtes (query) sont utilisées.

  • Exemple : ';sessionid=xyz' (rarement utilisé)

query

  • Signification : Chaîne de requête qui suit un point d'interrogation (?). Utilisée pour transmettre des données au serveur sous forme de paires clé-valeur.

  • Exemple : 'name=Alice&age=30'

  • Utilisation : Utilisée avec la fonction urllib.parse.parse_qs(), elle peut être facilement analysée sous forme de dictionnaire.

from urllib.parse import parse_qs
query_params = parse_qs(parsed_url.query)
print(query_params)
# Sortie : {'name': ['Alice'], 'age': ['30']}

fragment

  • Signification : Identifiant de fragment qui suit un hachage (#). Utilisé principalement pour naviguer vers une section spécifique d'une page web et est géré uniquement par le navigateur, sans être envoyé au serveur.

  • Exemple : 'section1'


3. Analyse approfondie de la propriété .netloc



.netloc est particulièrement importante parmi les résultats de urlparse(). netloc est l'abréviation de localisation réseau, et contient des informations clés concernant l'adresse du serveur web dans l'URL.

Composants de netloc

netloc peut être composé des éléments suivants :

  • Informations utilisateur (Userinfo) : Peut inclure le nom d'utilisateur et le mot de passe sous la forme user:password@. Bien que rarement utilisé dans les URL web classiques pour des raisons de sécurité, cela peut être observé dans d'autres protocoles comme FTP.

  • Hôte (Host) : Nom de domaine (www.example.com) ou adresse IP (192.168.1.1).

  • Port (Port) : Numéro de port qui suit le :. Lorsque les ports par défaut sont utilisés, comme le port 80 pour HTTP et le port 443 pour HTTPS, le numéro de port peut être omis dans netloc.

Exemple :

URL Résultat netloc Description
https://www.example.com www.example.com Comprend uniquement le domaine (port par défaut HTTPS 443 omis)
http://myhost:8000/app myhost:8000 Comprend l'hôte et le port
ftp://user:pass@ftp.example.org user:pass@ftp.example.org Comprend les informations utilisateur et l'hôte

Pourquoi et comment utiliser .netloc

  1. Extraction et validation de domaine :

    • Il est possible d'utiliser netloc pour facilement extraire la partie domaine afin d'appliquer des politiques de sécurité ou d'autoriser uniquement certains domaines en vérifiant la provenance de la requête web.

    • L'attribut parsed_url.hostname permet d'obtenir uniquement le nom d'hôte sans le numéro de port.

url = 'https://www.example.com:8080/path'
parsed = urlparse(url)
print(parsed.netloc)    # 'www.example.com:8080'
print(parsed.hostname)  # 'www.example.com'
print(parsed.port)      # 8080 (int)
  1. Réinjection ou modification d'URL :

    • Bien que l'objet ParseResult retourné par urlparse() soit immuable (immutable), vous pouvez en créer un nouveau en modifiant uniquement certaines propriétés à l'aide de la méthode .replace(). Cet objet modifié peut ensuite être passé à la fonction urlunparse() pour reconstruire facilement une nouvelle URL.

    • Par exemple, vous pouvez créer une URL en ne changeant que netloc pour implémenter une redirection vers un domaine spécifique.

from urllib.parse import urlparse, urlunparse

original_url = 'https://old.example.com/data'
parsed_original = urlparse(original_url)

# Créer une nouvelle URL en ne changeant que le domaine
new_netloc = 'new.example.com'
modified_parsed = parsed_original._replace(netloc=new_netloc)
new_url = urlunparse(modified_parsed)

print(new_url) # Sortie : https://new.example.com/data
  1. Comparaison d'identité d'URL (basée sur domaine/port) :

    • Lorsqu'il faut vérifier si deux URL pointent vers le même serveur, il est utile de comparer la propriété netloc.
url1 = 'https://api.myapp.com/v1/users'
url2 = 'https://api.myapp.com:443/v2/products' # 443 est le port par défaut HTTPS
url3 = 'https://oldapi.myapp.com/v1/users'

parsed1 = urlparse(url1)
parsed2 = urlparse(url2)
parsed3 = urlparse(url3)

print(parsed1.netloc == parsed2.netloc) # True (le port par défaut peut être omis et considéré comme identique)
print(parsed1.hostname == parsed2.hostname) # True
print(parsed1.netloc == parsed3.netloc) # False

4. Différences entre urlparse() et urlsplit()

Le module urllib.parse contient également une fonction urlsplit() qui est très similaire à urlparse(). La principale différence réside dans la manière dont elle traite la propriété params.

  • urlparse() : Sépare la propriété params.

  • urlsplit() : Inclut la propriété params dans la propriété path. Elle retourne un objet SplitResult au lieu de ParseResult et n'a pas de propriété params.

Dans le développement web moderne, étant donné que params est rarement utilisé, urlsplit() peut souvent être une alternative appropriée. Cependant, urlparse() fournit une séparation plus générale et complète.


Conclusion : L'outil indispensable pour l'analyse d'URL

La fonction urlparse() de Python est un puissant outil qui permet de décomposer systématiquement des chaînes d'URL complexes, et d'extraire uniquement les parties nécessaires. En particulier, la propriété .netloc offre des informations clés sur l'hôte et le port de l'URL, ce qui s'avère très utile pour le traitement logique basé sur le domaine ou la reconstruction d'URL.

Pour tous les développeurs Python traitant des URL, que ce soit pour le web scraping, le traitement des requêtes API ou la validation de sécurité, urlparse() est une connaissance essentielle à maîtriser. Utilisez cette fonction pour contrôler et tirer parti des données d'URL de manière plus efficace.

Schéma conceptuel de urlparse