JS逆向-某易云音樂下載器

文章目錄

  • 介紹
  • 下載鏈接
  • Robots文件
  • 搜索功能
  • JS逆向
      • **函數a:生成隨機字符串**
      • **函數b:AES-CBC加密**
      • **函數c:RSA公鑰加密**
  • 歌曲下載
  • 總結

介紹

在某易云音樂中,很多歌曲聽是免費的,但下載需要VIP,此程序旨在“可聽”則可下,只要能夠聽的歌,都可以下載下來。

而此篇博客則著重講此代碼是如何編寫的,如果只想要下載工具,請自行查看下載鏈接。

注意,此程序僅做學習參考,任何違法行為與作者無關。

下載鏈接

GitHub:https://github.com/13337356453/163Music
CSDN:https://download.csdn.net/download/realmels/90855703

Robots文件

養成好習慣,爬蟲之前,先看robots文件。
在這里插入圖片描述
禁止爬取

/prime/m/gift-receive

文件,剛好,我們這次不爬取此文件。

搜索功能

在某易云音樂中提供了搜索功能,可以通過關鍵詞搜索歌曲。
在這里插入圖片描述
而我們的程序需要通過用戶關鍵詞來搜索內容,因此需要首先從搜索功能開始爬取。

在這里通過歌曲abc為例,進行搜索功能的分析與實現。

在搜索欄輸入關鍵字abc,按下回車鍵得到搜索結果。
在這里插入圖片描述
按下F12進入開發者工具,選中Network,點擊XHR查看Ajax的請求包

刷新界面,出現了很多請求包
在這里插入圖片描述
逐個查看請求包的Response,尋找搜索歌曲的請求包。

在路徑為

/weapi/cloudsearch/get/web

的請求包中,我們可以看到歌曲的搜索信息。

在這里插入圖片描述
可以確定這個就是搜索歌曲的請求包。

接下來分析請求參數。

在這里插入圖片描述
這是一個POST請求,請求的URL為:https://music.163.com/weapi/cloudsearch/get/web
,POST的參數如下:

params=NM406wjNCdicjbT3ZSuA7X6ICkCBzfN6rA1KAeZR4Pmpv6VhTT8jKqR/ZRpGitFCp77TipjrdwPahGWiMjGf2cLrREp5Gadgeseo9l9+IMfrwG/JmgDfW9pLZaRIagi+MSESFlTJnlH3vJI7YbqwWPjgfbyzBX0sgw4l3IXxfuamFggnztM3DlEhB1uCBUPqEpDFlsMW8pPdEPtaJS47Y2DMXBY/SJVOa8Y3nD/rjP2lhw5sXaZ3qs5LEwmYKiriEAaZ6fRmKJb4Vn6Ay6ELCBWL74DqjF4BPh8GsEPicXdah/nR0BPoM+suZbKCICMK
encSecKey=8b987300e7f1a5e657c7a69d3c9ff9a4d9ab1c3dc1b2328df473600103b1fe18aa4898008ac9d03074c2cb560543ac22740c4c0c1f7d2c14535f938344a999224733d97e75ffdc26dc2a7ac9afff302f127b29ee762ce02061b9ce89ad2b9006938ed0e62667bfbac656b12adbe951ccff0d02dacd27fb94de7473fa933043ec

別的都容易理解,這兩個參數是什么呢?

我們從JS文件中找答案。

JS逆向

在這里先科普基本知識。一個網站,分為前端和后端,前端負責展現好看的頁面,后端負責處理繁雜的數據。用戶通過前端界面,將數據發送到后端,后端代碼處理數據,將相應的結果發送到前端,呈現在用戶眼前。這個過程通過request/response,實現。因此,前端所有奇形怪狀的參數,都可以在前端代碼中找到蛛絲馬跡。畢竟,后端代碼是不可見的,而前端代碼是公開的。

首先需要明白paramsencSecKey這兩個參數是如何產生的,這里我們復制encSecKey,在開發者工具中選中Sources,按下Ctrl+Shift+F進行全局搜索。
在這里插入圖片描述
在這里我們逐個進行分析,首先打開這個core開頭的JS文件,顧名思義,core就是核心,因此最可能有我們想要的數據。

打開文件后按下Ctrl+F進行文件內搜索,搜索encSecKey,查詢到三個結果。
在這里插入圖片描述
我們分別進行分析。

在第二次出現的地方,我們需要的兩個參數:paramsencsecKey同時出現
在這里插入圖片描述
懷疑這里有參數的生成邏輯,打一個斷點。
在這里插入圖片描述
刷新頁面,程序運行到斷點處停止。
在這里插入圖片描述
可以看到,paramsencsecKey這兩個參數分別是bYE4I這個對象的兩個屬性。而bYE4I這個對象是由window.asrsea這個函數生成的。

我們把光標放到window.asrsea這個函數上,查看這個函數的真實面目。
在這里插入圖片描述
跳轉到函數d
在這里插入圖片描述
我們可以看到,函數d中調用了函數a,b,c。正好這三個參數都在d函數的附近,我們一起復制過來查看。

function a(a) {var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";for (d = 0; a > d; d += 1)e = Math.random() * b.length,e = Math.floor(e),c += b.charAt(e);return c}function b(a, b) {var c = CryptoJS.enc.Utf8.parse(b), d = CryptoJS.enc.Utf8.parse("0102030405060708"), e = CryptoJS.enc.Utf8.parse(a), f = CryptoJS.AES.encrypt(e, c, {iv: d,mode: CryptoJS.mode.CBC});return f.toString()}function c(a, b, c) {var d, e;return setMaxDigits(131),d = new RSAKeyPair(b,"",c),e = encryptedString(d, a)}function d(d, e, f, g) {var h = {}, i = a(16);return h.encText = b(d, g),h.encText = b(h.encText, i),h.encSecKey = c(i, e, f),h}

我們在d函數中打上斷點,分析d函數的參數
在這里插入圖片描述
一直點擊上方的下一步,同時眼睛觀察著右邊的實時參數值。
在這里插入圖片描述
在這里插入圖片描述
多走幾步,我們會發現函數d接受的四個參數中,efg都是固定值,值如下:

e=010001
f=00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7
g=0CoJUm6Qyw8W8jud

參數d的值卻一直在變化。

我們一直點下一步的按鈕,同時盯著參數,點著點著,會發現右側的d參數發生變化,大多數時候都是csrf_token的值,我們不用管,但偶爾會出現別的內容,而大概點了幾十次后,參數會變成:

d="{\"hlpretag\":\"<span class=\\\"s-fc7\\\">\",\"hlposttag\":\"</span>\",\"s\":\"abc\",\"type\":\"1\",\"offset\":\"0\",\"total\":\"true\",\"limit\":\"30\",\"csrf_token\":\"\"}"

在其中,出現了我們的關鍵詞abc,以及出現歌曲的數量30

確定d函數就是生成參數的邏輯。

接下來仔細分析d函數

 function d(d, e, f, g) {var h = {}, i = a(16);return h.encText = b(d, g),h.encText = b(h.encText, i),h.encSecKey = c(i, e, f),h}

首先定義了一個空對象h,然后通過a函數生成內容,賦值給i,接下來通過b函數生成第一個encText,賦給h的屬性,接受參數dg,再用b函數二次處理encText,參數為第一次處理的encTexti,這就是提交時所需的params;同時用c函數生成encsecKey,接受參數ief

接下來我們逐個分析abc函數

function a(a) {var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";for (d = 0; a > d; d += 1)e = Math.random() * b.length,e = Math.floor(e),c += b.charAt(e);return c}function b(a, b) {var c = CryptoJS.enc.Utf8.parse(b), d = CryptoJS.enc.Utf8.parse("0102030405060708"), e = CryptoJS.enc.Utf8.parse(a), f = CryptoJS.AES.encrypt(e, c, {iv: d,mode: CryptoJS.mode.CBC});return f.toString()}function c(a, b, c) {var d, e;return setMaxDigits(131),d = new RSAKeyPair(b,"",c),e = encryptedString(d, a)}

人與動物的區別就是人會使用工具,我們直接問deepseek

在這里插入圖片描述
在這里插入圖片描述
這是deepseek的回答。


函數a:生成隨機字符串

function a(a) {var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";for (d = 0; a > d; d += 1)e = Math.random() * b.length,e = Math.floor(e),c += b.charAt(e);return c
}
  • 功能:生成指定長度的隨機字符串,字符集包括大小寫字母和數字。
  • 參數a 控制字符串長度。
  • 實現細節
    • 循環 a 次,每次從字符池 b 中隨機選取一個字符。
    • 使用 Math.random() 生成隨機索引,可能不夠安全(非密碼學安全隨機數)。
  • 安全問題
    • Math.random() 在瀏覽器中可能被預測,建議改用 crypto.getRandomValues()
  • 用途:生成臨時密鑰、Nonce 或鹽值。

函數b:AES-CBC加密

function b(a, b) {var c = CryptoJS.enc.Utf8.parse(b), d = CryptoJS.enc.Utf8.parse("0102030405060708"), e = CryptoJS.enc.Utf8.parse(a), f = CryptoJS.AES.encrypt(e, c, {iv: d,mode: CryptoJS.mode.CBC});return f.toString()
}
  • 功能:使用 AES-CBC 模式加密數據,密鑰由參數提供。
  • 參數
    • a:明文數據(UTF-8 字符串)。
    • b:加密密鑰(UTF-8 字符串)。
  • 實現細節
    • 固定初始化向量(IV)0102030405060708
    • 使用 CryptoJS 庫進行加密,返回 Base64 編碼的密文。
  • 安全問題
    • 固定IV:CBC 模式要求每次加密使用隨機 IV,否則可能導致明文模式泄露。
    • 密鑰建議使用二進制格式(如 PBKDF2 派生),而非直接字符串。
  • 用途:加密傳輸敏感數據。

函數c:RSA公鑰加密

function c(a, b, c) {var d, e;return setMaxDigits(131),d = new RSAKeyPair(b,"",c),e = encryptedString(d, a)
}
  • 功能:使用 RSA 公鑰加密數據。
  • 參數
    • a:明文數據(字符串或數值)。
    • b:公鑰指數(通常為 "10001" 十六進制)。
    • c:RSA 模數(n)。
  • 實現細節
    • setMaxDigits(131) 設置大整數位數(支持最大 131 位,對應 1024 位 RSA)。
    • RSAKeyPair 僅使用公鑰指數和模數,私鑰留空,表明這是公鑰加密。
    • encryptedString 可能是自定義函數,實現 RSA 加密邏輯。
  • 安全問題
    • 需確認是否使用正確填充(如 PKCS#1 v1.5 或 OAEP),默認可能不安全。
  • 用途:加密對稱密鑰(如 AES 密鑰)以便安全傳輸。

知道了函數的用途,我們開始編寫Python代碼。

寫一個工具類,分別實現函數abcd的功能,名字為JS,定義四個靜態方法:

import base64
import random
from binascii import hexlifyfrom Crypto.Cipher import AES
from Crypto.Util.Padding import padclass JS:@staticmethoddef d(d,e="010001",f="00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7",g="0CoJUm6Qyw8W8jud"):'''生成數據'''i=JS.a(16)h_encText=JS.b(d,g)encText=JS.b(h_encText,i)encSecKey=JS.c(i,e,f)return encText,encSecKey@staticmethoddef a(a):'''生成16位隨機字符'''b="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"c=""for i in range(a):e = random.randint(0, len(b) - 1)c+=b[e]return c@staticmethoddef b(a,b):'''AES加密'''key = b.encode('utf-8')iv = "0102030405060708".encode('utf-8')data = a.encode('utf-8')cipher = AES.new(key, AES.MODE_CBC, iv)encrypted = cipher.encrypt(pad(data, AES.block_size))return base64.b64encode(encrypted).decode('utf-8')@staticmethoddef c(a,b,c):'''RSA加密'''a = a[::-1]result = pow(int(hexlify(a.encode()), 16), int(b, 16), int(c, 16))return format(result, 'x').zfill(131)

至于這幾個函數是如何改寫的。。其實很簡單。
在這里插入圖片描述
接下來的步驟就很簡單了,編寫搜索歌曲功能代碼:

import requests
from urllib.parse import quote
from json import loadsfrom JS import JSrequests.packages.urllib3.disable_warnings()
class Searcher:url="https://music.163.com/weapi/cloudsearch/get/web?csrf_token="headers={'Host': 'music.163.com','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36','Referer': 'https://music.163.com/search/','Content-Type': 'application/x-www-form-urlencoded',}jsonStr="{\"hlpretag\":\"<span class=\\\"s-fc7\\\">\",\"hlposttag\":\"</span>\",\"s\":\"%s\",\"type\":\"1\",\"offset\":\"0\",\"total\":\"true\",\"limit\":\"%d\",\"csrf_token\":\"\"}"def __init__(self,keyword,proxies={},number=1,cookie=""):self.keyword=keywordself.proxies=proxiesself.number=numberself.headers['Cookie']=cookiedef getData(self):s=self.jsonStr%(self.keyword,self.number)params,encSecKey=JS.d(s)data=f"""params={quote(params)}&encSecKey={quote(encSecKey)}"""try:r=requests.post(self.url,headers=self.headers,data=data,verify=False,timeout=10,proxies=self.proxies)if r.status_code==200:result=loads(r.content.decode())return result['result']['songs']return Noneexcept Exception as e:print(f'[!] {e}')return None

注意注意,這里有個非常坑的點,就是在傳輸data中,數據還要進行URL加密,否則就會報400,參數錯誤。這個點害了我一晚上。

我們成功實現了通過關鍵字搜索功能,獲取到歌曲的idname,這兩個參數至關重要

歌曲下載

選中一首歌,我們打開詳細頁。
在這里插入圖片描述
打開開發者工具抓包,同時點擊播放按鈕
在這里插入圖片描述
抓取到數據包后,我們逐個分析。
在這里插入圖片描述
鎖定到

/weapi/song/enhance/player/url/v1

這個請求包,在請求包中,我們可以看到歌曲的下載鏈接。
在這里插入圖片描述
我們把這個鏈接復制到瀏覽器打開,成功播放了歌曲,確定就是下載鏈接。

在這里插入圖片描述
接下來我們分析這個請求包的參數。
在這里插入圖片描述
熟悉的paramsencsecKey,我們之前已經分析過了

使用同樣方法打好斷點,再次點擊播放按鈕,查看傳入的參數。

在這里插入圖片描述
這里出現了歌曲id,原始的參數為:

d="{\"ids\":\"[33004804]\",\"level\":\"exhigh\",\"encodeType\":\"aac\",\"csrf_token\":\"\"}"

于是我們可以編寫相關Python代碼:

from json import loads
from urllib.parse import quoteimport requestsfrom JS import JSrequests.packages.urllib3.disable_warnings()
class Musicer:url='https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token='headers={'Host': 'music.163.com','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36','Referer': 'https://music.163.com/search/','Content-Type': 'application/x-www-form-urlencoded',}jsonStr='{"ids":"[%s]","level":"exhigh","encodeType":"aac","csrf_token":""}'def __init__(self,musicid,cookie,name,proxies={}):self.musicid=str(musicid)self.headers['Cookie']=cookieself.proxies=proxiesself.name=namedef getDownloadUrl(self):s=self.jsonStr%self.musicidparams,encSecKey=JS.d(s)data=f"""params={quote(params)}&encSecKey={quote(encSecKey)}"""try:r=requests.post(self.url,headers=self.headers,data=data,verify=False,timeout=10,proxies=self.proxies)if r.status_code==200:return loads(r.content.decode())['data'][0]['url']return Noneexcept Exception as e:print(e)return Nonedef download(self):url=self.getDownloadUrl()try:r=requests.get(url,proxies=self.proxies,verify=False,timeout=10)if r.status_code==200:with open(f'{self.name}.mp3','wb') as f:f.write(r.content)print(f"[+] {self.name}.mp3 已保存")except Exception as e:print(f'[!] {e}')

至此,本項目全部完成。

總結

本博客僅做學習參考,任何違法犯罪行為與本文作者無關。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/81600.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/81600.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/81600.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

黑馬k8s(十)

1.Pod生命周期-鉤子函數 2.Pod生命周期-容器探測 因為沒有hello.txt文件 查看詳情&#xff1a; 修改為查看命令&#xff1a; 查看一下詳情&#xff1a; 因為只有一個80端口&#xff0c;沒有8080&#xff0c;所以會重啟 查看詳情&#xff1a; 修改成80&#xff1a; 因為沒有…

每日算法刷題Day9 5.17:leetcode定長滑動窗口3道題,用時1h

9. 1652.拆炸彈(簡單&#xff0c;學習) 1652. 拆炸彈 - 力扣&#xff08;LeetCode&#xff09; 思想 為了獲得正確的密碼&#xff0c;你需要替換掉每一個數字。所有數字會 同時 被替換。 如果 k > 0 &#xff0c;將第 i 個數字用 接下來 k 個數字之和替換。如果 k < 0…

Java IO及Netty框架學習小結

Netty netty官網: Netty 什么是Netty&#xff1f; Netty 是 一個異步事件驅動的網絡應用程序框架&#xff0c;用于快速開發可維護的高性能協議服務器和客戶端。Netty 是一個 NIO 客戶端服務器框架&#xff0c;可以快速輕松地開發網絡應用程序&#xff08;例如協議服務器和客…

計算機網絡筆記(二十七)——4.9多協議標簽交換MPLS

4.9.1MPLS的工作原理 一、MPLS基本工作原理 MPLS&#xff08;Multiprotocol Label Switching&#xff09;是一種介于數據鏈路層和網絡層之間的轉發技術&#xff0c;通過固定長度的標簽進行高速數據轉發。其核心特點是通過預建立的標簽交換路徑&#xff08;Label Switching Pa…

AI 賦能 Copula 建模:大語言模型驅動的相關性分析革新

技術點目錄 R及Python語言及相關性研究初步二元Copula理論與實踐&#xff08;一&#xff09;二元Copula理論與實踐&#xff08;二&#xff09;【R語言為主】Copula函數的統計檢驗與選擇【R語言為主】高維數據與Vine Copula 【R語言】正則Vine Copula&#xff08;一&#xff09;…

【洛谷P3386】二分圖最大匹配之Kuhn算法/匈牙利算法:直觀理解

題目&#xff1a;洛谷P3386 【模板】二分圖最大匹配 &#x1f955; 匈牙利算法本來是針對帶權圖最大匹配的&#xff0c;這里由于題目只是求最大匹配的邊數&#xff0c;所以我們也只考慮無權的情況。 &#x1f680; 本文旨在服務于看了別的關于匈牙利算法的文章但不甚理解的童…

【數據結構】二分查找(返回插入點)5.14

二分查找基礎版 package 二分查找; public class BinarySearch { public static void main(String[] args) { // TODO Auto-generated method stub } public static int binarySearchBasic(int[] a,int target) { int i0,ja.length-1; //設置指針初值 while…

Ubuntu 命令

Ubuntu 命令速查表? ?分類??命令??功能描述??示例/常用選項????文件與目錄?ls列出目錄內容ls -a&#xff08;顯示隱藏文件&#xff09;; ls -lh&#xff08;詳細列表易讀大小&#xff09; cd切換目錄cd ~&#xff08;主目錄&#xff09;; cd ..&#xff08;上級…

Java集合框架詳解與使用場景示例

Java集合框架是Java標準庫中一組用于存儲和操作數據的接口和類。它提供了多種數據結構&#xff0c;每種數據結構都有其特定的用途和性能特點。在本文中&#xff0c;我們將詳細介紹Java集合框架的主要組成部分&#xff1a;List、Set和Queue&#xff0c;并通過代碼示例展示它們的…

《Python星球日記》 第78天:CV 基礎與圖像處理

名人說:路漫漫其修遠兮,吾將上下而求索。—— 屈原《離騷》 創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder??) 目錄 一、計算機視覺(CV)簡介1. 什么是計算機視覺?2. 計算機視覺的應用場景3. 圖像的基本屬性a》像素(Pixel)b》通道(Channel)c》分辨率(Res…

LabVIEW在電子電工教學中的應用

在電子電工教學領域&#xff0c;傳統教學模式面臨諸多挑戰&#xff0c;如實驗設備數量有限、實驗過程存在安全隱患、教學內容更新滯后等。LabVIEW 作為一款功能強大的圖形化編程軟件&#xff0c;為解決這些問題提供了創新思路&#xff0c;在電子電工教學的多個關鍵環節發揮著重…

【優選算法 | 字符串】字符串模擬題精選:思維+實現解析

算法相關知識點可以通過點擊以下鏈接進行學習一起加油&#xff01;雙指針滑動窗口二分查找前綴和位運算模擬鏈表哈希表 在眾多字符串算法題中&#xff0c;有一類題目看起來沒有太多算法技巧&#xff0c;卻經常讓人“翻車”——那就是字符串模擬題。這類題型往往不依賴復雜的數據…

虛幻引擎5-Unreal Engine筆記之Default Pawn與GamMode、Camera的關系

虛幻引擎5-Unreal Engine筆記之Default Pawn與GamMode、Camera的關系 code review! 文章目錄 虛幻引擎5-Unreal Engine筆記之Default Pawn與GamMode、Camera的關系1.Default Pawn與Camera的關系1.1. Default Pawn 是什么&#xff1f;1.2. Default Pawn 的主要組件1.3. Default…

HarmonyOs開發之———UIAbility進階

謝謝關注!! 前言:上一篇文章主要介紹開發之———使用HTTP訪問網絡資源:HarmonyOs開發之———使用HTTP訪問網絡資源-CSDN博客 代碼資源:https://download.csdn.net/download/this_is_bug/90841580 一、基本概念 UIAbility 是 HarmonyOS 應用的核心組件,負責用戶界面的…

java實現根據Velocity批量生成pdf并合成zip壓縮包

Velocity 模版操作 用的之前寫好的: 傳送門 其中需要新加一個轉成輸入流的方法 public static InputStream convertToPdf(StringWriter stringWriter) throws IOException {//將 HTML 轉為字節流byte[] htmlBytes stringWriter.toString().getBytes(StandardCharsets.UTF_8)…

SCDN能夠運用在物聯網加速當中嗎?

在當今的科技化時代當中&#xff0c;物聯網已經廣泛滲透在各個領域行業當中&#xff0c;隨著物聯網規模的不斷擴大&#xff0c;數據信息的傳輸速度和網絡穩定性成為企業需要重視的兩點因素&#xff0c;而SCDN也成為安全內容分發網絡作為一種融合了內容加速和安全防護的技術&…

二程運輸的干散貨船路徑優化

在二程運輸中&#xff0c;干散貨船需要將貨物從一個港口運輸到多個不同的目的地港口。路徑優化的目標是在滿足貨物運輸需求、船舶航行限制等條件下&#xff0c;確定船舶的最佳航行路線&#xff0c;以最小化運輸成本、運輸時間或其他相關的優化目標。 影響因素 港口布局與距離…

Oracle物理恢復相關注意點

如果需要恢復的數據庫或者數據文件不存在&#xff0c;則需要將全量備份集RESTORE[ 將全量備份集恢復到目標數據庫中&#xff0c;稱之為RESTORE。]到目標數據庫中&#xff0c;然后再RECOVER[ 將增量備份集或者歸檔日志恢復到目標數據庫中&#xff0c;稱之為RECOVER。]增量備份集…

C++ string小記

#include<string> using std::string;string s1; string s2 "hello" //初始化一個hello字符串 string s3(5,a) //連續5個字符a組成的串&#xff0c;即aaaaa///字符串操作int length s1.size() //.size()求字符串長度char c1 s1[1]; //從下標0開始&#xf…

自然語言處理入門級項目——文本分類(預處理)

文章目錄 前言1.數據預處理1.1數據集介紹1.2數據集抽取1.3劃分數據集1.4數據清洗1.5數據保存 2.樣本的向量化表征2.1詞匯表2.2向量化2.3自定義數據集2.4備注 結語 前言 本篇博客主要介紹自然語言處理領域中一個項目案例——文本分類&#xff0c;具體而言就是判斷評價屬于積極還…