如何不使用Tweepy通过Twitter V2 API创建推文?代码报401错误求助
解决Twitter API请求返回401未授权错误的方案
你的代码触发401错误,核心原因是OAuth授权头不完整或不符合规范,以下是具体问题和修复方式:
核心问题分析
- OAuth头参数缺失:你构造的
Authorization头只包含了oauth_consumer_key、oauth_token和签名方法,但Twitter OAuth 1.0a要求必须包含oauth_signature、oauth_timestamp、oauth_nonce、oauth_version这些必填参数,缺少任何一个都会触发401。 - 未生成有效签名:声明了
oauth_signature_method=HMAC-SHA1,但没有生成对应的签名值。HMAC-SHA1签名需要结合消费者密钥(consumer_secret)、令牌密钥(access_token_secret)、请求方法、URL、请求参数等信息生成,不能仅声明方法。
修复方案
方案1:使用OAuth库自动处理(推荐)
用requests-oauthlib库可以自动生成完整的OAuth签名和头参数,避免手动构造出错:
from requests_oauthlib import OAuth1Session # 替换为你的实际密钥 consumer_key = "你的consumer_key" consumer_secret = "你的consumer_secret" access_token = "你的access_token" access_token_secret = "你的access_token_secret" tweet_post_url = "https://api.twitter.com/1.1/statuses/update.json" # v1.1 API地址,v2用https://api.twitter.com/2/tweets # 初始化OAuth会话 twitter = OAuth1Session( consumer_key, client_secret=consumer_secret, resource_owner_key=access_token, resource_owner_secret=access_token_secret ) # 构造请求数据(v2 API需调整参数格式) data = { "text": text, "media_ids": [media_id] } # 发送请求 tweet_response = twitter.post(tweet_post_url, json=data) print(tweet_response.json())
方案2:手动构造完整的OAuth头(不推荐,容易出错)
如果必须手动构造,需要生成所有必填参数并计算签名:
- 生成
oauth_nonce(随机字符串)、oauth_timestamp(当前Unix时间戳)、oauth_version="1.0" - 按照OAuth 1.0a规范,用HMAC-SHA1算法计算
oauth_signature - 拼接完整的Authorization头,示例代码如下:
import time import random import string import hmac import hashlib import base64 import requests # 生成随机nonce和时间戳 oauth_nonce = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(32)) oauth_timestamp = str(int(time.time())) # 替换为你的实际密钥和参数 consumer_key = "你的consumer_key" consumer_secret = "你的consumer_secret" access_token = "你的access_token" access_token_secret = "你的access_token_secret" tweet_post_url = "https://api.twitter.com/1.1/statuses/update.json" text = "你的推文内容" media_id = "你的媒体ID" # 构造参数列表用于签名(包括请求参数和OAuth参数) params = { "oauth_consumer_key": consumer_key, "oauth_token": access_token, "oauth_signature_method": "HMAC-SHA1", "oauth_timestamp": oauth_timestamp, "oauth_nonce": oauth_nonce, "oauth_version": "1.0", "text": text, "media_ids": media_id } # 按OAuth规范排序参数并拼接成字符串 sorted_params = sorted(params.items(), key=lambda x: x[0]) param_string = '&'.join([f"{k}={v}" for k, v in sorted_params]) # 构造签名基字符串 base_string = f"POST&{tweet_post_url}&{param_string}" # 生成签名密钥 signing_key = f"{consumer_secret}&{access_token_secret}" # 计算HMAC-SHA1签名并base64编码 signature = hmac.new(signing_key.encode(), base_string.encode(), hashlib.sha1).digest() oauth_signature = base64.b64encode(signature).decode() # 构造完整的Authorization头 headers = { "Authorization": f'OAuth oauth_consumer_key="{consumer_key}", oauth_token="{access_token}", oauth_signature_method="HMAC-SHA1", oauth_timestamp="{oauth_timestamp}", oauth_nonce="{oauth_nonce}", oauth_version="1.0", oauth_signature="{oauth_signature}"' } # 发送请求 data = { "text": text, "media_ids": [media_id], "tweet_mode": "extended" } tweet_response = requests.post(tweet_post_url, headers=headers, data=data) print(tweet_response.json())
额外检查项
- 确认你的
access_token拥有发布推文的权限(比如v1.1的write权限,v2的tweet.write权限),权限不足也会返回401。 - 核对所有密钥(consumer_key、consumer_secret、access_token、access_token_secret)是否和开发者平台上的一致,避免拼写或大小写错误。
- 确认
tweet_post_url是否正确,v1.1和v2 API的地址不同,参数格式也有差异。
内容的提问来源于stack exchange,提问作者Volatil3
相关产品推荐
相关产品推荐

