Python9 min de lecture

Comment encoder une URL en Python (guide complet urllib.parse)

L'encodage d'URL en Python repose sur urllib.parse.quote() pour l'encodage-pourcent des chaines et sur urllib.parse.urlencode() pour transformer des dictionnaires en chaines de requete. Ce guide couvre quote(), unquote(), urlencode() et parse_qs() avec des exemples concrets.

Encodage d'URL avec quote()

La fonction urllib.parse.quote() est l'outil principal de Python pour l'encodage-pourcent des chaines de caracteres. Elle convertit les caracteres qui ne peuvent pas etre utilises sans risque dans les URL en leurs equivalents encodes en pourcent. Par defaut, elle considere les barres obliques (/) comme des caracteres surs, mais vous pouvez personnaliser ce comportement.

from urllib.parse import quote

# Encodage de base
print(quote('hello world'))
# Sortie : hello%20world

# Encodage de caracteres speciaux
print(quote('price=10&qty=2'))
# Sortie : price%3D10%26qty%3D2

# Par defaut, / n'est pas encode
print(quote('path/to/file'))
# Sortie : path/to/file

# Pour encoder aussi les barres obliques, definir safe=''
print(quote('path/to/file', safe=''))
# Sortie : path%2Fto%2Ffile

# Encodage de caracteres Unicode
print(quote('cafe'))
# Sortie : caf%C3%A9

# Specifier des caracteres surs supplementaires
print(quote('key=value&foo=bar', safe='=&'))
# Sortie : key=value&foo=bar

Le parametre safe est la cle pour controler ce qui est encode. Par defaut, safe='/'. Si vous souhaitez encoder tout sauf les caracteres alphanumeriques et _.-~, definissez safe=''. Cela equivaut a la fonction encodeURIComponent() de JavaScript.

Il existe aussi quote_plus(), qui fonctionne comme quote() mais encode les espaces en + au lieu de %20. C'est le format utilise pour les donnees de formulaire HTML (application/x-www-form-urlencoded).

from urllib.parse import quote_plus

print(quote_plus('hello world'))
# Sortie : hello+world

print(quote_plus('key=value&name=John Doe'))
# Sortie : key%3Dvalue%26name%3DJohn+Doe

Decodage d'URL avec unquote()

La fonction urllib.parse.unquote() inverse l'encodage-pourcent en reconvertissant les sequences %XX en leurs caracteres d'origine. Il existe egalement unquote_plus(), qui convertit en plus les signes + en espaces.

from urllib.parse import unquote, unquote_plus

# Decodage de base
print(unquote('hello%20world'))
# Sortie : hello world

print(unquote('caf%C3%A9'))
# Sortie : cafe (avec accent)

# unquote ne convertit PAS + en espace
print(unquote('hello+world'))
# Sortie : hello+world

# unquote_plus convertit + en espace
print(unquote_plus('hello+world'))
# Sortie : hello world

# Decodage d'une URL complete
url = 'https://example.com/search?q=C%2B%2B%20programming'
print(unquote(url))
# Sortie : https://example.com/search?q=C++ programming

Utilisez toujours unquote_plus() pour decoder des donnees de formulaire, car les formulaires HTML encodent les espaces en +. Utilisez unquote() pour le decodage d'URL general, ou les espaces sont encodes en %20.

Encodage de chaines de requete avec urlencode()

La fonction urllib.parse.urlencode() prend un dictionnaire ou une liste de tuples et le convertit en une chaine de requete correctement formatee. C'est la maniere la plus pratique de construire des chaines de requete en Python.

from urllib.parse import urlencode

# Dictionnaire vers chaine de requete
params = {
    'q': 'python programming',
    'page': 1,
    'lang': 'en'
}
print(urlencode(params))
# Sortie : q=python+programming&page=1&lang=en

# Liste de tuples (preserve l'ordre, autorise les cles en double)
params = [
    ('tag', 'python'),
    ('tag', 'web'),
    ('sort', 'date')
]
print(urlencode(params))
# Sortie : tag=python&tag=web&sort=date

# Utilisation de doseq=True pour les valeurs de type liste
params = {
    'tag': ['python', 'web', 'api'],
    'sort': 'date'
}
print(urlencode(params, doseq=True))
# Sortie : tag=python&tag=web&tag=api&sort=date

# Utilisation de quote_via pour controler l'encodage des espaces
from urllib.parse import quote
params = {'q': 'hello world'}
print(urlencode(params, quote_via=quote))
# Sortie : q=hello%20world  (utilise %20 au lieu de +)

Par defaut, urlencode() utilise quote_plus() en interne, ce qui signifie que les espaces deviennent des +. Si vous avez besoin de %20 pour les espaces, passez quote_via=quote comme indique ci-dessus.

Analyse de chaines de requete avec parse_qs()

La fonction urllib.parse.parse_qs() analyse une chaine de requete pour la reconvertir en dictionnaire. Chaque valeur du dictionnaire est une liste, car les parametres de requete peuvent avoir plusieurs valeurs. Il existe aussi parse_qsl(), qui renvoie une liste de tuples.

from urllib.parse import parse_qs, parse_qsl

# Analyse d'une chaine de requete en dictionnaire
qs = 'q=python+programming&page=1&lang=en'
result = parse_qs(qs)
print(result)
# Sortie : {'q': ['python programming'], 'page': ['1'], 'lang': ['en']}

# Remarque : les valeurs sont toujours des listes
print(result['q'][0])  # 'python programming'

# Gestion de plusieurs valeurs pour une meme cle
qs = 'tag=python&tag=web&tag=api'
result = parse_qs(qs)
print(result)
# Sortie : {'tag': ['python', 'web', 'api']}

# parse_qsl renvoie une liste de tuples
result = parse_qsl(qs)
print(result)
# Sortie : [('tag', 'python'), ('tag', 'web'), ('tag', 'api')]

# Conserver les valeurs vides (par defaut, elles sont omises)
qs = 'name=John&email=&age=30'
print(parse_qs(qs, keep_blank_values=True))
# Sortie : {'name': ['John'], 'email': [''], 'age': ['30']}

Encodage d'URL completes avec urlparse

Lorsque vous travaillez avec des URL completes, les fonctions urlparse() et urlunparse() de Python permettent de decomposer et de reconstruire les URL en toute securite. C'est particulierement utile lorsque vous devez modifier des parties precises d'une URL sans en casser la structure.

from urllib.parse import urlparse, urlunparse, urlencode, quote

# Analyse d'une URL en composants
url = 'https://example.com/search?q=hello&page=1#results'
parsed = urlparse(url)
print(parsed.scheme)    # 'https'
print(parsed.netloc)    # 'example.com'
print(parsed.path)      # '/search'
print(parsed.query)     # 'q=hello&page=1'
print(parsed.fragment)  # 'results'

# Construction d'une URL a partir de composants
from urllib.parse import ParseResult
new_url = urlunparse(ParseResult(
    scheme='https',
    netloc='api.example.com',
    path='/v2/search',
    params='',
    query=urlencode({'q': 'python & java', 'limit': 10}),
    fragment=''
))
print(new_url)
# Sortie : https://api.example.com/v2/search?q=python+%26+java&limit=10

# Ajout securise d'un segment de chemin contenant des caracteres speciaux
base = 'https://example.com/files/'
filename = 'my report (final).pdf'
safe_url = base + quote(filename, safe='')
print(safe_url)
# Sortie : https://example.com/files/my%20report%20%28final%29.pdf

Pour du code Python moderne, envisagez d'utiliser la bibliotheque requests, qui gere automatiquement l'encodage d'URL lorsque vous passez les parametres sous forme de dictionnaire. La bibliotheque httpx offre egalement des capacites d'encodage automatique similaires.

import requests

# requests gere l'encodage automatiquement
response = requests.get(
    'https://api.example.com/search',
    params={
        'q': 'python & java',
        'page': 1,
        'sort': 'relevance'
    }
)
print(response.url)
# https://api.example.com/search?q=python+%26+java&page=1&sort=relevance

Articles connexes

Essayez nos outils gratuits