我正在使用Spotify API的python包装器。
https://spotipy.readthedocs.io/en/latest/#installation
作为授权过程的一部分,Spotify API允许用户在其默认Web浏览器中登录Spotify,然后将其发送到预定义(当您使用Spotify注册应用程序时)REDIRECT_URI。此REDIRECT_URI目前设置为localhost:6969。登录后,它会生成一个输入()(输入死亡),您可以将重定向的URI复制粘贴到命令提示符中。
我真的不想让随机的人使用命令提示符。
目标是在localhost上打开一个烧瓶服务器:6969(起诉我),然后双击它的/ authorize页面(发送到oauth2登录然后捕获代码)
http://flask.pocoo.org/docs/1.0/
所以 -
我保留了我的Flask装备并在jflask.py中找到捕手:
from flask import Flask, request, redirect, session
from requests_oauth2 import OAuth2
from spotipy import Spotify
import spotipy.util as util
import requests
import datetime
app = Flask(__name__)
spotify_auth = OAuth2(
client_id='e33c6fa0d6a249ccafa232a9cf62a616',
client_secret='a43b0b6a4de14b97b4e468459e0f7824',
redirect_uri="http://localhost:6969/authorize",
site="https://accounts.spotify.com",
authorization_url="/authorize",
token_url="/api/token",
scope_sep=" "
)
# and then use this url as a link within a public login view
print(spotify_auth.authorize_url(
scope=["user-read-recently-played", "user-top-read"],
response_type="code"
)
)
# and have an authorize route that can direct you to Spotify or handle you
#being redirected back here from Spotify
@app .route('/authorize')
def authorize():
print('triggered')
error = request.args.get("error")
if error:
abort(404)
code = request.args.get("code")
if code:
data = spotify_auth.get_token(
code=code,
grant_type="authorization_code",
)
access_token = data["access_token"]
refresh_token = data["refresh_token"]
scopes = data["scope"].split()
self.sp = spotipy.Spotify(auth=access_token)
print(access_token)
return self.sp
else:
print('code aint defined hoe')
return redirect(spotify_auth.authorize_url(
scope=["user-read-recently-played", "user-top-read"],
response_type="code",
#state=session['state']
))
if __name__ == '__main__':
app.run(host='localhost', port=6969)
我用master.py生成它:
from subprocess import Popen, PIPE
import webbrowser
jflask=Popen(['python', 'jflask.py'])
webbrowser.open('http://localhost:6969/authorize')
我已经尝试过使用带有stdout = PIPE的Popen。经过进一步的研究,我很确定这也抑制了我的成功。该规范旨在与subprocess.communicate()一起使用
https://docs.python.org/3/library/subprocess.html#subprocess.PIP
感谢大家的帮助。
Spotipy的prompt_for_user_token
方法是一种快速而简单的方法,允许在本地使用该模块的人启动并运行,并且如果您希望任意用户能够通过以下任意用户进行身份验证,则不应将其作为直接构建的代码。网站。由于你有一个Flask应用程序,你应该拥有它,而你的Spotipy代码直接通过导入而不是使用管道和标准i / o进行交互。
要研究的一些事情是:
spotipy.Spotify
会话)之外,将auth传递给requests
的替代方法。这些其他方法允许Spotipy客户端在访问中途到期时刷新访问令牌,处理用户撤销等。# import Flask things, requests-oauth2,
from requests_oauth2 import OAuth2
from spotipy import Spotify
from flask import redirect
spotify_auth = OAuth2(
client_id=os.environ["SPOTIFY_CLIENT_ID"],
client_secret=os.environ["SPOTIFY_CLIENT_SECRET"],
redirect_uri=f"http://{os.environ['HOST_NAME']}/authorize",
site="https://accounts.spotify.com",
authorization_url="/authorize",
token_url="/api/token",
scope_sep=" "
)
# and then use this url as a link within a public login view
spotify_auth.authorize_url(
scope=["user-read-recently-played", "user-top-read"],
response_type="code"
)
# and have an authorize route that can direct you to Spotify or handle you being redirected back here from Spotify
@app.route('/authorize')
def authorize():
error = request.args.get("error")
if error:
abort(404)
code = request.args.get("code")
if code:
data = spotify_auth.get_token(
code=code,
grant_type="authorization_code",
)
access_token = data["access_token"]
refresh_token = data["refresh_token"]
scopes = data["scope"].split()
spotify_client = spotipy.Spotify(auth=access_token)
else:
return redirect(spotify_auth.authorize_url(
scope=["user-read-recently-played", "user-top-read"],
response_type="code",
state=session['state']
))
在第一次访问/authorize
时,它会将用户重定向到Spotify的登录页面。但是当用户在那里成功登录时,它会将用户重定向回Flask站点(返回/authorize
),而不是执行prompt_for_user_token()
的复制/粘贴部分。
一旦他们回到/authorize
,这次有一个code
请求参数 - 因此它使OAuth2 Client-to-Provider请求将此代码转换为访问令牌。
这和prompt_for_user_token
都遵循相同的方法:
prompt_for_user_token
通过从不存在的网页复制/粘贴URL来执行此操作。我可能已经对这段代码进行了一些屠杀,因为它是从我的Spotsk集成的旧Flask实现中挑选出来的。这是一个more complete gist,但我很确定很多SQLAlchemy的东西,授权视图,非常糟糕,所以拿一点盐。
您可以尝试修改util模块。用其中的response = raw_input()替换try-except块:
response = sys.stdin.readline().strip()
如果尚未导入sys,请不要忘记导入sys。
这应该允许正常的PIPE。
或者您可以使用pexpect库而不是子进程模块。它知道如何处理调整终端的fcntl标志或在Windows上使用mscvrt的输入。
此外,在PIPE-ing数据时,不要忘记raw_input(),input()或sys.stdin.readline()在收到适当的行尾字符之前不会返回。 “\ r”,“\ n”或“\ r \ n”。您之前是否使用授权URL发送了它?