Merge pull request #922 from makeding/huggy_edit

更新 UA 列表,更改随机 UA 相关逻辑
This commit is contained in:
binaryify 2020-09-12 09:39:29 +08:00 committed by GitHub
commit 346593e0c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 281 additions and 263 deletions

5
.gitignore vendored
View File

@ -1,8 +1,5 @@
.DS_Store .DS_Store
node_modules node_modules
*.log *.log
.idea
.idea/
.vscode .vscode

View File

@ -192,7 +192,7 @@
## 安装 ## 安装
```shell ```shell
$ git clone git@github.com:Binaryify/NeteaseCloudMusicApi.git $ git clone https://github.com/Binaryify/NeteaseCloudMusicApi.git
$ npm install $ npm install
``` ```

View File

@ -1,80 +1,82 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>更新头像</title>
</head>
<body>
<input id="file" type="file" name="filename" />
<img id="avatar" style="height: 200px; width: 200px; border-radius: 50%;" />
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.20.0-0/axios.min.js
"></script>
<script>
const phone = ''
const password = ''
const port = 3000
let cookieToken = ''
if (!phone || !password) {
const msg = '请设置你的手机号码和密码'
alert(msg)
throw new Error(msg)
}
main() <head>
login() <meta charset="UTF-8" />
async function main() { <meta name="viewport" content="width=device-width, initial-scale=1.0" />
document.querySelector('input[type="file"]').addEventListener( <title>更新头像</title>
'change', </head>
function (e) {
var file = this.files[0] <body>
upload(file) <input id="file" type="file" name="filename" />
}, <img id="avatar" style="height: 200px; width: 200px; border-radius: 50%;" />
false <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.20.0-0/axios.min.js
) "></script>
const res = await axios({ <script>
url: `http://localhost:${port}/user/detail?uid=32953014&timestamp=${Date.now()}`, const phone = ''
withCredentials: true, //关键 const password = ''
}) let cookieToken = ''
document.querySelector('#avatar').src = res.data.profile.avatarUrl if (!phone || !password) {
} const msg = '请设置你的手机号码和密码'
async function login() { alert(msg)
const res = await axios({ throw new Error(msg)
url: `http://localhost:${port}/login/cellphone?phone=${phone}&password=${password}`, }
withCredentials: true, //关键
}) main()
cookieToken = res.data.cookie login()
} async function main() {
async function upload(file) { document.querySelector('input[type="file"]').addEventListener(
var formData = new FormData() 'change',
formData.append('imgFile', file) function (e) {
const imgSize = await getImgSize(file) var file = this.files[0]
const res = await axios({ upload(file)
method: 'post', },
url: `http://localhost:3000/avatar/upload?cookie=${cookieToken}&imgSize=${imgSize.width}&imgX=0&imgY=0&timestamp=${Date.now()}`, false
headers: { )
'Content-Type': 'multipart/form-data', const res = await axios({
}, url: `/user/detail?uid=32953014&timestamp=${Date.now()}`,
data: formData, withCredentials: true, //关键
}) })
document.querySelector('#avatar').src = res.data.data.url document.querySelector('#avatar').src = res.data.profile.avatarUrl
} }
function getImgSize(file) { async function login() {
return new Promise((resolve, reject) => { const res = await axios({
let reader = new FileReader() url: `/login/cellphone?phone=${phone}&password=${password}`,
reader.readAsDataURL(file) withCredentials: true, //关键
reader.onload = function (theFile) { })
let image = new Image() cookieToken = res.data.cookie
image.src = theFile.target.result }
image.onload = function () { async function upload(file) {
resolve({ var formData = new FormData()
width: this.width, formData.append('imgFile', file)
height: this.height const imgSize = await getImgSize(file)
}) const res = await axios({
} method: 'post',
url: `http://localhost:3000/avatar/upload?cookie=${cookieToken}&imgSize=${imgSize.width}&imgX=0&imgY=0&timestamp=${Date.now()}`,
headers: {
'Content-Type': 'multipart/form-data',
},
data: formData,
})
document.querySelector('#avatar').src = res.data.data.url
}
function getImgSize(file) {
return new Promise((resolve, reject) => {
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = function (theFile) {
let image = new Image()
image.src = theFile.target.result
image.onload = function () {
resolve({
width: this.width,
height: this.height
})
} }
}) }
} })
</script> }
</body> </script>
</html> </body>
</html>

View File

@ -1,11 +1,13 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html lang="zh">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>网易云音乐 API</title> <title>网易云音乐 API</title>
</head> </head>
<body> <body>
<h1>网易云音乐 API</h1> <h1>网易云音乐 API</h1>
当你看到这个页面时,这个服务已经成功跑起来了~ 当你看到这个页面时,这个服务已经成功跑起来了~
@ -17,32 +19,40 @@
<li>3. <a href="/dj/program?rid=336355127">电台节目</a></li> <li>3. <a href="/dj/program?rid=336355127">电台节目</a></li>
</ul> </ul>
<style> <style>
html,body{ html,
body {
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
margin: 0; margin: 0;
padding: 0; padding: 0;
background: #ffffff; background: #ffffff;
text-align: center; text-align: center;
margin-top:30px; margin-top: 30px;
overflow: hidden; overflow: hidden;
} }
*{
color:rgb(100,100,100); * {
color: rgb(100, 100, 100);
} }
a{
color:#42b983; a {
color: #42b983;
} }
ul,li{
ul,
li {
margin: 0; margin: 0;
} }
ul{
ul {
margin-left: -40px; margin-left: -40px;
line-height: 30px; line-height: 30px;
} }
li{
li {
list-style: none; list-style: none;
} }
</style> </style>
</body> </body>
</html> </html>

View File

@ -1,86 +1,88 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>歌单封面上传</title>
</head>
<body>
<input id="file" type="file" name="filename" />
<img id="playlist_cover" style="height: 200px; width: 200px; border-radius: 50%;" />
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.20.0-0/axios.min.js
"></script>
<script>
const phone = ''
const password = ''
const playlist_id = ''
const port = 3000
let cookieToken = ''
if (!phone || !password) {
const msg = '请设置你的手机号码和密码'
alert(msg)
throw new Error(msg)
}
if (!playlist_id) {
const msg = '请设置你的歌单id'
alert(msg)
throw new Error(msg)
}
main() <head>
login() <meta charset="UTF-8" />
async function main() { <meta name="viewport" content="width=device-width, initial-scale=1.0" />
document.querySelector('input[type="file"]').addEventListener( <title>歌单封面上传</title>
'change', </head>
function (e) {
var file = this.files[0] <body>
upload(file)
}, <input id="file" type="file" name="filename" />
false <img id="playlist_cover" style="height: 200px; width: 200px; border-radius: 50%;" />
) <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.20.0-0/axios.min.js
const res = await axios({ "></script>
url: `http://localhost:${port}/playlist/detail?id=${playlist_id}&timestamp=${Date.now()}`, <script>
}) const phone = ''
document.querySelector('#playlist_cover').src = res.data.playlist.coverImgUrl const password = ''
} const playlist_id = ''
async function login() { let cookieToken = ''
const res = await axios({ if (!phone || !password) {
url: `http://localhost:${port}/login/cellphone?phone=${phone}&password=${password}`, const msg = '请设置你的手机号码和密码'
withCredentials: true, //关键 alert(msg)
}) throw new Error(msg)
cookieToken = res.data.cookie }
} if (!playlist_id) {
async function upload(file) { const msg = '请设置你的歌单id'
var formData = new FormData() alert(msg)
formData.append('imgFile', file) throw new Error(msg)
const imgSize = await getImgSize(file) }
const res = await axios({
method: 'post', main()
url: `http://localhost:3000/playlist/cover/update?id=${playlist_id}&cookie=${cookieToken}&imgSize=${imgSize.width}&imgX=0&imgY=0&timestamp=${Date.now()}`, login()
headers: { async function main() {
'Content-Type': 'multipart/form-data', document.querySelector('input[type="file"]').addEventListener(
}, 'change',
data: formData, function (e) {
}) var file = this.files[0]
document.querySelector('#playlist_cover').src = res.data.data.url upload(file)
} },
function getImgSize(file) { false
return new Promise((resolve, reject) => { )
let reader = new FileReader() const res = await axios({
reader.readAsDataURL(file) url: `/playlist/detail?id=${playlist_id}&timestamp=${Date.now()}`,
reader.onload = function (theFile) { })
let image = new Image() document.querySelector('#playlist_cover').src = res.data.playlist.coverImgUrl
image.src = theFile.target.result }
image.onload = function () { async function login() {
resolve({ const res = await axios({
width: this.width, url: `/login/cellphone?phone=${phone}&password=${password}`,
height: this.height, withCredentials: true, //关键
}) })
} cookieToken = res.data.cookie
}
async function upload(file) {
var formData = new FormData()
formData.append('imgFile', file)
const imgSize = await getImgSize(file)
const res = await axios({
method: 'post',
url: `http://localhost:3000/playlist/cover/update?id=${playlist_id}&cookie=${cookieToken}&imgSize=${imgSize.width}&imgX=0&imgY=0&timestamp=${Date.now()}`,
headers: {
'Content-Type': 'multipart/form-data',
},
data: formData,
})
document.querySelector('#playlist_cover').src = res.data.data.url
}
function getImgSize(file) {
return new Promise((resolve, reject) => {
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = function (theFile) {
let image = new Image()
image.src = theFile.target.result
image.onload = function () {
resolve({
width: this.width,
height: this.height,
})
} }
}) }
} })
</script> }
</body> </script>
</html> </body>
</html>

View File

@ -1,62 +1,63 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>test</title>
</head>
<body> <head>
<p>请在控制台看结果</p> <meta charset="UTF-8" />
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.bootcss.com/axios/0.18.0/axios.min.js"></script> <meta http-equiv="X-UA-Compatible" content="ie=edge" />
<script> <title>test</title>
const phone = '' </head>
const password = ''
const port = 3000
if(!phone || !password){
const msg = '请设置你的手机号码和密码'
alert(msg)
throw new Error(msg)
}
$.ajax({
url: `http://localhost:${port}/login/cellphone?phone=${phone}&password=${password}`,
xhrFields: {
withCredentials: true //关键
},
success: function(data) {
console.log(data)
$.ajax({
url: `http://localhost:${port}/recommend/resource `,
xhrFields: {
withCredentials: true //关键
},
success: function(data) {
console.log(data)
},
error: function(err) {
console.log(err)
}
})
},
error: function(err) {
console.log(err)
}
})
axios({ <body>
url: `http://localhost:${port}/login/cellphone?phone=${phone}&password=${password}`, <p>请在控制台看结果</p>
withCredentials: true //关键 <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
}).then(function(res) { <script src="https://cdn.bootcss.com/axios/0.18.0/axios.min.js"></script>
console.log(res.data) <script>
axios({ const phone = ''
url: `http://localhost:${port}/recommend/resource`, const password = ''
withCredentials: true //关键 if (!phone || !password) {
}).then(function(res) { const msg = '请设置你的手机号码和密码'
console.log(res.data) alert(msg)
}) throw new Error(msg)
}) }
</script> $.ajax({
</body> url: `/login/cellphone?phone=${phone}&password=${password}`,
</html> xhrFields: {
withCredentials: true //关键
},
success: function (data) {
console.log(data)
$.ajax({
url: `/recommend/resource `,
xhrFields: {
withCredentials: true //关键
},
success: function (data) {
console.log(data)
},
error: function (err) {
console.log(err)
}
})
},
error: function (err) {
console.log(err)
}
})
axios({
url: `/login/cellphone?phone=${phone}&password=${password}`,
withCredentials: true //关键
}).then(function (res) {
console.log(res.data)
axios({
url: `/recommend/resource`,
withCredentials: true //关键
}).then(function (res) {
console.log(res.data)
})
})
</script>
</body>
</html>

View File

@ -6,32 +6,38 @@ const zlib = require('zlib')
// request.debug = true // 开启可看到更详细信息 // request.debug = true // 开启可看到更详细信息
const chooseUserAgent = ua => { const chooseUserAgent = (ua = false) => {
const userAgentList = [ // UA 列表要经常更新啊
'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1', const userAgentList = {
'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1', mobile: [
'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Mobile Safari/537.36', // iOS 13.5.1 14.0 beta with safari
'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Mobile Safari/537.36', 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Mobile Safari/537.36', 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.',
'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) Mobile/14F89;GameHelper', // iOS with qq micromsg
'Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A300 Safari/602.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML like Gecko) Mobile/14A456 QQ/6.5.7.408 V1_IPH_SQ_6.5.7_1_APP_A Pixel/750 Core/UIWebView NetType/4G Mem/103',
'Mozilla/5.0 (iPad; CPU OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A300 Safari/602.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/7.0.15(0x17000f27) NetType/WIFI Language/zh',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:46.0) Gecko/20100101 Firefox/46.0', // Android -> Huawei Xiaomi
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', 'Mozilla/5.0 (Linux; Android 9; PCT-AL10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.64 HuaweiBrowser/10.0.3.311 Mobile Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4', 'Mozilla/5.0 (Linux; U; Android 9; zh-cn; Redmi Note 8 Build/PKQ1.190616.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/71.0.3578.141 Mobile Safari/537.36 XiaoMi/MiuiBrowser/12.5.22',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:46.0) Gecko/20100101 Firefox/46.0', // Android + qq micromsg
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36', 'Mozilla/5.0 (Linux; Android 10; YAL-AL00 Build/HUAWEIYAL-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.62 XWEB/2581 MMWEBSDK/200801 Mobile Safari/537.36 MMWEBID/3027 MicroMessenger/7.0.18.1740(0x27001235) Process/toolsmp WeChat/arm64 NetType/WIFI Language/zh_CN ABI/arm64',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/13.10586' 'Mozilla/5.0 (Linux; U; Android 8.1.0; zh-cn; BKK-AL10 Build/HONORBKK-AL10) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/10.6 Mobile Safari/537.36',
] ],
let index = 0 pc: [
if (typeof ua == 'undefined') // macOS 10.15.6 Firefox / Chrome / Safari
index = Math.floor(Math.random() * userAgentList.length) 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:80.0) Gecko/20100101 Firefox/80.0',
else if (ua === 'mobile') index = Math.floor(Math.random() * 7) 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.30 Safari/537.36',
else if (ua === 'pc') index = Math.floor(Math.random() * 5) + 8 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15',
else return ua // Windows 10 Firefox / Chrome / Edge
return userAgentList[index] 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.30 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/13.10586'
// Linux 就算了
]
}
let realUserAgentList = userAgentList[ua] || (userAgentList.mobile).concat(userAgentList.pc)
return (['mobile', 'pc', false].indexOf(ua) > -1) ? realUserAgentList[Math.floor(Math.random() * realUserAgentList.length)] : ua
} }
const createRequest = (method, url, data, options) => { const createRequest = (method, url, data, options) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let headers = { 'User-Agent': chooseUserAgent(options.ua) } let headers = { 'User-Agent': chooseUserAgent(options.ua) }
@ -52,7 +58,7 @@ const createRequest = (method, url, data, options) => {
) )
.join('; ') .join('; ')
else if (options.cookie) headers['Cookie'] = options.cookie else if (options.cookie) headers['Cookie'] = options.cookie
if (!headers['Cookie']) { if (!headers['Cookie']) {
headers['Cookie'] = options.token || '' headers['Cookie'] = options.token || ''
} }
@ -134,10 +140,10 @@ const createRequest = (method, url, data, options) => {
zlib.unzip(body, function (err, buffer) { zlib.unzip(body, function (err, buffer) {
const _buffer = err ? body : buffer const _buffer = err ? body : buffer
try { try {
try{ try {
answer.body = JSON.parse(encrypt.decrypt(_buffer).toString()) answer.body = JSON.parse(encrypt.decrypt(_buffer).toString())
answer.status = answer.body.code || res.statusCode answer.status = answer.body.code || res.statusCode
} catch(e){ } catch (e) {
answer.body = JSON.parse(_buffer.toString()) answer.body = JSON.parse(_buffer.toString())
answer.status = res.statusCode answer.status = res.statusCode
} }
@ -156,7 +162,7 @@ const createRequest = (method, url, data, options) => {
answer.body = JSON.parse(body) answer.body = JSON.parse(body)
answer.status = answer.body.code || res.statusCode answer.status = answer.body.code || res.statusCode
if(answer.body.code === 502){ if (answer.body.code === 502) {
answer.status = 200 answer.status = 200
} }
} }