如何防止 Python 请求从百分比编码我的网址?

我尝试使用 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)

有没有什么方法可以传递原始形式的参数——不需要百分比编码?

谢谢!

70514 次浏览

正如设计的那样,解决方案是直接传递 URL。

这不是一个好的解决方案,但你可以直接使用 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) :

还可以使用带参数 safe=':+'urllib.parse.urlencode(...)创建字符串,而不用转换字符 :+

据我所知,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页来测试它。

如果将来其他人遇到这种情况,您可以对请求进行子类化。会话,重写 send 方法,并更改原始 URL,以修复百分比编码等。 欢迎对以下内容进行更正。

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.")

上面的答案对我不起作用。

我尝试在参数包含管道的地方执行 get 请求,但是 python 请求也会对管道进行百分比编码。那么 相反,我使用了 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'

请看看这个 Github 链接中的第一个选项。您可以忽略 urlibpart,它的意思是 prep.url = url而不是 prep.url = url + qry

从请求版本2.26开始,上述所有解决方案似乎都不再起作用了。来自 GitHub 回购的建议解决方案似乎是围绕 PreparedRequest 使用工作。

下面的方法对我很有效。确保 URL 是可解析的,所以不要使用“ this-is-not-a-domain.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