Hướng dẫn toàn diện công cụ tự động nghe nhạc NetEase Music với Python

Hướng dẫn toàn diện công cụ tự động nghe nhạc NetEase Music với Python

Giới thiệu tổng quan

Trong bài viết này, chúng ta sẽ tìm hiểu cách xây dựng một công cụ tự động hóa quy trình nghe nhạc trên NetEase Music (Netease Cloud Music) sử dụng Python. Công cụ này cho phép người dùng hoàn thành 300 bài hát mỗi ngày một cách tự động mà không cần thao tác thủ công.

Vấn đề thực tế

Để đạt được level cao trên NetEase Music, người dùng cần nghe ít nhất 300 bài hát mỗi ngày. Quy trình này đòi hỏi 30-60 phút thời gian liên tục, gây khó khăn cho những người bận rộn. Công cụ automation được đề cập trong bài viết giúp giải quyết vấn đề này bằng cách tự động hóa toàn bộ quy trình.

Kiến trúc hệ thống

Các thành phần chính

Hệ thống bao gồm hai thành phần chính:

  • Client Application: Script Python thực hiện việc tự động nghe nhạc
  • API Service: NeteaseCloudMusicApi đóng vai trò trung gian giao tiếp với server NetEase

Sơ đồ luồng hoạt động

┌─────────────┐     ┌────────────────────────┐     ┌─────────────────┐
│   Client    │────▶│  NeteaseCloudMusicApi  │────▶│  NetEase Server │
│   (Python)  │     │      (Localhost)       │     │                 │
└─────────────┘     └────────────────────────┘     └─────────────────┘
      │                                               │
      ▼                                               ▼
┌─────────────┐                               ┌─────────────────┐
│  Log File   │                               │  Playback Data  │
└─────────────┘                               └─────────────────┘

Cài đặt môi trường

Yêu cầu hệ thống

  • Python 3.8 trở lên
  • Git
  • Internet connection ổn định

Các bước cài đặt

Bước 1: Clone dự án

git clone https://github.com/nicechuan/netease-cloud-music-api.git
cd netease-cloud-music-api
npm install

Bước 2: Khởi động API service

# Mặc định service chạy trên port 3000
npm start

Bước 3: Cài đặt dependencies cho client

# Tạo virtual environment (tùy chọn nhưng khuyến nghị)
python -m venv venv
source venv/bin/activate  # Linux/Mac
# hoặc
venv\Scripts\activate     # Windows

# Cài đặt các thư viện cần thiết
pip install requests cryptography schedule

Cấu hình ứng dụng

Cấu trúc thư mục

project/
├── app.py              # File chính của ứng dụng
├── config.json         # File cấu hình
├── accounts.json       # Danh sách tài khoản (nếu có nhiều)
├── requirements.txt    # Dependencies
└── logs/
    └── run.log         # File log hoạt động

File cấu hình config.json

{
    "api_endpoint": "http://localhost:3000",
    "account": {
        "username": "your_phone_number",
        "password": "your_password",
        "country_code": "86"
    },
    "playlist": {
        "id": "your_playlist_id",
        "min_songs": 300
    },
    "settings": {
        "daily_target": 300,
        "request_delay_min": 2,
        "request_delay_max": 5,
        "enable_md5": false,
        "multi_account_mode": false
    },
    "notifications": {
        "enabled": false,
        "type": "serverchan",
        "webhook_url": ""
    }
}

Cách lấy Playlist ID

  1. Mở ứng dụng NetEase Music hoặc trang web
  2. Tìm playlist mong muốn
  3. Chọn "Chia sẻ" (Share) → "Sao chép liên kết" (Copy link)
  4. Trong URL, tìm tham số id= - đó chính là Playlist ID
# Ví dụ URL: https://music.163.com/playlist?id=5234162158
# Playlist ID: 5234162158

Triển khai code chính

Module xử lý đăng nhập

import requests
import json
import time
import random
import hashlib
from datetime import datetime

class NeteaseMusicClient:
    def __init__(self, config_path='config.json'):
        self.config = self.load_config(config_path)
        self.session = requests.Session()
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Referer': 'https://music.163.com/',
            'Origin': 'https://music.163.com'
        })
        self.cookies = {}
        self.played_count = 0
        
    def load_config(self, path):
        with open(path, 'r', encoding='utf-8') as f:
            return json.load(f)
    
    def encrypt_password(self, password):
        """Mã hóa mật khẩu theo format của NetEase"""
        char_list = '010001'
        modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
        
        # Thực hiện mã hóa password (rút gọn)
        temp = password + "password_to_encrypt"
        return hashlib.md5(temp.encode()).hexdigest()
    
    def login(self):
        """Đăng nhập vào tài khoản NetEase"""
        account = self.config['account']
        api_url = f"{self.config['api_endpoint']}/login/cellphone"
        
        data = {
            'phone': account['username'],
            'password': account['password'],
            'countrycode': account.get('country_code', '86')
        }
        
        response = self.session.post(api_url, data=data)
        result = response.json()
        
        if result.get('code') == 200:
            self.cookies = response.cookies
            print(f"Đăng nhập thành công: {result.get('profile', {}).get('nickname')}")
            return True
        else:
            print(f"Đăng nhập thất bại: {result.get('message')}")
            return False

Module xử lý phát nhạc

    def get_playlist_tracks(self, playlist_id):
        """Lấy danh sách bài hát từ playlist"""
        api_url = f"{self.config['api_endpoint']}/playlist/track/all"
        
        params = {
            'id': playlist_id,
            'limit': 500,  # Lấy tối đa 500 bài
            'offset': 0
        }
        
        response = self.session.get(api_url, params=params)
        result = response.json()
        
        if result.get('code') == 200:
            tracks = result.get('songs', [])
            print(f"Đã lấy {len(tracks)} bài hát từ playlist")
            return tracks
        return []
    
    def play_track(self, track_id):
        """Phát một bài hát"""
        api_url = f"{self.config['api_endpoint']}/song/url"
        
        params = {'id': track_id, 'br': 128000}
        
        response = self.session.get(api_url, params=params)
        result = response.json()
        
        if result.get('code') == 200 and result.get('data'):
            # Gọi API để record thời gian nghe
            self.record_playtime(track_id)
            return True
        return False
    
    def record_playtime(self, track_id):
        """Ghi nhận thời gian nghe nhạc"""
        api_url = f"{self.config['api_endpoint']}/scrobble"
        
        data = {
            'id': track_id,
            'sourceid': track_id,
            'time': int(time.time() * 1000),
            'type': 'song'
        }
        
        response = self.session.post(api_url, data=data)
        return response.json().get('code') == 200

Module điều phối chính

    def start_automation(self):
        """Bắt đầu quy trình tự động nghe nhạc"""
        if not self.login():
            return False
        
        playlist_id = self.config['playlist']['id']
        tracks = self.get_playlist_tracks(playlist_id)
        
        if len(tracks) < self.config['playlist'].get('min_songs', 300):
            print(f"Cảnh báo: Playlist có ít hơn 300 bài hát!")
        
        daily_target = self.config['settings']['daily_target']
        self.played_count = 0
        
        print(f"Bắt đầu phát {daily_target} bài hát...")
        
        for track in tracks:
            if self.played_count >= daily_target:
                break
            
            track_id = track['id']
            if self.play_track(track_id):
                self.played_count += 1
                print(f"Đã phát: {self.played_count}/{daily_target} - {track['name']}")
            
            # Random delay để tránh bị phát hiện là bot
            delay = random.randint(
                self.config['settings']['request_delay_min'],
                self.config['settings']['request_delay_max']
            )
            time.sleep(delay)
        
        print(f"Hoàn thành! Đã phát {self.played_count} bài hát trong ngày hôm nay")
        return True
    
    def write_log(self, message):
        """Ghi log hoạt động"""
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        log_entry = f"[{timestamp}] {message}\n"
        
        with open('logs/run.log', 'a', encoding='utf-8') as f:
            f.write(log_entry)

Điểm khởi động chương trình

import schedule
import time

def main():
    client = NeteaseMusicClient('config.json')
    client.start_automation()

# Đặt lịch chạy hàng ngày vào lúc 1:00 sáng
schedule.every().day.at("01:00").do(main)

if __name__ == "__main__":
    print("Khởi động NetEase Music Automation Tool...")
    main()
    
    # Chạy vòng lặp scheduler
    while True:
        schedule.run_pending()
        time.sleep(60)

Các tính năng nâng cao

Hỗ trợ nhiều tài khoản

Để sử dụng tính năng quản lý nhiều tài khoản, cấu hình file accounts.json:

[
    {
        "username": "phone_number_1",
        "password": "password_1"
    },
    {
        "username": "phone_number_2", 
        "password": "password_2"
    }
]

Sau đó bật chế độ multi-account trong config.json:

"settings": {
    "multi_account_mode": true,
    "account_switch_interval": 3600
}

Tích hợp thông báo

Công cụ hỗ trợ nhiều hình thức thông báo:

Loại thông báo Mô tả
ServerChan Gửi thông báo qua WeChat
WxPusher Gửi qua微信公众号
Bark Gửi thông báo đến iOS devices

Xử lý sự cố

Các lỗi thường gặp

Mã lỗi Nguyên nhân Giải pháp
301 Tài khoản hoặc mật khẩu sai Kiểm tra lại thông tin đăng nhập
400 Playlist ID không hợp lệ Xác nhận lại playlist ID
461 Bài hát không thể phát (license) Chuyển sang playlist khác

Tối ưu hóa hiệu suất

  • Network: Sử dụng kết nối internet ổn định, tránh VPN gây lag
  • Timing: Chạy vào ban đêm (00:00-06:00) để tránh peak hours
  • Delay: Đặt delay tối thiểu 2-5 giây giữa các bài hát

Lưu ý về bảo mật

  • Thông tin tài khoản được lưu trữ cục bộ trên máy người dùng
  • Nên bật xác thực hai yếu tố (2FA) cho tài khoản NetEase
  • Không nên chạy quá nhiều tài khoản trên cùng một IP
  • Công cụ này chỉ nên được sử dụng cho mục đích học tập và cá nhân

Kết luận

Bằng cách sử dụng công cụ tự động hóa này, người dùng có thể tiết kiệm đáng kể thời gian trong việc tích lũy số giờ nghe nhạc trên NetEase Music. Tuy nhiên, cần sử dụng một cách có trách nhiệm và tuân thủ các điều khoản sử dụng của nền tảng.

Thẻ: python automation netease-music API Scripting

Đăng vào ngày 12 tháng 7 lúc 12:26