วิธี urlencode การสอบถามใน Python?


552

ฉันพยายามที่จะ urlencode สตริงนี้ก่อนที่ฉันจะส่ง

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

คำตอบ:


561

คุณต้องส่งพารามิเตอร์ของคุณให้urlencode()เป็นทั้งการจับคู่ (dict) หรือลำดับของ 2-tuples เช่น:

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

Python 3 ขึ้นไป

ใช้:

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

โปรดทราบว่านี่ไม่ใช่การเข้ารหัส url ในความหมายที่ใช้กันทั่วไป (ดูที่เอาต์พุต) สำหรับการใช้งานurllib.parse.quote_plusนั้น


12
"โปรดทราบว่า urllib.urlencode ไม่ได้ทำเคล็ดลับเสมอปัญหาคือบริการบางอย่างใส่ใจกับลำดับของข้อโต้แย้งซึ่งจะหายไปเมื่อคุณสร้างพจนานุกรมสำหรับกรณีดังกล่าว urllib.quote_plus จะดีกว่าดังที่ Ricky แนะนำ "
Blairg23

16
ในทางเทคนิคแล้วนั่นเป็นข้อผิดพลาดในบริการใช่ไหม
holdenweb

5
และวิธีการหนึ่งจะทำเช่นนี้ถ้าคุณเพียงแค่ต้องการให้ URL สตริงที่ปลอดภัยโดยไม่ต้องสร้างสตริงอาร์กิวเมนต์แบบสอบถามแบบเต็ม?
ไมค์ 'Pomax' Kamermans

1
@ Mike'Pomax'Kamermans - ดูเช่นstackoverflow.com/questions/12082314/…หรือคำตอบของ Ricky สำหรับคำถามนี้
bgporter

1
@ bk0 ดูเหมือนว่าวิธีการของคุณใช้ได้กับพจนานุกรมเท่านั้นและไม่ใช่สตริง
JD Gamboa

1021

Python 2

สิ่งที่คุณกำลังมองหาคือ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'

Python 3

ใน Python 3 urllibแพ็คเกจได้ถูกแบ่งออกเป็นส่วนประกอบที่เล็กกว่า คุณจะใช้urllib.parse.quote_plus(หมายเหตุparseโมดูลย่อย)

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

4
ขอบคุณ! ในกรณีของฉัน แต่ฉันต้องใส่:import urllib.parse ... urllib.parse.quote_plus(query)
ivkremer

3
ดีมาก แต่ทำไมไม่คุ้นเคยกับ Unicode ถ้าสตริง url เป็น Unicode ฉันต้องเข้ารหัสเป็น UTF-8 มีวิธีอื่นที่จะทำหรือไม่
Karl Doenitz

7
สิ่งนี้ใช้งานได้ดี แต่ฉันไม่สามารถเข้าถึงบริการออนไลน์ (REST) ​​บางอย่างได้จนกว่าฉันจะเพิ่มพารามิเตอร์นี้ safe = '; /
?:

ฉันลองใน Python 3 แต่ไม่สามารถทำได้: stackoverflow.com/questions/40557606/…
สัตว์เลื้อยคลาน

1
python3 -c "import urllib.parse, sys; print(urllib.parse.quote_plus(sys.argv[1])) "string to encode"สำหรับหนึ่งซับในบรรทัดคำสั่ง
Amos Joshua

52

ลองใช้คำขอแทน urllib และคุณไม่จำเป็นต้องกังวลกับ urlencode!

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

แก้ไข:

หากคุณต้องการคู่ค่าชื่อที่เรียงลำดับหรือหลายค่าสำหรับชื่อให้ตั้งค่าพารามิเตอร์ดังนี้:

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

แทนที่จะใช้พจนานุกรม


5
สิ่งนี้ไม่ได้แก้ไขปัญหาของการสั่งซื้อคู่ค่าชื่อและต้องได้รับอนุญาตในการติดตั้งไลบรารีภายนอกซึ่งอาจไม่สามารถทำได้สำหรับโครงการ
dreftymac

ฉันโพสต์รหัสขั้นต่ำที่เหมาะกับ OP OP ไม่ได้ร้องขอคู่ที่สั่งซื้อ แต่ก็สามารถใช้งานได้ดูการอัปเดตของฉัน
บาร์นีย์

@dreftymac: นี่คือการสั่งซื้อที่อยู่ (แม้ว่ามันจะไม่ได้เป็นส่วนหนึ่งของคำถาม) โปรดอ่านคำตอบที่อัปเดตของฉัน
บาร์นีย์

36

บริบท

  • Python (รุ่น 2.7.2)

ปัญหา

  • คุณต้องการสร้างสตริงแบบสอบถามแบบใช้ urlencoded
  • คุณมีพจนานุกรมหรือวัตถุที่มีคู่ค่าชื่อ
  • คุณต้องการควบคุมการเรียงลำดับผลลัพธ์ของคู่ค่า - ชื่อ

สารละลาย

  • urllib.urlencode
  • urllib.quote_plus

ผิดพลาด

ตัวอย่าง

ต่อไปนี้เป็นโซลูชันที่สมบูรณ์รวมถึงวิธีจัดการกับข้อผิดพลาดบางอย่าง

### ********************
## 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

ลองสิ่งนี้:

urllib.pathname2url(stringToURLEncode)

urlencodeจะไม่ทำงานเพราะใช้งานได้กับพจนานุกรมเท่านั้น quote_plusไม่ได้สร้างผลลัพธ์ที่ถูกต้อง


นั่นเป็นประโยชน์จริงๆ! ในกรณีของฉันฉันมีเพียงแค่ส่วนหนึ่งของสตริงที่ฉันต้องการที่จะเข้ารหัส URL ตัวอย่างเช่นผมต้องการที่จะเปลี่ยนไปmy string my%20stringโซลูชันของคุณทำงานได้อย่างมีเสน่ห์สำหรับสิ่งนั้น!
TanguyP

ทำงานสำหรับฉันที่จะได้รับแทน%20 +ขอบคุณ
Jossef Harush

21

โปรดทราบว่า urllib.urlencode ไม่ได้ทำเคล็ดลับเสมอ ปัญหาคือบริการบางบริการดูแลเกี่ยวกับลำดับของการขัดแย้งซึ่งจะหายไปเมื่อคุณสร้างพจนานุกรม สำหรับกรณีเช่นนี้ urllib.quote_plus จะดีกว่าดังที่ Ricky แนะนำ


2
มันทำงานได้ดีและรักษาคำสั่งถ้าคุณผ่านรายการของ tuples:>>> import urllib >>> urllib.urlencode([('name', 'brandon'), ('uid', 1000)]) 'name=brandon&uid=1000'
แบรนดอนโรดส์


6

สำหรับการอ้างอิงในอนาคต (เช่น: สำหรับ python3)

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

1
โดยปกติแล้วคุณเพียงแค่ต้องการให้ url เข้ารหัสค่าสิ่งที่คุณทำที่นี่จะทำให้การสืบค้น GET ไม่ถูกต้อง
Codewithcheese

เอาท์พุทสำหรับ'c:/2 < 3'บน Windows '///C://2%20%3C%203'คือ 'c:/2%20%3C%203'ฉันต้องการสิ่งที่จะเป็นเพียงแค่การส่งออก
binki

3

สำหรับใช้ในสคริปต์ / โปรแกรมที่จำเป็นต้องรองรับทั้ง python 2 และ 3 โมดูลทั้งหกมีฟังก์ชั่น quote และ 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

หาก urllib.parse.urlencode () ให้ข้อผิดพลาดแก่คุณให้ลองใช้โมดูล urllib3

ไวยากรณ์เป็นดังนี้:

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

1

อีกสิ่งที่อาจไม่ได้กล่าวถึงแล้วคือการurllib.urlencode()เข้ารหัสค่าว่างในพจนานุกรมเป็นสตริงNoneแทนที่จะมีพารามิเตอร์ขาด ผมไม่ทราบว่านี้มักจะเป็นที่ต้องการหรือไม่ quote_plusแต่ไม่พอดีกับกรณีการใช้งานของฉันดังนั้นฉันต้องใช้


0

สำหรับ Python 3 urllib3ทำงานได้อย่างถูกต้องคุณสามารถใช้ดังต่อไปนี้ตามเอกสารอย่างเป็นทางการ :

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')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.