Làm cách nào để chuyển từ điển sang chuỗi truy vấn trong Python?


Câu trả lời:


158

Python 3

urllib.parse.urlencode(truy vấn, liều lượngq = Sai, [...])

Chuyển đổi một đối tượng ánh xạ hoặc một chuỗi các bộ gồm hai phần tử, có thể chứa các đối tượng str hoặc byte, thành chuỗi văn bản ASCII được mã hóa theo phần trăm.

- Tài liệu Python 3urllib.parse

A dictlà một ánh xạ.

Python kế thừa

urllib.urlencode( query[, doseq])
Chuyển đổi một đối tượng ánh xạ hoặc một chuỗi các bộ giá trị hai phần tử thành một chuỗi "được mã hóa phần trăm" ... một chuỗi các key=valuecặp được phân tách bằng '&'ký tự ...

- Tài liệu Python 2.7urllib


1
Điều này đúng, nhưng giá trị dicttrả về cgi.parse_qs()thực sự có lists là "giá trị" của nó. Chuyển thẳng vào sẽ dẫn đến các chuỗi truy vấn trông rất kỳ quặc.
Johnsyweb

Đúng vậy. Điều đó sẽ dạy tôi đọc nhiều hơn câu đầu tiên!
Johnsyweb


Vấn đề là urlencode sẽ chuyển đổi không gian thành +, điều này không được khuyến khích.
user1633272

1
@ user1633272: Không nên theo ai?
Ignacio Vazquez-Abrams

65

Trong python3, hơi khác:

from urllib.parse import urlencode
urlencode({'pram1': 'foo', 'param2': 'bar'})

đầu ra: 'pram1=foo&param2=bar'

để tương thích với python2 và python3, hãy thử điều này:

try:
    #python2
    from urllib import urlencode
except ImportError:
    #python3
    from urllib.parse import urlencode

6

Bạn đang tìm kiếm một cái gì đó giống hệt nhưurllib.urlencode() !

Tuy nhiên, khi bạn gọi parse_qs()(khác với parse_qsl()), khóa từ điển là tên biến truy vấn duy nhất và giá trị là danh sách giá trị cho mỗi tên.

Để chuyển thông tin này vào urllib.urlencode(), bạn phải "san phẳng" các danh sách này. Đây là cách bạn có thể làm điều đó với một danh sách toàn bộ các bộ giá trị:

query_pairs = [(k,v) for k,vlist in d.iteritems() for v in vlist]
urllib.urlencode(query_pairs)

15
Hoặc bạn có thể vượt qua doseq=True.
Ignacio Vazquez-Abrams

@downvoter: Làm cách nào để cải thiện câu trả lời này? Đã sáu năm kể từ khi tôi viết nó!
Johnsyweb

-1

Có thể bạn đang tìm kiếm một cái gì đó như thế này:

def dictToQuery(d):
  query = ''
  for key in d.keys():
    query += str(key) + '=' + str(d[key]) + "&"
  return query

Nó cần một từ điển và chuyển đổi nó thành một chuỗi truy vấn, giống như urlencode. Nó sẽ thêm một dấu "&" cuối cùng vào chuỗi truy vấn, nhưng sẽ return query[:-1]khắc phục điều đó, nếu đó là sự cố.


4
Bạn đã gặp nhau str.join()chưa? Làm thế nào về urllib.quote_plus()?
Ignacio Vazquez-Abrams

1
@garbados Giải pháp của bạn sẽ hoạt động trong các trường hợp đơn giản. Tuy nhiên, hãy xem urlencodetrongurllib.py (nó nên bởi bằng Python của bạn cài đặt) để xem lý do tại sao việc tạo ra một chuỗi truy vấn là đôi khi không hoàn toàn đơn giản như câu trả lời của bạn ngụ ý (đặc biệt là sự cần thiết phải 'quote' nhất định ký tự không hợp lệ trong một URL). @Ignacio cũng đã tham khảo hai chức năng có thể làm sạch quá trình triển khai của bạn và làm cho nó chính xác.
Anthony Cramp

À, đúng vậy. Xin lỗi vì việc thực hiện thiếu chặt chẽ. Điều đó cho thấy tôi nên cẩn thận hơn khi trả lời những câu hỏi mà bản thân chưa từng đối mặt.
garbados

Mặc dù đây có thể không phải là câu trả lời hay nhất, nhưng nó chính xác là những gì tôi muốn thấy khi nhấp vào tiêu đề của câu hỏi này. Tôi chỉ có 4 mục trong một câu lệnh mà tôi cần chuyển thành một cặp name = value được phân tách bằng dấu '&'. Giá trị của tôi được kiểm soát. Hàm str.join () rất tiện dụng trong trường hợp của tôi nhưng tôi không cần đến quote_plus (), một lần nữa, vì nó không phải là mã công khai :) Cảm ơn!
harperville

1
@harperville nhưng cách đúng hơn ( from urllib.parse import urlencode; urlencode(your_dict)) ngắn hơn và dễ hơn cách này! Tôi sẽ cho rằng đôi khi thật thông minh khi sáng tạo lại bánh xe, thậm chí là kém chất lượng, khi việc sử dụng các bánh xe hiện có, được thiết kế tốt, nhưng ở đây, việc sử dụng bánh xe có sẵn sẽ dễ dàng và nhanh chóng hơn so với việc lăn bánh xe kém hơn của bạn .
Mark Amery
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.