我用一天时间“偷了”网易云音乐50W+用户信息 / python爬虫

没有多进程,没有任何黑科技的裸爬虫。练手用,爬虫获取到的数据皆为公开且非敏感的用户信息。

目录

一、思路

二、参数加密流程分析

三、代码实现

common.py (需要用到的函数)

demo.py (主程序)

四、数据



一、思路

在GitHub上已经有网易云音乐的node.js API(GitHub:https://github.com/Binaryify/NeteaseCloudMusicApi)。根据这个库提供的信息,可以很轻易的获取到网易云音乐获取某个用户的粉丝信息接口的参数(接口限制只能获取100个),进而继续获取这100个粉丝的粉丝…简单的几层循环嵌套就能很轻易的拿到十万级到百万级的用户数据(非敏感用户信息)。

 

二、参数加密流程分析

__getFormData(data, __get_random_str())
    参数1:data是dict数据,包含了表单的各个字段和数据
    参数2:16位的随机字符串
    最终return的是一个dict,包含了params和encSecKey两个参数

    params
        __get_encText(args1, random16str)
            参数1:args1是__getFormData函数的参数1,是dict数据,包含了表单的各个字段和数据
            参数2:random16str是__getFormData函数的参数2,是一个16位的随机字符串
            最终返回的是将参数加密后产生的params

            __AES_encrypt(args1, args4)
                参数1:args1是__get_encText函数的参数1,是dict数据,包含了表单的各个字段和数据
                参数2:arg4是一个固定参数
                最终返回的是将参数使用AES CBC加密后再进行一次base64加密产生的字符串
            
            使用__AES_encrypt函数首先加密一次参数是(args1,args4)得到一个加密的字符串
            在使用加密过一次的字符串作为参数1,和__get_encText函数传入的参数2 random16str 这个随机16位的字符串作为参数2继续加密1次
            最终得到params

    encSecKey
        __get_encSecKey(random16str)
            参数1:random16str是__getFormData函数的参数2,是一个16位的随机字符串
            最终返回的是通过随机字符串产生的encSecKey

            固定参数arg2
            固定参数arg3
            通过固定算法,使用随机16位的字符串random16str与这两个固定参数产生encSecKey

 

三、代码实现

common.py (需要用到的函数)

import base64
from Crypto.Cipher import AES
import random
import codecs
import requests
from fake_useragent import UserAgent


def __AES_encrypt(text, key):
    '''
    获取到加密后的数据
    :param text: 首先CBC加密方法,text必须位16位数据
    :param key: 加密的key
    :return: 加密后的字符串
    '''
    iv = "0102030405060708"
    pad = 16 - len(text) % 16
    if isinstance(text, str):
        text = text + pad * chr(pad)
    else:
        text = text.deocde("utf-8") + pad * chr(pad)
    aes = AES.new(key=bytes(key, encoding="utf-8"), mode=2, IV=bytes(iv, encoding="utf-8"))
    res = aes.encrypt(bytes(text, encoding="utf-8"))
    res = base64.b64encode(res).decode("utf-8")
    return res


def __get_encText(args1, random16str):
    args4 = "0CoJUm6Qyw8W8jud"

    encText = __AES_encrypt(args1, args4)
    encText = __AES_encrypt(encText, random16str)
    return encText


def __get_encSecKey(random16str):
    '''通过查看js代码,获取encSecKey'''
    arg2 = "010001"
    arg3 = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"

    text = random16str[::-1]
    rs = int(codecs.encode(text.encode('utf-8'), 'hex_codec'), 16) ** int(arg2, 16) % int(arg3, 16)
    return format(rs, 'x').zfill(256)


def __get_random_str():
    '''这是16位的随机字符串'''
    str_set = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    random_str = ""
    for i in range(16):
        index = random.randint(0, len(str_set) - 1)
        random_str += str_set[index]
    return random_str


def __getFormData(args1, random16str):
    '''获取到提交的数据'''
    data = {"params": __get_encText(args1, random16str), "encSecKey": __get_encSecKey(random16str)}
    return data


def __getFans(userID):
    userDict = {}
    userID = str(userID)  # userID="6177307"

    data = '{"userId":"' + userID + '","time":"-1","limit":"104334","csrf_token": ""}'
    formdata = __getFormData(data, __get_random_str())

    ua = UserAgent()
    session = requests.Session()
    headers = {}
    headers["content-type"] = "application/x-www-form-urlencoded"
    headers["user-agent"] = ua.random
    headers["referer"] = "https://music.163.com/"

    response = session.post(url='https://music.163.com/weapi/user/getfolloweds', headers=headers,
                            data=formdata)
    results = response.json()
    # print(response.status_code)
    results = results.get('followeds')
    for one in results:
        userDict[one.get('userId')] = one
        # print(one.get('userId'))
        # print(str(one))
    return userDict

 

demo.py (主程序)

# -*- coding: utf-8 -*-
import common

AllData = {}
data = common.__getFans(6177307)
AllData.update(data)
sum = 0
for item in data:
    temp = common.__getFans(item)
    AllData.update(temp)
    for item1 in temp:
        temp2 = common.__getFans(item1)
        AllData.update(temp2)
        for item2 in temp2:
            sum += 1
            print(sum)
            temp3 = common.__getFans(item2)
            AllData.update(temp3)

with open('fans.txt', 'a', encoding='utf-8') as f:
    for one in AllData.items():
        f.write(str(one) + '\n')
        print(str(one))

 

四、数据

我把demo.py放到了服务器上运行,跑到程序结束大概用了24小时左右后看了一下存储的文本有50W左右的用户数据(不含敏感信息),以下用户信息为网易云公开数据,并且已经对部分数据进行打码。(已通过网易云音乐客户端私信征求用户同意)

(8****823, {'py': 'm**st', 'time': 1510*****4852, 'userId': 8******3, 'mutual': False, 'followed': False, 'accountStatus': 0, 'nickname': '名剑****收天', 'avatarUrl': 'http://p1.music.126.net/uocXBF145t-_V0pLWDwv0w==/3272146604393759.jpg', 'gender': 1, 'expertTags': None, 'experts': None, 'followeds': 13, 'remarkName': None, 'follows': 19, 'authStatus': 0, 'userType': 0, 'vipType': 0, 'signature': '天下若倾,尚有儒门一手擎天!', 'vipRights': None, 'eventCount': 1, 'playlistCount': 5})
(30****375, {'py': 'tt******y', 'time': 15107******003, 'userId': 305******5, 'mutual': False, 'followed': False, 'accountStatus': 0, 'nickname': '甜****ny', 'avatarUrl': 'http://p1.music.126.net/v9iyq-6I1WC96R7SlbKvXQ==/3420580709664324.jpg', 'gender': 1, 'expertTags': None, 'experts': None, 'followeds': 4, 'remarkName': None, 'follows': 30, 'authStatus': 0, 'userType': 0, 'vipType': 11, 'signature': None, 'vipRights': {'associator': {'vipCode': 100, 'rights': True}, 'musicPackage': None, 'redVipAnnualCount': -1}, 'eventCount': 0, 'playlistCount': 3})
(35****22, {'py': 'x******jl-_', 'time': 150941******9, 'userId': 35******2, 'mutual': False, 'followed': False, 'accountStatus': 0, 'nickname': '醒*****家了-_', 'avatarUrl': 'http://p1.music.126.net/KcAVTPDSC8MrKaFB9_Vd9g==/109951163985306640.jpg', 'gender': 1, 'expertTags': None, 'experts': None, 'followeds': 4, 'remarkName': None, 'follows': 9, 'authStatus': 0, 'userType': 0, 'vipType': 0, 'signature': '身邪不怕影子正', 'vipRights': None, 'eventCount': 0, 'playlistCount': 7})

 

#python #网易云音乐 #爬虫

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章