Làm thế nào để urlencode một chuỗi truy vấn trong Python?


552

Tôi đang cố gắng để urlencode chuỗi này trước khi tôi gửi.

queryString = 'eventName=' + evt.fields["eventName"] + '&' + 'eventDescription=' + evt.fields["eventDescription"]; 

Câu trả lời:


561

Bạn cần chuyển các tham số của mình thành urlencode()một ánh xạ (dict) hoặc một chuỗi gồm 2 bộ dữ liệu, như:

>>> import urllib
>>> f = { 'eventName' : 'myEvent', 'eventDescription' : 'cool event'}
>>> urllib.urlencode(f)
'eventName=myEvent&eventDescription=cool+event'

Python 3 trở lên

Sử dụng:

>>> urllib.parse.urlencode(f)
eventName=myEvent&eventDescription=cool+event

Lưu ý rằng điều này không thực hiện mã hóa url theo nghĩa thường được sử dụng (nhìn vào đầu ra). Đối với việc sử dụng đó urllib.parse.quote_plus.


12
"Lưu ý rằng urllib.urlencode không phải lúc nào cũng lừa được. Vấn đề là một số dịch vụ quan tâm đến thứ tự của các đối số, bị mất khi bạn tạo từ điển. Đối với những trường hợp như vậy, urllib.quote_plus tốt hơn, như Ricky đề xuất. "
Blairg23

16
Về mặt kỹ thuật, đó là một lỗi trong dịch vụ, phải không?
Holdenweb

5
và làm thế nào một người có thể làm điều này nếu bạn chỉ muốn làm cho một chuỗi URL an toàn mà không cần xây dựng một chuỗi đối số truy vấn đầy đủ?
Mike 'Pomax' Kamermans

1
@ Mike'Pomax'Kamermans - xem ví dụ stackoverflow.com/questions/12082314/ Lời hoặc Ricky trả lời cho câu hỏi này.
bgporter

1
@ bk0 có vẻ như phương thức của bạn chỉ hợp lệ cho từ điển chứ không phải chuỗi.
JD Gamboa

1021

Con trăn 2

Những gì bạn đang tìm kiếm là urllib.quote_plus:

>>> urllib.quote_plus('string_of_characters_like_these:$#@=?%^Q^$')
'string_of_characters_like_these%3A%24%23%40%3D%3F%25%5EQ%5E%24'

Con trăn 3

Trong Python 3, urllibgói đã được chia thành các thành phần nhỏ hơn. Bạn sẽ sử dụng urllib.parse.quote_plus(lưu ý parsemô-đun con)

import urllib.parse
urllib.parse.quote_plus(...)

4
Cảm ơn! Tuy nhiên, trong trường hợp của tôi, tôi cần phải đặt:import urllib.parse ... urllib.parse.quote_plus(query)
ivkremer

3
rất tốt, nhưng tại sao không sử dụng Unicode? Nếu chuỗi url là Unicode, tôi phải mã hóa nó thành UTF-8. Có cách nào khác để làm điều đó không?
Karl Doenitz 6/2/2015

7
Điều này hoạt động rất tốt, nhưng tôi không thể truy cập một số dịch vụ trực tuyến (REST) ​​cho đến khi tôi thêm tham số này safe = '; / ?: @ & = + $,'
rovyko

Tôi đã thử điều đó trong Python 3 nhưng không thể: stackoverflow.com/questions
40557606 / Giả

1
python3 -c "import urllib.parse, sys; print(urllib.parse.quote_plus(sys.argv[1])) "string to encode"cho một lớp lót trên dòng lệnh
Amos Joshua

52

Hãy thử các yêu cầu thay vì urllib và bạn không cần phải bận tâm với urlencode!

import requests
requests.get('http://youraddress.com', params=evt.fields)

BIÊN TẬP:

Nếu bạn cần các cặp giá trị tên được đặt hàng hoặc nhiều giá trị cho một tên thì hãy đặt tham số như sau:

params=[('name1','value11'), ('name1','value12'), ('name2','value21'), ...]

thay vì sử dụng từ điển


5
Điều này không giải quyết vấn đề đặt hàng các cặp giá trị tên, điều này cũng đòi hỏi phải có quyền cài đặt các thư viện bên ngoài mà có thể không thực hiện được cho dự án.
dreftymac

Tôi đã đăng mã tối thiểu sẽ hoạt động cho OP. OP không yêu cầu các cặp theo thứ tự tuy nhiên cũng có thể thực hiện được, xem cập nhật của tôi.
Barney

@dreftymac: đây là địa chỉ đặt hàng (mặc dù nó không phải là một phần của câu hỏi), vui lòng đọc câu trả lời cập nhật của tôi.
Barney

36

Bối cảnh

  • Python (phiên bản 2.7.2)

Vấn đề

  • Bạn muốn tạo một chuỗi truy vấn urlencoding.
  • Bạn có một từ điển hoặc đối tượng chứa các cặp tên-giá trị.
  • Bạn muốn có thể kiểm soát thứ tự đầu ra của các cặp tên-giá trị.

Giải pháp

  • urllib.urlencode
  • urllib.quote_plus

Cạm bẫy

Thí dụ

Sau đây là một giải pháp hoàn chỉnh, bao gồm cách đối phó với một số cạm bẫy.

### ********************
## init python (version 2.7.2 )
import urllib

### ********************
## first setup a dictionary of name-value pairs
dict_name_value_pairs = {
  "bravo"   : "True != False",
  "alpha"   : "http://www.example.com",
  "charlie" : "hello world",
  "delta"   : "1234567 !@#$%^&*",
  "echo"    : "user@example.com",
  }

### ********************
## setup an exact ordering for the name-value pairs
ary_ordered_names = []
ary_ordered_names.append('alpha')
ary_ordered_names.append('bravo')
ary_ordered_names.append('charlie')
ary_ordered_names.append('delta')
ary_ordered_names.append('echo')

### ********************
## show the output results
if('NO we DO NOT care about the ordering of name-value pairs'):
  queryString  = urllib.urlencode(dict_name_value_pairs)
  print queryString 
  """
  echo=user%40example.com&bravo=True+%21%3D+False&delta=1234567+%21%40%23%24%25%5E%26%2A&charlie=hello+world&alpha=http%3A%2F%2Fwww.example.com
  """

if('YES we DO care about the ordering of name-value pairs'):
  queryString  = "&".join( [ item+'='+urllib.quote_plus(dict_name_value_pairs[item]) for item in ary_ordered_names ] )
  print queryString
  """
  alpha=http%3A%2F%2Fwww.example.com&bravo=True+%21%3D+False&charlie=hello+world&delta=1234567+%21%40%23%24%25%5E%26%2A&echo=user%40example.com
  """ 


23

Thử cái này:

urllib.pathname2url(stringToURLEncode)

urlencodesẽ không hoạt động vì nó chỉ hoạt động trên từ điển. quote_pluskhông tạo ra đầu ra chính xác.


Điều đó thực sự hữu ích! Trong trường hợp của tôi, tôi chỉ có một phần chuỗi mà tôi muốn mã hóa URL, ví dụ tôi muốn chuyển đổi my stringthành my%20string. Giải pháp của bạn hoạt động như một cơ duyên cho điều đó!
TanguyP 14/2/2016

Làm việc cho tôi để có được %20thay vì +. Cảm ơn
Jossef Harush

21

Lưu ý rằng urllib.urlencode không phải lúc nào cũng thực hiện thủ thuật. Vấn đề là một số dịch vụ quan tâm đến thứ tự của các đối số, bị mất khi bạn tạo từ điển. Đối với những trường hợp như vậy, urllib.quote_plus tốt hơn, như Ricky đề xuất.


2
Nó hoạt động tốt và giữ trật tự nếu bạn vượt qua một danh sách các bộ dữ liệu:>>> import urllib >>> urllib.urlencode([('name', 'brandon'), ('uid', 1000)]) 'name=brandon&uid=1000'
Brandon Rhodes

8

Trong Python 3, điều này đã làm việc với tôi

import urllib

urllib.parse.quote(query)

6

để tham khảo trong tương lai (ví dụ: cho python3)

>>> import urllib.request as req
>>> query = 'eventName=theEvent&eventDescription=testDesc'
>>> req.pathname2url(query)
>>> 'eventName%3DtheEvent%26eventDescription%3DtestDesc'

1
thông thường bạn chỉ muốn url mã hóa các giá trị, những gì bạn đã làm ở đây sẽ tạo một truy vấn GET không hợp lệ
Codewithcheese 24/2/2015

Đầu ra cho 'c:/2 < 3'Windows là '///C://2%20%3C%203'. Tôi muốn một cái gì đó sẽ chỉ xuất ra 'c:/2%20%3C%203'.
binki

3

Để sử dụng trong các tập lệnh / chương trình cần hỗ trợ cả python 2 và 3, mô-đun sáu cung cấp các hàm quote và urlencode:

>>> from six.moves.urllib.parse import urlencode, quote
>>> data = {'some': 'query', 'for': 'encoding'}
>>> urlencode(data)
'some=query&for=encoding'
>>> url = '/some/url/with spaces and %;!<>&'
>>> quote(url)
'/some/url/with%20spaces%20and%20%25%3B%21%3C%3E%26'

2

Nếu urllib.parse.urlencode () gây ra lỗi cho bạn, thì hãy thử mô-đun urllib3.

Các cú pháp như sau:

import urllib3
urllib3.request.urlencode({"user" : "john" }) 

1

Một điều khác có thể chưa được đề cập là urllib.urlencode()sẽ mã hóa các giá trị trống trong từ điển dưới dạng chuỗi Nonethay vì không có tham số đó. Tôi không biết điều này thường được mong muốn hay không, nhưng không phù hợp với trường hợp sử dụng của tôi, do đó tôi phải sử dụng quote_plus.


0

Để Python 3 urllib3 hoạt động chính xác, bạn có thể sử dụng như sau theo tài liệu chính thức của nó :

import urllib3

http = urllib3.PoolManager()
response = http.request(
     'GET',
     'https://api.prylabs.net/eth/v1alpha1/beacon/attestations',
     fields={  # here fields are the query params
          'epoch': 1234,
          'pageSize': pageSize 
      } 
 )
response = attestations.data.decode('UTF-8')
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.