【问题标题】:Google Webmaster API gives Response 500: Backend Error on every requestGoogle Webmaster API 给出响应 500:每个请求的后端错误
【发布时间】:2018-01-03 04:18:00
【问题描述】:

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

即使使用推荐的“指数退避”
使用googles API explorer 似乎可以正常工作:

另外:这似乎也给出了类似的错误:

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

【问题讨论】:

  • 对于您的500 错误...不知道,真的...对于第二个,看起来(也许)您必须指定Content-Type 请求的标头是@ 987654333@?检查另一个问题:stackoverflow.com/q/9733638/289011
  • 知道你让我走上正轨!我必须传入,headers = {'Content-type': 'application/json', 'Authorization' : 'Bearer %s' % access_token} 和 json.dumps(data)

标签: python api google-search-console


【解决方案1】:

所以,您可以将request 的内容视为文本,对吗?不仅是文本,还有接受相对有限字符数的文本。

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

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

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

所以这个数据:

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

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

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

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

另一种允许更大灵活性(例如维护基本类型或嵌套结构)的格式是JSON。这是 Google 服务器“想要”的格式,为了告诉服务器请求正文中包含的“文本”遵循 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 不能(看看表单编码如何不区分 integer 5 或 string 6)。与列表相同。通过使用字符[,服务器将能够判断c 是一个列表(和整数)

【讨论】:

    【解决方案2】:

    我明白了!解决办法:

    是通过以下方式传递标题信息:

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

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

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

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

    【讨论】:

    • 您可以将您请求的内容视为“文本”,对吧?没有什么可以做的魔法:它只是文本。然后Content-type 标头告诉服务器如何 格式化文本。默认情况下,requests 模块告诉服务器格式化为 form,它(服务器)不喜欢这样:它需要 JSON,但标头说它的格式为 form。服务器没有进一步查看并拒绝它。这里有更多信息:smtpeter.com/en/documentation/json-vs-post
    • 这很有道理,如果您要写一个答案,我会非常乐意将其标记为正确答案。
    • 嗯,你真好。我做到了:-)我希望解释清楚。不知道,也许不是(也许太长了,拐弯抹角)如果您对此有更多疑问,请添加评论,以便它在我的 S.O. 中弹出。 收件箱,我会尽量回答(在我的可能性范围内,这不是……不是那么多):-/
    猜你喜欢
    • 2023-03-29
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多