chore:update publish.yml

This commit is contained in:
2061360308 2023-12-20 00:50:12 +08:00
parent f34639a9ce
commit fb1d5fa298
14 changed files with 327 additions and 75 deletions

View File

@ -1,5 +1,5 @@
[bumpversion] [bumpversion]
current_version = 0.1.8 current_version = 0.1.7
commit = True commit = True
tag = True tag = True

View File

@ -46,7 +46,7 @@ jobs:
- name: Build a binary wheel and a source tarball - name: Build a binary wheel and a source tarball
run: | run: |
cd package cd package
python setup.py build python setup.py upload
ls ./dist/ ls ./dist/
- name: Publish distribution 📦 to PyPI - name: Publish distribution 📦 to PyPI

View File

@ -17,6 +17,7 @@ Description-Content-Type: text/markdown
License-File: LICENSE License-File: LICENSE
# NeteaseCloudMusic_PythonSDK # NeteaseCloudMusic_PythonSDK
> 基于 [ NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi) 封装的 Python SDK。 > 基于 [ NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi) 封装的 Python SDK。
> 网易云API Python版本。 > 网易云API Python版本。
@ -54,15 +55,48 @@ print(api_list())
> 注意: request(self, name, query=None) 的第一个参数为API名称第二个参数为API参数具体API名称和参数请参考 [NeteaseCloudMusicApi文档](https://docs.neteasecloudmusicapi.binaryify.com)name支持`/song/url/v1`和`song_url_v1`两种写法。 > 注意: request(self, name, query=None) 的第一个参数为API名称第二个参数为API参数具体API名称和参数请参考 [NeteaseCloudMusicApi文档](https://docs.neteasecloudmusicapi.binaryify.com)name支持`/song/url/v1`和`song_url_v1`两种写法。
> api已加入自动缓存在测试接口时如果频繁调用获取结果在query里应该加上timestamp参数来区分例如
> ```python
> response = netease_cloud_music_api.request("song_url_v1", {"id": 33894312, "level": "exhigh", "timestamp": time.time()})
> ```
### 开发 ### 开发
- 克隆项目 `git clone git@github.com:2061360308/NeteaseCloudMusic_PythonSDK.git` - 克隆项目 `git clone git@github.com:2061360308/NeteaseCloudMusic_PythonSDK.git`
- 安装依赖 `pip install -r requirements.txt` - 安装依赖 `pip install -r requirements.txt`
- 目录/文件说明 - 目录/文件说明
```
├── package 项目包根目录 ├── package 项目包根目录
├── test_gender 生成测试代码的脚本 ├── test_gender 生成测试代码的脚本
├── test.py 手动测试/ 使用示例 ├── test.py 手动测试/ 使用示例
```
### 更新
项目使用towncrier自动生成更新日志
在 newsfragments 目录下,创建一个新的文本文件。这个文件的名字应该是一个唯一的编号,后缀是 .rst。
例如,如果你正在处理编号为 123 的问题,你可以创建一个名为 123.feature.rst 的文件。
注意在 towncrier 中,新闻片段的类型通常由文件名的后缀决定。以下是一些常见的新闻片段类型:
- .feature: 用于描述新的特性或者功能。
- .bugfix: 用于描述一个 bug 修复。
- .doc: 用于描述文档的更改。
- .removal: 用于描述移除的特性或者功能。
- .misc: 用于描述其他类型的更改。
-
在这个文件中,写下你的更改的描述。这个描述应该是简短的,通常只有一到两句话。
例如`Added support for the XYZ feature.`
### 发布新版本
使用bumpversion自动更新版本号提交并发布标签
你需要安装bumpversion然后执行
```bash
bumpversion patch # for a patch level increase (e.g., 1.0.0 to 1.0.1)
bumpversion minor # for a minor level increase (e.g., 1.0.0 to 1.1.0)
bumpversion major # for a major level increase (e.g., 1.0.0 to 2.0.0)
```
接下来会自动更新版本号并提交到远程仓库,然后发布一个新的标签
workflow会依据标签自动发布相应资源并且发布到pypi
### 改进 ### 改进
> 下列API未支持 > 下列API未支持
@ -107,3 +141,8 @@ print(api_list())
- /fm_trash - /fm_trash
### 欢迎提交PR ### 欢迎提交PR
更正request库返回多个cookie时自动用分号拼接导致后续cookie不好解析的问题
添加了对cookie中Max-Age为0的处理
改进判断cookie是否过期的逻辑
添加了自动处理cookie的更新操作

View File

@ -7,6 +7,7 @@ NeteaseCloudMusic/__init__.py
NeteaseCloudMusic/config.json NeteaseCloudMusic/config.json
NeteaseCloudMusic/help.py NeteaseCloudMusic/help.py
NeteaseCloudMusic/main.py NeteaseCloudMusic/main.py
NeteaseCloudMusic/utils.py
NeteaseCloudMusic.egg-info/PKG-INFO NeteaseCloudMusic.egg-info/PKG-INFO
NeteaseCloudMusic.egg-info/SOURCES.txt NeteaseCloudMusic.egg-info/SOURCES.txt
NeteaseCloudMusic.egg-info/dependency_links.txt NeteaseCloudMusic.egg-info/dependency_links.txt

View File

@ -1,2 +1,3 @@
py_mini_racer py_mini_racer
requests requests
diskcache

View File

@ -2,4 +2,4 @@ from .main import NeteaseCloudMusicApi
from .help import api_help, api_list from .help import api_help, api_list
from .utils import format_cookie_str, prase_cookie_str from .utils import format_cookie_str, prase_cookie_str
__version__ = '0.1.8' __version__ = '0.1.7'

View File

@ -35,15 +35,48 @@ print(api_list())
> 注意: request(self, name, query=None) 的第一个参数为API名称第二个参数为API参数具体API名称和参数请参考 [NeteaseCloudMusicApi文档](https://docs.neteasecloudmusicapi.binaryify.com)name支持`/song/url/v1`和`song_url_v1`两种写法。 > 注意: request(self, name, query=None) 的第一个参数为API名称第二个参数为API参数具体API名称和参数请参考 [NeteaseCloudMusicApi文档](https://docs.neteasecloudmusicapi.binaryify.com)name支持`/song/url/v1`和`song_url_v1`两种写法。
> api已加入自动缓存在测试接口时如果频繁调用获取结果在query里应该加上timestamp参数来区分例如
> ```python
> response = netease_cloud_music_api.request("song_url_v1", {"id": 33894312, "level": "exhigh", "timestamp": time.time()})
> ```
### 开发 ### 开发
- 克隆项目 `git clone git@github.com:2061360308/NeteaseCloudMusic_PythonSDK.git` - 克隆项目 `git clone git@github.com:2061360308/NeteaseCloudMusic_PythonSDK.git`
- 安装依赖 `pip install -r requirements.txt` - 安装依赖 `pip install -r requirements.txt`
- 目录/文件说明 - 目录/文件说明
```
├── package 项目包根目录 ├── package 项目包根目录
├── test_gender 生成测试代码的脚本 ├── test_gender 生成测试代码的脚本
├── test.py 手动测试/ 使用示例 ├── test.py 手动测试/ 使用示例
```
### 更新
项目使用towncrier自动生成更新日志
在 newsfragments 目录下,创建一个新的文本文件。这个文件的名字应该是一个唯一的编号,后缀是 .rst。
例如,如果你正在处理编号为 123 的问题,你可以创建一个名为 123.feature.rst 的文件。
注意在 towncrier 中,新闻片段的类型通常由文件名的后缀决定。以下是一些常见的新闻片段类型:
- .feature: 用于描述新的特性或者功能。
- .bugfix: 用于描述一个 bug 修复。
- .doc: 用于描述文档的更改。
- .removal: 用于描述移除的特性或者功能。
- .misc: 用于描述其他类型的更改。
-
在这个文件中,写下你的更改的描述。这个描述应该是简短的,通常只有一到两句话。
例如`Added support for the XYZ feature.`
### 发布新版本
使用bumpversion自动更新版本号提交并发布标签
你需要安装bumpversion然后执行
```bash
bumpversion patch # for a patch level increase (e.g., 1.0.0 to 1.0.1)
bumpversion minor # for a minor level increase (e.g., 1.0.0 to 1.1.0)
bumpversion major # for a major level increase (e.g., 1.0.0 to 2.0.0)
```
接下来会自动更新版本号并提交到远程仓库,然后发布一个新的标签
workflow会依据标签自动发布相应资源并且发布到pypi
### 改进 ### 改进
> 下列API未支持 > 下列API未支持
@ -88,3 +121,8 @@ print(api_list())
- /fm_trash - /fm_trash
### 欢迎提交PR ### 欢迎提交PR
更正request库返回多个cookie时自动用分号拼接导致后续cookie不好解析的问题
添加了对cookie中Max-Age为0的处理
改进判断cookie是否过期的逻辑
添加了自动处理cookie的更新操作

View File

@ -44,6 +44,7 @@ if (typeof window === "undefined") {
} }
function encodeURIComponent(str) { function encodeURIComponent(str) {
str = String(str); // 将输入转换为字符串 以免TrueFalse等非字符无法转换
var result = ""; var result = "";
if (str !== undefined && str !== null) { if (str !== undefined && str !== null) {
@ -37928,7 +37929,7 @@ const hug_comment_resourceTypeMap = config_namespaceObject.A;
}); });
;// CONCATENATED MODULE: ./package.json ;// CONCATENATED MODULE: ./package.json
const package_namespaceObject = {"i8":"0.1.1"}; const package_namespaceObject = {"i8":"0.1.2"};
;// CONCATENATED MODULE: ./module/inner_version.js ;// CONCATENATED MODULE: ./module/inner_version.js
/* harmony default export */ const inner_version = ((query, request) => { /* harmony default export */ const inner_version = ((query, request) => {
@ -38338,30 +38339,19 @@ var crypto_js = __webpack_require__(1292);
;// CONCATENATED MODULE: ./module/login_refresh.js ;// CONCATENATED MODULE: ./module/login_refresh.js
// 登录刷新 // 登录刷新
/* harmony default export */ const login_refresh = (async (query, request) => { /* harmony default export */ const login_refresh = ((query, request) => {
let result = await request( return request(
'POST', "POST",
`https://music.163.com/weapi/login/token/refresh`, `https://music.163.com/weapi/login/token/refresh`,
{}, {},
{ {
crypto: 'weapi', crypto: "weapi",
ua: 'pc', ua: "pc",
cookie: query.cookie, cookie: query.cookie,
proxy: query.proxy, proxy: query.proxy,
realIP: query.realIP, realIP: query.realIP,
},
)
if (result.body.code === 200) {
result = {
status: 200,
body: {
...result.body,
cookie: result.cookie.join(';'),
},
cookie: result.cookie,
} }
} );
return result
}); });
;// CONCATENATED MODULE: ./module/login_status.js ;// CONCATENATED MODULE: ./module/login_status.js
@ -42852,6 +42842,7 @@ const weapi = (object) => {
for (let i = 0; i < 16; i++) { for (let i = 0; i < 16; i++) {
secretKey += base62.charAt(Math.round(Math.random() * 61)) secretKey += base62.charAt(Math.round(Math.random() * 61))
} }
return { return {
params: aesEncrypt( params: aesEncrypt(
aesEncrypt(text, 'cbc', presetKey, iv), aesEncrypt(text, 'cbc', presetKey, iv),
@ -43181,6 +43172,27 @@ function beforeRequest(name, query) {
return response; return response;
}); });
;// CONCATENATED MODULE: ./afterRequest/login_refresh.js
/* harmony default export */ const afterRequest_login_refresh = ((response) => {
response = JSON.parse(response);
let cookie = response.cookie;
if (Array.isArray(cookie)) {
cookie = cookie.join(";");
}
if (response.body.code === 200) {
response = {
status: 200,
body: {
...response.body,
cookie: cookie,
},
cookie: cookie,
};
}
return response;
});
;// CONCATENATED MODULE: ./afterRequest/login_status.js ;// CONCATENATED MODULE: ./afterRequest/login_status.js
/* harmony default export */ const afterRequest_login_status = ((response) => { /* harmony default export */ const afterRequest_login_status = ((response) => {
response = JSON.parse(response); response = JSON.parse(response);
@ -43255,9 +43267,11 @@ function beforeRequest(name, query) {
/* harmony default export */ const afterRequestApi = ({ /* harmony default export */ const afterRequestApi = ({
'check_music':afterRequest_check_music, 'check_music':afterRequest_check_music,
'login_cellphone':afterRequest_login_cellphone, 'login_cellphone':afterRequest_login_cellphone,
'login_refresh':afterRequest_login_refresh,
'login_status':afterRequest_login_status, 'login_status':afterRequest_login_status,
'related_playlist':afterRequest_related_playlist, 'related_playlist':afterRequest_related_playlist,
'top_playlist':afterRequest_top_playlist, 'top_playlist':afterRequest_top_playlist,

View File

@ -1,2 +1,5 @@
from .main import NeteaseCloudMusicApi from .main import NeteaseCloudMusicApi
from .help import api_help, api_list from .help import api_help, api_list
from .utils import format_cookie_str, prase_cookie_str
__version__ = '0.1.7'

View File

@ -1,26 +1,36 @@
import json import json
import os.path import os.path
import socket import socket
import time
from pprint import pprint from pprint import pprint
import http.cookies import http.cookies
import datetime import datetime
from diskcache import Cache
import pkg_resources import pkg_resources
import requests import requests
from py_mini_racer import py_mini_racer from py_mini_racer import py_mini_racer
from .help import api_list from .help import api_list
from .utils import format_cookie_str, prase_cookie_str
import urllib.parse
class NeteaseCloudMusicApi: class NeteaseCloudMusicApi:
__cookie = None __cookie = None
__ip = None __ip = None
def __init__(self, debug=False): cache = Cache('cache', timeout=120) # 设置缓存目录和过期时间
# cache = TTLCache(maxsize=100, ttl=120) # 设置缓存大小为100缓存项的生存时间为120秒
def __init__(self, debug=False, cache=False):
self.DEBUG = debug # 是否开启调试模式 self.DEBUG = debug # 是否开启调试模式
self.CACHE = cache # 是否开启缓存
self.special_api = {"/playlist/track/all": self.playlist_track_all, self.special_api = {"/playlist/track/all": self.playlist_track_all,
"/login/cellphone": self.login_cellphone, "/login/cellphone": self.login_cellphone,
"/inner/version": self.inner_version} "/inner/version": self.inner_version,
"/login/refresh": self.login_refresh}
# 载入js代码 # 载入js代码
resource_path = pkg_resources.resource_filename(__name__, 'NeteaseCloudMusicApi.js') resource_path = pkg_resources.resource_filename(__name__, 'NeteaseCloudMusicApi.js')
@ -66,8 +76,21 @@ class NeteaseCloudMusicApi:
if name not in yubei_special.values(): if name not in yubei_special.values():
raise Exception(f"apiName: {name} not foundplease use ”api_list()“ to view the interface list") raise Exception(f"apiName: {name} not foundplease use ”api_list()“ to view the interface list")
# 生成一个唯一的键,用于在缓存中查找结果
cache_key = (name, frozenset(query.items()) if query else None)
if self.CACHE:
# 检查缓存中是否已经有了结果
if self.cache.get(cache_key):
return self.cache.get(cache_key)
if query is None: if query is None:
query = {} query = {}
else:
# 如果存在timestamp参数那么删除它
if query.get("timestamp"):
del query["timestamp"]
if query.get("cookie") is None: if query.get("cookie") is None:
query["cookie"] = self.cookie query["cookie"] = self.cookie
@ -82,7 +105,9 @@ class NeteaseCloudMusicApi:
else: else:
result = self.call_api(name, query) result = self.call_api(name, query)
# if self.CACHE:
# 将结果存入缓存
self.cache.set(cache_key, result)
return result return result
@ -105,46 +130,47 @@ class NeteaseCloudMusicApi:
if self.__cookie is None: if self.__cookie is None:
if os.path.isfile("cookie_storage"): if os.path.isfile("cookie_storage"):
with open("cookie_storage", "r", encoding='utf-8') as f: with open("cookie_storage", "r", encoding='utf-8') as f:
self.cookie = f.read() content = f.read()
try:
cookie_storage = json.loads(content)
# 验证cookie是否过期
create_time_stamp = cookie_storage['create_time_stamp']
if time.time() - create_time_stamp > 1296010:
# cookie过期了
self.__cookie = ""
else:
# 判断cookie生成时间是否超过1天
if time.time() - create_time_stamp > 86400:
# 更新cookie
# Todo login_refresh接口返回cookie好像少一些值
# self.request("/login/refresh", {"cookie": cookie_storage['cookie'], "timestamp": time.time()})
self.cookie = cookie_storage['cookie']
else:
self.__cookie = cookie_storage['cookie']
except json.JSONDecodeError and KeyError:
self.__cookie = ""
else: else:
self.__cookie = "" # 如果没有cookie文件就设置为空 self.__cookie = "" # 如果没有cookie文件就设置为空
return self.__cookie return self.__cookie
@cookie.setter @cookie.setter
def cookie(self, cookie): def cookie(self, value):
if cookie is None: if value is None:
cookie = "" self.__cookie = ""
return
_cookie = cookie "判断cookie是否合法, 简单检查一下关键的键"
necessary_keys = ["__csrf", "MUSIC_A_T", "MUSIC_R_T"]
cookie_dict = prase_cookie_str(value)
for key in necessary_keys:
if cookie_dict.get(key) is None:
raise Exception(f"cookie is illegal, missing key: {key}.")
'''判断cookie是否过期''' self.__cookie = value
# 创建一个Morsel对象它可以解析cookie字符串
morsel = http.cookies.SimpleCookie(cookie)
# 获取当前时间
now = datetime.datetime.now()
# 只判断 __csrf 是否过期
if not morsel.get('__csrf'):
# __csrf 不存在不是有效cookie
_cookie = ""
else:
# 将过期时间字符串转换为datetime对象
expires = morsel.get('__csrf')['expires']
expires_datetime = datetime.datetime.strptime(expires, "%a, %d %b %Y %H:%M:%S GMT")
# 判断cookie是否过期
if now > expires_datetime:
# 过期了
_cookie = ""
else:
# 未过期
pass
self.__cookie = _cookie
with open("cookie_storage", "w+", encoding='utf-8') as f: with open("cookie_storage", "w+", encoding='utf-8') as f:
f.write(_cookie) f.write(json.dumps({"cookie": value, "create_time_stamp": time.time()}, indent=2, ensure_ascii=False))
@property @property
def ip(self): def ip(self):
@ -155,18 +181,17 @@ class NeteaseCloudMusicApi:
def call_api(self, name, query): def call_api(self, name, query):
request_param = self.ctx.call('NeteaseCloudMusicApi.beforeRequest', name, query) # 拿到请求头和请求参数 request_param = self.ctx.call('NeteaseCloudMusicApi.beforeRequest', name, query) # 拿到请求头和请求参数
# Todo 了解 py_mini_racer 返回没有自动编码 而 node可以
param_data = {} param_data = {}
if request_param["data"] != "": if request_param["data"] != "":
for item in request_param["data"].split("&"): for item in request_param["data"].split("&"):
# param_data[item.split("=")[0]] = urllib.parse.quote(item.split("=")[1], safe='') # 不需要编码后反而出错
param_data[item.split("=")[0]] = item.split("=")[1] param_data[item.split("=")[0]] = item.split("=")[1]
# print("url", request_param["url"], "data", param_data, "headers\n", json.dumps(request_param["headers"], indent=2, ensure_ascii=False))
if request_param.get("method") == "GET": if request_param.get("method") == "GET":
response = requests.get(request_param["url"], params=param_data, headers=request_param["headers"]) response = requests.get(request_param["url"], params=param_data, headers=request_param["headers"])
else: else:
response = requests.post(request_param["url"], data=param_data, headers=request_param["headers"]) response = requests.post(request_param["url"], data=param_data, headers=request_param["headers"])
# response = requests.post(request_param["url"], data=param_data, headers=request_param["headers"])
try: try:
data = json.loads(response.text) data = json.loads(response.text)
@ -179,12 +204,6 @@ class NeteaseCloudMusicApi:
"status": response.status_code, "status": response.status_code,
} }
# print("headers", response.headers)
# print("headers_dict", dict(response.headers))
# with open("response_result.json", "w+", encoding='utf-8') as f:
# f.write(json.dumps(response_result, indent=2, ensure_ascii=False))
result = self.ctx.call('NeteaseCloudMusicApi.afterRequest', result = self.ctx.call('NeteaseCloudMusicApi.afterRequest',
json.dumps(response_result), json.dumps(response_result),
request_param.get('crypto', None), request_param.get('crypto', None),
@ -230,8 +249,29 @@ class NeteaseCloudMusicApi:
""" """
result = self.call_api("/login/cellphone", query) result = self.call_api("/login/cellphone", query)
# 自动 填充cookie # 自动 更新cookie
if result["code"] == 200: if result["code"] == 200:
if result.get("data").get("cookie"): if result.get("data").get("cookie"):
self.cookie = result.get("data").get("cookie") # cookie_str = format_cookie_str(result.get("data").get("cookie"))
cookie_str = result.get("data").get("cookie")
result["data"]["cookie"] = cookie_str
self.cookie = cookie_str
return result
def login_refresh(self, query):
"""
刷新登录状态
:param query:
:return:
"""
result = self.call_api("/login/refresh", query)
# 自动 更新cookie
# if result["code"] == 200:
# if result.get("data").get("cookie"):
# # cookie_str = format_cookie_str(result.get("data").get("cookie"))
# cookie_str = result.get("data").get("cookie")
# result["data"]["cookie"] = cookie_str
# pprint(cookie_str)
# self.cookie = cookie_str
return result return result

View File

@ -0,0 +1,124 @@
from pprint import pprint
def format_cookie_str(cookie_str: str) -> str:
"""
格式化cookie字符串
功能
处理以逗号分割的cookie字符串
删除max-age为0的cookie
注意
传入cookie字符串必须是以 逗号+空格 分号+空格 分割的规范cookie字符串
:param cookie_str:
:return: 格式化后的cookie str
"""
if not cookie_str:
return ""
# 解析cookie字符串
cookie_dict = prase_cookie_str(cookie_str)
cookie_valid_dict = {}
# 删除max-age为0的cookie
for item in cookie_dict.keys():
max_age = cookie_dict[item].get("Max-Age")
if max_age:
max_age = int(max_age)
if max_age != 0:
cookie_valid_dict[item] = cookie_dict[item]
# 重新拼接cookie字符串
cookie = ""
for item in cookie_valid_dict.keys():
cookie += item + "=" + cookie_valid_dict[item]["value"] + "; "
for key in cookie_valid_dict[item].keys():
if key != "value":
cookie += key + "=" + cookie_valid_dict[item][key] + "; "
return cookie[: -2]
def prase_cookie_str(cookie_str: str) -> dict:
"""
解析cookie字符串
功能
处理以逗号分割的cookie字符串
注意
传入cookie字符串必须是以 逗号+空格 分号+空格 分割的规范cookie字符串
:param cookie_str:
:return: cookie dict
"""
if not cookie_str:
return {}
# 解决用逗号分割的问题
cookie_part = []
for item in cookie_str.split(", "):
cookie_part.extend(item.split("; "))
cookies = []
for item in cookie_part:
if "=" not in item:
# 属于上一个cookie的一部分
cookies[-1] = cookies[-1] + item
else:
cookies.append(item)
cookie_dict = {}
current_name = ""
for cookie in cookies:
# print(cookie)
if cookie[-1] == "=":
name = cookie[:-1]
value = ""
else:
part = cookie.split("=")
name = part[0]
value = part[1]
if name in ["Max-Age", "Expires", "Path", "Domain"]:
cookie_dict[current_name][name] = value
else:
cookie_dict[name] = {"value": value}
current_name = name
return cookie_dict
if __name__ == '__main__':
cookie = ("MUSIC_R_T=1579622000495; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; "
"Path=/openapi/clientlog; Domain=.music.163.com, MUSIC_A_T=1579621885297; Max-Age=2147483647; Expires=Wed, "
"02 Jan 2092 11:39:38 GMT; Path=/wapi/feedback; Domain=.music.163.com, __remember_me=true; "
"Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; Path=/; Domain=.music.163.com, "
"MUSIC_A_T=1579621885297; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; Path=/api/feedback; "
"Domain=.music.163.com, MUSIC_A_T=1579621885297; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; "
"Path=/eapi/clientlog; Domain=.music.163.com, MUSIC_A_T=1579621885297; Max-Age=2147483647; Expires=Wed, "
"02 Jan 2092 11:39:38 GMT; Path=/api/clientlog; Domain=.music.163.com, MUSIC_R_T=1579622000495; "
"Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; Path=/wapi/feedback; Domain=.music.163.com, "
"MUSIC_A_T=1579621885297; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; Path=/weapi/clientlog; "
"Domain=.music.163.com, MUSIC_R_T=1579622000495; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; "
"Path=/neapi/feedback; Domain=.music.163.com, MUSIC_R_T=1579622000495; Max-Age=2147483647; Expires=Wed, "
"02 Jan 2092 11:39:38 GMT; Path=/eapi/clientlog; Domain=.music.163.com, MUSIC_R_T=1579622000495; "
"Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; Path=/api/feedback; Domain=.music.163.com, "
"MUSIC_A_T=1579621885297; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; Path=/weapi/feedback; "
"Domain=.music.163.com, MUSIC_R_T=1579622000495; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; "
"Path=/eapi/feedback; Domain=.music.163.com, MUSIC_A_T=1579621885297; Max-Age=2147483647; Expires=Wed, "
"02 Jan 2092 11:39:38 GMT; Path=/neapi/clientlog; Domain=.music.163.com, MUSIC_R_T=1579622000495; "
"Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; Path=/wapi/clientlog; Domain=.music.163.com, "
"MUSIC_A_T=1579621885297; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; Path=/wapi/clientlog; "
"Domain=.music.163.com, MUSIC_R_T=1579622000495; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; "
"Path=/weapi/feedback; Domain=.music.163.com, NMTID=00OLqRn-wykrFFXdElLpZA3_-aaQtIAAAGMbJSp9A; "
"Max-Age=315360000; Expires=Mon, 12 Dec 2033 08:25:31 GMT; Path=/; Domain=music.163.com, "
"__csrf=4d5e515015723fd3d7edaa5b05f35b4d; Max-Age=1296010; Expires=Sat, 30 Dec 2023 08:25:41 GMT; Path=/; "
"Domain=.music.163.com, MUSIC_R_T=1579622000495; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; "
"Path=/neapi/clientlog; Domain=.music.163.com, MUSIC_A_T=1579621885297; Max-Age=2147483647; Expires=Wed, "
"02 Jan 2092 11:39:38 GMT; Path=/openapi/clientlog; Domain=.music.163.com, MUSIC_A_T=1579621885297; "
"Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; Path=/eapi/feedback; Domain=.music.163.com, "
"MUSIC_R_T=1579622000495; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; Path=/weapi/clientlog; "
"Domain=.music.163.com, MUSIC_R_T=1579622000495; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; "
"Path=/api/clientlog; Domain=.music.163.com, MUSIC_SNS=; Max-Age=0; Expires=Fri, 15 Dec 2023 08:25:31 GMT; "
"Path=/, "
"MUSIC_U=00CCEEF2F7A9825637C9869A455B5CA8E009D905415134A7EDAC2E404A940B2D58BFF7129A413193E9A8FD6D1D497E1E8E9023611BA91D2CB28FA94B53DBE4C42699A30FF1448C8EFAF5B00E73ADD353C52F2E004C094AEAC4BA4D83C6FFBB4CD532DEEAEA8D5584E69AC78110BBA682829C263DA72F5AA290AD826A47F640CA3903AC652E4DDE946ACC4EB8A63E5853FA695B480A919CF84498B7084C5CA9A91297F2CF5AF45C2D545AC0D5C03A1641306BAC0FB6FFD57BC653A91F2483FB52BFE85DE39280B012BC036DF244883D9700480E5FDDCD5A417C60241AE08CD6AA84BFC1C8890AE4A08286144D9D1146E33C67CF7797CDB5A961C85DB5AC492B232601D80D4DB07E4F170F635ABC01E080B4D32408FA0698DAD95AD80CDB99F2F672638048F5116214319175B596BF68B2A7A0269746EABFD919D62C165353725E6B1253A7C5D6774D453DDDCC28524D3378; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; Path=/; Domain=.music.163.com, MUSIC_A_T=1579621885297; Max-Age=2147483647; Expires=Wed, 02 Jan 2092 11:39:38 GMT; Path=/neapi/feedback; Domain=.music.163.com")
pprint(prase_cookie_str(cookie))

Binary file not shown.

View File

@ -19,7 +19,7 @@ URL = 'https://github.com/2061360308/NeteaseCloudMusic_PythonSDK'
EMAIL = '2061360308@qq.com' EMAIL = '2061360308@qq.com'
AUTHOR = '盧瞳' AUTHOR = '盧瞳'
REQUIRES_PYTHON = '>=3.6.0' REQUIRES_PYTHON = '>=3.6.0'
VERSION = '0.1.8' VERSION = '0.1.7'
UPDATA_INFO = ('修复了初次使用时没有cookie导致的一系列问题\n' UPDATA_INFO = ('修复了初次使用时没有cookie导致的一系列问题\n'
'修复了NeteaseCloudMusicApi.js没有更新的问题\n' '修复了NeteaseCloudMusicApi.js没有更新的问题\n'
'添加了对于cookie的判断现在可以正常判断cookie是否过期了') '添加了对于cookie的判断现在可以正常判断cookie是否过期了')
@ -114,13 +114,6 @@ class UploadCommand(Command):
self.status('Building Source and Wheel (universal) distribution…') self.status('Building Source and Wheel (universal) distribution…')
os.system('{0} setup.py sdist bdist_wheel --universal'.format(sys.executable)) os.system('{0} setup.py sdist bdist_wheel --universal'.format(sys.executable))
self.status('Uploading the package to PyPI via Twine…')
os.system('twine upload dist/*')
self.status('Pushing git tags…')
os.system(f'git tag -a {about["__version__"]} -m {UPDATA_INFO}')
os.system('git push --tags')
sys.exit() sys.exit()
@ -193,6 +186,5 @@ setup(
# $ setup.py publish support. # $ setup.py publish support.
cmdclass={ cmdclass={
'upload': UploadCommand, 'upload': UploadCommand,
'build': BuildCommand,
}, },
) )