首页 文章

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

提问于
浏览
0

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

即使被推荐'Exponential backoff'
使用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 回答

  • 1

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

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

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

    转义控件名称和值 . 空格字符被替换为,然后保留字符被转义,如[RFC1738],第2.2节中所述:非字母数字字符由%HH替换,百分号和两个十六进制数字代表字符的ASCII代码 . 换行符表示为“CR LF”对(即%0D%0A) . 控件名称/值按它们在文档中出现的顺序列出 . 名称与值分隔=,名称/值对通过&分隔 .

    所以这个数据:

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

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

    该序列化格式在 Content-type 请求中标识为 application/x-www-form-urlencoded 's header. That request' s Headers 告诉服务器接收它的内容类似“嘿!我的_394511中的数据是按照约定序列化的,该约定使用 = 符号将值与值分开并拆分使用&的键/值对,通过 + 改变空格......等等

    (!) Very important: 这是 requests 模块在 POST 上使用的格式,除非另有说明 .

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

    您的Google服务器在收到 request 后正在检查的是 Content-type 标头,如果它不是Json,它会给您一个400错误,表示“哦,我不明白这种格式......我想要Json! “

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

    有一个比较两种格式here的例子 .

    您也可以更清楚地看到它,因为最新版本的 requests 模块可以为您执行JSON解析 . 由于JSON格式变得如此常见,您可以通过json=参数传递Python结构(例如 dict )中提供的数据,模块将执行 json.dumps 并为您设置 Headers . 这也允许你稍微看一下身体的样子(可以更清楚地看到差异) .

    看一下这个:

    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 可以区分整数5或字符串6) . 与列表相同 . 通过使用字符 [ ,服务器将能够告诉 c 是一个列表(和整数)

  • 0

    我知道了!解决方案:

    是传递 Headers 信息:

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

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

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

    如果有人可以解释我的答案背后的原因,那将是伟大的 .

相关问题