วิธีการเข้ารหัสพารามิเตอร์ URL เปอร์เซ็นต์ใน Python?


299

ถ้าฉันทำ

url = "http://example.com?p=" + urllib.quote(query)
  1. มันไม่ได้เข้ารหัส/ไปที่%2F(หยุดพักการฟื้นฟู OAuth)
  2. มันไม่ได้จัดการกับ Unicode (มันส่งข้อยกเว้น)

มีห้องสมุดที่ดีกว่านี้ไหม


1
สิ่งเหล่านี้ไม่ใช่พารามิเตอร์ URL, FYI คุณควรชี้แจง
เจมี่มาร์แชลล์

คำตอบ:


390

Python 2

จากเอกสาร :

urllib.quote(string[, safe])

แทนที่อักขระพิเศษในสตริงโดยใช้ตัวหนี% xx จะไม่มีการอ้างถึงตัวอักษรตัวเลขและอักขระ '_.-' โดยค่าเริ่มต้นฟังก์ชั่นนี้มีไว้สำหรับการอ้างอิงส่วนเส้นทางของ URL พารามิเตอร์ตัวเลือกที่ปลอดภัยระบุตัวละครเพิ่มเติมที่ไม่ควรยกมา - ค่าเริ่มต้นของมันคือ '/'

นั่นหมายถึงการผ่าน '' เพื่อความปลอดภัยจะช่วยแก้ไขปัญหาแรกของคุณ

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

เกี่ยวกับปัญหาที่สองมีการรายงานข้อผิดพลาดเกี่ยวกับเรื่องนี้ที่นี่ เห็นได้ชัดว่ามันถูกแก้ไขใน python 3 คุณสามารถแก้ไขได้โดยการเข้ารหัสเป็น utf8 ดังนี้:

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

โดยวิธีการดูurlencode

Python 3

เดียวกันยกเว้นแทนที่ด้วยurllib.quoteurllib.parse.quote


1
ขอบคุณคุณทั้งสองทำงานได้ดี urlencode เพียงแค่เรียก quoteplus หลายครั้งในการวนซ้ำซึ่งไม่ใช่วิธีการฟื้นฟูที่ถูกต้องสำหรับงานของฉัน (oauth)
Paul Tarjan

6
ข้อมูลจำเพาะ: rfc 2396กำหนดสิ่งเหล่านี้ว่าสงวนไว้reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","ซึ่งเป็นสิ่งที่ urllib.quote กำลังติดต่อด้วย
Jeff Sheffield

63
urllib.quoteย้ายไปurlib.parse.quoteตั้งแต่ Python3
Hibou57


นอกจากนี้ในกรณีที่มีการเข้ารหัสข้อความค้นหาคุณอาจจะดีกว่าโดยใช้ quote_plus: docs.python.org/3/library/ ...... 1. มันเข้ารหัสเครื่องหมายสแลชโดยค่าเริ่มต้น 2 นอกจากนี้ยังเข้ารหัสช่องว่าง
Pavel Vergeev

174

ใน Python 3 urllib.quoteถูกย้ายไปที่urllib.parse.quoteและจะจัดการ unicode ตามค่าเริ่มต้น

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

2
ชื่อquoteค่อนข้างคลุมเครือในระดับโลก มันอาจจะดีกว่าที่จะใช้สิ่งที่ต้องการ from urllib.parse import quote as urlencodeurlencode:
Luc

โปรดทราบว่ามีฟังก์ชั่นที่มีชื่อurlencodeอยู่urllib.parseแล้วและทำสิ่งที่แตกต่างไปจากเดิมอย่างสิ้นเชิงดังนั้นคุณควรเลือกชื่ออื่นหรือเสี่ยงที่จะทำให้ผู้อ่านรหัสของคุณสับสนในอนาคต
jaymmer - Reinstate Monica

48

คำตอบของฉันคล้ายกับคำตอบของเปาโล

ฉันคิดว่าโมดูลrequestsดีกว่ามาก urllib3ก็ขึ้นอยู่กับ คุณสามารถลองสิ่งนี้:

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

5
requests.utils.quotequoteเชื่อมโยงไปยังหลาม ดูแหล่งที่มาร้องขอ
Cjkjvfnby

16
requests.utils.quoteเป็น wrapper เข้ากันได้บางurllib.quoteสำหรับ python 2 และurllib.parse.quoteสำหรับ python 3
Jeff Sheffield

13

หากคุณใช้ django คุณสามารถใช้ urlquote:

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

โปรดทราบว่าการเปลี่ยนแปลงเป็น Python ตั้งแต่คำตอบนี้ได้รับการเผยแพร่หมายความว่าตอนนี้นี่เป็น wrapper ดั้งเดิม จากซอร์สโค้ด Django สำหรับ django.utils.http:

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

2

มันจะดีกว่าที่จะใช้urlencodeที่นี่ ไม่แตกต่างกันมากสำหรับพารามิเตอร์เดียว แต่ IMHO ทำให้รหัสชัดเจนขึ้น (มันดูสับสนที่จะเห็นฟังก์ชั่นquote_plus! โดยเฉพาะอย่างยิ่งผู้ที่มาจากภาษาอื่น ๆ )

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

เอกสาร

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

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

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