Google网站站长API会针对每个请求提供响应500:后端错误

时间:2017-12-28 18:47:47

标签: python api google-webmaster-tools

我自己调用谷歌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'}}

即使有推荐的指数退避&#39> 使用googles API explorer似乎工作正常:

Google screenshot

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.'}}

2 个答案:

答案 0 :(得分:1)

那么,您可以将request的内容视为文本,对吧?不仅是文本,还包含接受相对有限数量字符的文本。

考虑到这一点,这一切都归结为如何序列化"复杂"数据结构为文本。我最近回答another question关于 kinddddaaa 类似想法的文件。

如果你有一堆key=value参数,你可以使用一个简单的"技巧":

  
      
  1. 转义控件名称和值。空格字符被替换为   +,然后按照中所述对保留字符进行转义   [RFC1738],第2.2节:非字母数字字符替换为   %HH,百分号和两个十六进制数字代表   字符的ASCII码。换行符表示为"CR LF"   对(即%0D%0A)。
  2.   
  3. 控件名称/值列在   命令它们出现在文档中。该名称与。分开   值=和名称/值对彼此分开   &
  4.   

所以这个数据:

{a="foo", b="bar baz"}

可按照上述规范序列化为文本,如:a=foo&b=bar+baz

该序列化格式在application/x-www-form-urlencoded请求的标头中标识为Content-type。该请求的标题告诉服务器接收它像"嘿!我的body中的数据是按照惯例序列化的,该约定使用=符号将键与值分开,并使用&拆分键/值对,将空格更改为+。等等"

(!)非常重要:这是requests模块在​​POST上使用的格式,除非另有说明。

另一种允许更多灵活性的格式(例如维护基本类型或嵌套结构)是JSON。这是Google服务器"想要的格式,并且为了告诉服务器" text"包含在请求的主体中遵循Json标准(或约定),Content-Type标头必须设置为'application/json'

您的Google服务器在收到request时看到的内容正在检查Content-type标题,如果它不是Json,则会显示400错误" 哦,我不明白这种格式......我想要Json!"

这就是你必须指定Json标头的原因。

比较两种格式here的示例。

您也可以更清楚地看到它,因为最新版本的requests模块可以为您执行JSON解析。由于JSON格式变得如此常见,您可以通过json=参数传递Python结构中提供的数据(例如dict),模块将执行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)

输出:

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}'

看到区别? JSON能够区分字符串foo-16(使用")而不是5是一个整数,而x-www-form可以&# 39; t(查看表单编码如何区分整数 5或字符串 6)。与列表相同。通过使用字符[,服务器将能够告诉c是一个列表(和整数)

答案 1 :(得分:0)

我明白了!解决方案:

传递标题信息:

headers = {'Content-type': 'application/json',
           'Authorization' : 'Bearer %s' % access_token}

并确保将json数据转储为字符串:

r = requests.post(url,data = json.dumps(params),  headers = headers)

如果有人能解释我的答案背后的原因,那就太好了。