Làm cách nào để mã hóa các tham số URL trong Python?


299

Nếu tôi làm

url = "http://example.com?p=" + urllib.quote(query)
  1. Nó không mã hóa /thành %2F(phá vỡ chuẩn hóa OAuth)
  2. Nó không xử lý Unicode (nó ném một ngoại lệ)

Có một thư viện tốt hơn?


1
Đây không phải là thông số URL, FYI. Bạn nên làm rõ.
Jamie Marshall

Câu trả lời:


390

Con trăn 2

Từ các tài liệu :

urllib.quote(string[, safe])

Thay thế các ký tự đặc biệt trong chuỗi bằng cách sử dụng% xx thoát. Chữ cái, chữ số và ký tự '_.-' không bao giờ được trích dẫn. Theo mặc định, chức năng này được dành để trích dẫn phần đường dẫn của URL. Tham số an toàn tùy chọn chỉ định các ký tự bổ sung không nên trích dẫn - giá trị mặc định của nó là '/'

Điều đó có nghĩa là vượt qua '' cho an toàn sẽ giải quyết vấn đề đầu tiên của bạn:

>>> urllib.quote('/test')
'/test'
>>> urllib.quote('/test', safe='')
'%2Ftest'

Về vấn đề thứ hai, có một báo cáo lỗi về nó ở đây . Rõ ràng nó đã được sửa trong python 3. Bạn có thể khắc phục nó bằng cách mã hóa dưới dạng utf8 như thế này:

>>> query = urllib.quote(u"Müller".encode('utf8'))
>>> print urllib.unquote(query).decode('utf8')
Müller

Nhân tiện, hãy xem urlencode

Con trăn 3

Tương tự, ngoại trừ thay thế urllib.quotebằng urllib.parse.quote.


1
Cảm ơn bạn, cả hai đã làm việc tuyệt vời. urlencode chỉ gọi các trích dẫn nhiều lần trong một vòng lặp, đó không phải là chuẩn hóa chính xác cho nhiệm vụ của tôi (oauth).
Paul Tarjan

6
spec: rfc 2396 định nghĩa những cái này là dành riêng reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","Đó là những gì urllib.quote đang xử lý.
Jeff Sheffield

63
urllib.quotechuyển đến urlib.parse.quote, kể từ Python3.
Hibou57

5
urllib.parse.quote tài liệu
Andreas Haferburg

Ngoài ra, trong trường hợp mã hóa một truy vấn tìm kiếm, bạn có lẽ nên sử dụng quote_plus: docs.python.org/3/library/... 1. Nó mã hóa dấu gạch chéo theo mặc định 2. Nó cũng mã hóa không gian
Pavel Vergeev

174

Trong Python 3, urllib.quoteđã được chuyển đến urllib.parse.quotevà nó xử lý unicode theo mặc định.

>>> from urllib.parse import quote
>>> quote('/test')
'/test'
>>> quote('/test', safe='')
'%2Ftest'
>>> quote('/El Niño/')
'/El%20Ni%C3%B1o/'

2
Cái tên quotekhá mơ hồ như toàn cầu. Nó có thể đẹp hơn để sử dụng một cái gì đó như urlencode : from urllib.parse import quote as urlencode.
Luc

Lưu ý rằng có một hàm có tên urlencodetrong urllib.parseđã có làm điều gì đó hoàn toàn khác nhau, vì vậy bạn muốn được tốt hơn chọn một tên khác hoặc có nguy cơ gây nhầm lẫn nghiêm trọng độc giả tương lai của mã của bạn.
jaymmer - Tái lập Monica

48

Câu trả lời của tôi tương tự như câu trả lời của Paolo.

Tôi nghĩ rằng mô-đun requestslà tốt hơn nhiều. Nó dựa trên urllib3. Bạn có thể thử điều này:

>>> from requests.utils import quote
>>> quote('/test')
'/test'
>>> quote('/test', safe='')
'%2Ftest'

5
requests.utils.quotelà liên kết đến trăn quote. Xem nguồn yêu cầu .
Cjkjvfnby

16
requests.utils.quotelà một trình bao bọc tương thích mỏng urllib.quotedành cho python 2 và urllib.parse.quotecho python 3
Jeff Sheffield

13

Nếu bạn đang sử dụng django, bạn có thể sử dụng urlquote:

>>> from django.utils.http import urlquote
>>> urlquote(u"Müller")
u'M%C3%BCller'

Lưu ý rằng các thay đổi đối với Python vì câu trả lời này đã được xuất bản có nghĩa là đây là một trình bao bọc kế thừa. Từ mã nguồn Django 2.1 cho django.utils.http:

A legacy compatibility wrapper to Python's urllib.parse.quote() function.
(was used for unicode handling on Python 2)

2

Nó là tốt hơn để sử dụng urlencodeở đây. Không có nhiều khác biệt cho tham số đơn nhưng IMHO làm cho mã rõ ràng hơn. (Có vẻ khó hiểu khi thấy một chức năng quote_plus! Đặc biệt là những người đến từ các nhóm khác)

In [21]: query='lskdfj/sdfkjdf/ksdfj skfj'

In [22]: val=34

In [23]: from urllib.parse import urlencode

In [24]: encoded = urlencode(dict(p=query,val=val))

In [25]: print(f"http://example.com?{encoded}")
http://example.com?p=lskdfj%2Fsdfkjdf%2Fksdfj+skfj&val=34

Tài liệu

urlencode: https://docs.python.org/3/l Library / urllib.parse.html # urllib.parse.urlencode

quote_plus: https://docs.python.org/3/l Library / urllib.parse.html # urllib.parse.quote_plus

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.