我自己调用谷歌API,而不是使用他们的python库,因为我背后是一个不方便的公司代理,它杀死了他们的库,所以我必须自己做。
这很好用:
requests.get('https://www.googleapis.com/webmasters/v3/sites', params =
{'access_token':'my_access_token_here'})
另一方面,这不是:
site = https://www.my_website_from_the_above_function.com
site = urllib.parse.quote_plus(site)
def get_website_info():
url = 'https://www.googleapis.com/webmasters/v3/sites/{}/searchAnalytics/query'.format(site)
params = {
"endDate": "2017-12-10",
"startDate": "2017-12-01",
"access_token": my_access_token
}
r = requests.post(url, params = params)
return r
x = get_website_info().json()
我得到的只是这个错误代码:
{'error': {'code': 500,
'errors': [{'domain': 'global',
'message': 'Backend Error',
'reason': 'backendError'}],
'message': 'Backend Error'}}
即使推荐使用'指数退避' 使用qazxsw poi似乎工作正常:
Aditional:这也似乎给出了类似的错误:
最后:
r = requests.post(url, params = auth_params, data = json.dumps(params))
只是给
r = requests.post(url, params = auth_params, data = params)
所以,你可以把{'error': {'code': 400,
'errors': [{'domain': 'global',
'message': 'This API does not support parsing form-encoded input.',
'reason': 'parseError'}],
'message': 'This API does not support parsing form-encoded input.'}}
的内容想象成文本吧?不仅是文本,还包含接受相对有限数量字符的文本。
考虑到这一点,这一切都归结为如何将“复杂”数据结构序列化为文本。我最近回答了request
关于类似的想法的文件。
如果你有一堆another question参数,你可以使用一个简单的“技巧”:
- 控制名称和值将被转义。空格字符由
key=value
替换,然后保留字符按照+
第2.2节中的描述进行转义:非字母数字字符由[RFC1738]替换,百分号和两个十六进制数字表示字符的ASCII代码。换行符表示为%HH
对(即"CR LF"
)。- 控件名称/值按它们在文档中出现的顺序列出。该名称与
%0D%0A
的值分开,名称/值对由=
相互分隔。
所以这个数据:
&
可以按照上面的规范序列化为文本,如:{a="foo", b="bar baz"}
该序列化格式在a=foo&b=bar+baz
请求的标题中标识为application/x-www-form-urlencoded
。该请求的标题告诉服务器接收它类似“嘿!我的Content-type
中的数据是按照惯例序列化的,使用body
符号将键与值分开,并使用&拆分键/值对,通过=
更改空格... 等等”
(!)非常重要:除非另有说明,否则这是+
模块在requests
上使用的格式。
另一种允许更多灵活性的格式(例如维护基本类型或嵌套结构)是POST
。这是Google服务器“想要”的格式,并且为了告诉服务器请求主体中包含的“文本”遵循Json标准(或约定),JSON标头必须设置为Content-Type
。
你的Google服务器在收到'application/json'
时看到的是检查request
标头,如果它不是Json,它会给你一个Content-type
错误,表示“哦,我不明白这种格式......我想要Json! “
这就是你必须指定Json头的原因。
有一个例子比较两种格式400
。
您也可以更清楚地看到它,因为最新版本的here模块可以为您进行JSON解析。由于JSON格式已变得如此常见,您可以通过requests
参数传递Python结构(例如dict
)中提供的数据,模块将执行json=
并为您设置标题。这也可以让你“反省”一下身体的样子(可以更清楚地看到差异)。
看一下这个:
json.dumps
输出:
from requests import Request
data = {
'a': 'foo-1 baz',
'b': 5,
'c': [1, 2, 3],
'd': '6'
}
req = Request('POST', 'http://foo.bar', data=data)
prepped = req.prepare()
print("Normal headers: %s" % prepped.headers)
print("Normal body: %s" % prepped.body)
req = Request('POST', 'http://foo.bar', json=data)
prepped = req.prepare()
print("Json headers: %s" % prepped.headers)
print("Json body: %s" % prepped.body)
看到不同? JSON能够在字符串Normal headers: {'Content-Length': '31', 'Content-Type': 'application/x-www-form-urlencoded'}
Normal body: d=6&a=foo-1+baz&c=1&c=2&c=3&b=5
Json headers: {'Content-Length': '52', 'Content-Type': 'application/json'}
Json body: b'{"d": "6", "a": "foo-1 baz", "c": [1, 2, 3], "b": 5}'
或foo-1
(使用6
)之间产生差异,而"
是一个整数,而5
则不能(看看表单编码如何区分整数5或字符串6) 。与列表相同。通过使用字符x-www-form
,服务器将能够告诉[
是一个列表(和整数)
我知道了!解决方案:
是传递标题信息:
c
并确保将json数据转储为字符串:
headers = {'Content-type': 'application/json',
'Authorization' : 'Bearer %s' % access_token}
如果有人能解释我的答案背后的原因,那将是伟大的。