如何防止Python请求对我的URL进行百分号编码?
我正在尝试使用 Python 的 requests.get() 方法获取一个特定格式的 URL:
http://api.example.com/export/?format=json&key=site:dummy+type:example+group:wheel
#!/usr/local/bin/python
import requests
print(requests.__versiom__)
url = 'http://api.example.com/export/'
payload = {'format': 'json', 'key': 'site:dummy+type:example+group:wheel'}
r = requests.get(url, params=payload)
print(r.url)
但是,这个 URL 被转换成了百分比编码,我没有得到预期的响应。
2.2.1
http://api.example.com/export/?key=site%3Adummy%2Btype%3Aexample%2Bgroup%3Awheel&format=json
如果我直接传递这个 URL,它是可以正常工作的:
url = http://api.example.com/export/?format=json&key=site:dummy+type:example+group:wheel
r = requests.get(url)
有没有什么方法可以以原始形式传递参数,而不进行百分比编码呢?
谢谢!
7 个回答
以上提到的所有解决方案在requests版本2.26之后似乎都不再有效。GitHub上的建议解决方案似乎是使用一种叫做PreparedRequest的变通方法。
以下方法对我有效。确保你使用的URL是可以解析的,不要用'这不是一个域名.com'这样的地址。
import requests
base_url = 'https://www.example.com/search'
query = '?format=json&key=site:dummy+type:example+group:wheel'
s = requests.Session()
req = requests.Request('GET', base_url)
p = req.prepare()
p.url += query
resp = s.send(p)
print(resp.request.url)
来源:https://github.com/psf/requests/issues/5964#issuecomment-949013046
这个解决方案的设计就是直接传递网址。
上面的答案对我没用。
我想发送一个包含管道符号(|)的请求参数,但用Python的requests库时,它会把管道符号也进行百分比编码。所以我改用了urlopen:
# python3
from urllib.request import urlopen
base_url = 'http://www.example.com/search?'
query = 'date_range=2017-01-01|2017-03-01'
url = base_url + query
response = urlopen(url)
data = response.read()
# response data valid
print(response.url)
# output: 'http://www.example.com/search?date_range=2017-01-01|2017-03-01'
如果将来有人遇到这个问题,你可以通过创建一个请求会话的子类,重写发送方法,来修改原始网址,从而修正百分比编码等问题。欢迎对下面的内容进行补充和修正。
import requests, urllib
class NoQuotedCommasSession(requests.Session):
def send(self, *a, **kw):
# a[0] is prepared request
a[0].url = a[0].url.replace(urllib.parse.quote(","), ",")
return requests.Session.send(self, *a, **kw)
s = NoQuotedCommasSession()
s.get("http://somesite.com/an,url,with,commas,that,won't,be,encoded.")
这不是最好的解决办法,但你可以直接使用 string
:
r = requests.get(url, params='format=json&key=site:dummy+type:example+group:wheel')
顺便说一下:
这段代码是用来把 payload
转换成这个字符串的
payload = {
'format': 'json',
'key': 'site:dummy+type:example+group:wheel'
}
payload_str = "&".join("%s=%s" % (k,v) for k,v in payload.items())
# 'format=json&key=site:dummy+type:example+group:wheel'
r = requests.get(url, params=payload_str)
编辑(2020):
你也可以使用 urllib.parse.urlencode(...)
,并设置参数 safe=':+'
,这样就可以创建一个不转换字符 :+
的字符串。
据我所知,requests
也使用 urllib.parse.urlencode(...)
来实现这个功能,但没有 safe=
的设置。
import requests
import urllib.parse
payload = {
'format': 'json',
'key': 'site:dummy+type:example+group:wheel'
}
payload_str = urllib.parse.urlencode(payload, safe=':+')
# 'format=json&key=site:dummy+type:example+group:wheel'
url = 'https://httpbin.org/get'
r = requests.get(url, params=payload_str)
print(r.text)
我使用了这个页面 https://httpbin.org/get 来进行测试。