调用Google Search Console API报keys not supported 401错误
问题根因
你的401报错是多个问题叠加导致的:
- 核心触发点:请求Search Console站点地图接口时,在URL末尾拼接了
?key=API_KEY参数。该接口不支持API密钥认证方式,当请求URL携带key参数时,服务端会优先判定你使用了不被支持的认证方案,直接返回401,和你是否在请求头里传了Bearer格式的OAuth令牌无关,和返回的报错信息描述完全对应。 - 代码逻辑bug:你定义的
YOUR_ACCESS_TOKEN是main()函数内if/else分支里的局部变量,readSiteMap()方法无法稳定获取到正确的token值,大概率拿到空值、过期的旧值,也会触发认证失败。 - 缺失校验逻辑:从本地
token.json加载凭证后,你没有做有效性校验,如果本地存储的token已经过期,直接发起请求同样会返回未认证错误。
修复步骤
- 移除接口请求URL中的
?key=API_KEY参数,该接口仅支持OAuth2令牌认证,不需要传递API key。 - 废弃全局变量隐式传递token的写法,直接把校验通过的凭证对象传入请求方法,彻底解决作用域导致的传值错误。
- 统一凭证校验逻辑:不管是加载本地存储的凭证,还是新完成授权的凭证,都先校验有效性,过期自动刷新后再发起业务请求。
修正后可运行代码
import os import requests from bs4 import BeautifulSoup from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request from requests.structures import CaseInsensitiveDict SCOPES = ['https://www.googleapis.com/auth/webmasters'] # 替换为你自己在Search Console中已验证的站点属性,必须和后台显示的完全一致(包含协议头、末尾斜杠) WEBSITE = "https://你的站点地址/" CLIENT_SECRETS_FILE = "client_secret.json" sitemaps = [] def readSiteMap(creds): # 已移除URL中的key参数 url = f"https://searchconsole.googleapis.com/webmasters/v3/sites/{WEBSITE}/sitemaps" headers = CaseInsensitiveDict() headers["Accept"] = "application/json" headers["Authorization"] = f"Bearer {creds.token}" headers["Content-Type"] = "application/json" resp = requests.get(url=url, headers=headers) if resp.status_code != 200: print("接口请求失败:", resp.json()) return sitemap_data = resp.json() first_sitemap_path = sitemap_data['sitemap'][0]['path'] xml_content = requests.get(first_sitemap_path).text soup = BeautifulSoup(xml_content, "xml") sitemap_tags = soup.find_all("sitemap") print(f"检测到的站点地图总数:{len(sitemap_tags)}") for sitemap_entry in sitemap_tags: loc_url = sitemap_entry.findNext("loc").text if "post" in loc_url: sitemaps.append(loc_url) print("抓取到的文章类站点地图列表:", sitemaps) def main(): creds = None # 加载本地已保存的授权凭证 if os.path.exists('token.json'): creds = Credentials.from_authorized_user_file('token.json', SCOPES) # 校验凭证有效性,无效则自动刷新或引导用户重新授权 if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file( CLIENT_SECRETS_FILE, SCOPES) creds = flow.run_local_server(port=0) # 把最新的有效凭证持久化存储到本地 with open('token.json', 'w') as token_file: token_file.write(creds.to_json()) # 直接传入有效凭证调用业务逻辑,避免全局变量传值问题 readSiteMap(creds) if __name__ == "__main__": main()
注意:
WEBSITE变量的值必须和Search Console后台验证的属性完全匹配,比如你验证的是带www的域名就不能写不带www的,验证的是https站点就不能写http,末尾的斜杠也要和后台保持一致,否则会出现权限不足的错误。
内容的提问来源于stack exchange,提问作者MD Rahat Islam Khan
相关产品推荐
相关产品推荐

