当前位置:   article > 正文

手把手操作JS逆向爬虫(二)_逆向 爬虫 uuid

逆向 爬虫 uuid

本案例独立完成,没有参考任何资料。虽说不是什么高难度的JS逆向,但对新手来说还是有点难度的。话不多说,开始正题。本次破解的目标是音乐网站的歌曲下载。

目标网站:
未免侵权,此处省略。需要的私我。

基本思路:
搜索歌曲名字,获得歌曲地址,完成下载。

逆向过程:
1、搜索歌曲,通过手动观察和查找,不难在Network下的JS面板下找到目标请求信息。

2、我们来看一下这个请求的具体信息:

Headers:

Playload:看得出来有很多参数,一个截图都放不下。

 

 3、找到加密参数。通过搜索不同的歌曲名字,比较请求信息,可以看出每次请求中有变化的参数是keyword和signature,还有clienttime,mid,uuid共5个参数。其中后三个很显然是时间戳,keyword是搜索的歌曲名字。所以最关键的参数就是signature。接下去要做的就是找到该参数的生成原理。

4、在开发者状态下,点击search,输入signature.

 ,结果只有一个,双击打开,再点击美化打印。

就能看到如下界面:

5、来看这行的代码:
h.signature = faultylabs.MD5(o.join("")),
原来signature参数就是一个函数(faultylabs.MD5)带一个参数(o.join(""))生成的。
从函数名称就知道,该函数是把字符串做md5加密,并返回大写的字母。

如果看不出来,也可以这抠代码。
打上断点,刷新,鼠标移至MD5,系统提示这个函数就是anonymous(a)。

 点击该函数,显示如下界面:

 函数很长,末尾是这样的,

 把整个函数抠出来做成一个新的js文件,然后任一字符串参数测试下这个函数的作用,结果是一长
串数字和大写字母。

和直接用python的md5加密hashlib.md5(string.encode(encoding='utf-8')).hexdigest()结果是一样的。

6、现在就剩下参数,就是o.join("")的生成原理了。很显然,就是将列表o的字符串进行拼接。
那么列表o哪里来的? 我们在join前面的小框勾选上,再执行 :


到这里的时候,我们在Console面板看下o的结果,输入o,得到:

 这个o的值是否很熟悉?没错就是,把请求参数字典的键值对用“=”拼接,作为列表的元素。然后再列表前后加入固定字符串'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt'
注意这里是部分参数,并且按照一定的顺序!这里是个坑。

到此,所有的加密原理已经搞定。
那么,是否完成载?还没有!别高兴得太早!我们只是搞定了请求,能获得如下结果:

7、 那么如何根据这些结果能够获得音乐的下载链接呢?
回到最初的搜过结果,点击任一结果,弹出的窗口地址如下,形如https://www.kugou.com/song/#hash={filehash}&album_id={album_id}

 只要拿到filehash和albumid两个参数就可以构造音乐请求的地址,而这两个参数都已经获取了。

 8、下一步是获取歌曲链接地址。进入音乐播放窗口,点右键,点检查,查看网页源码。
搜索mp3,结果如下:

可是 根据上述的歌曲播放地址构造请求,发现结果里面没有mp3文件。判断是用了动态渲染技术,所以想到selenium请求获取歌曲地址,然后就可以通过requests请求下载了。

至此,整个音乐下载的过程都完成了。上完整代码如下:    

  1. '''
  2. construct rquests address, then get '.mp3' address in the response. then download by requests it.
  3. '''
  4. import requests,pprint,re,json,time,hashlib
  5. from selenium import webdriver
  6. # from selenium.webdriver.chrome.options import Options
  7. headers = {
  8. 'authority': 'complexsearch.kugou.com',
  9. 'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"',
  10. 'sec-ch-ua-mobile': '?0',
  11. 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36',
  12. 'sec-ch-ua-platform': '"Windows"',
  13. 'accept': '*/*',
  14. 'sec-fetch-site': 'same-site',
  15. 'sec-fetch-mode': 'no-cors',
  16. 'sec-fetch-dest': 'script',
  17. 'referer': 'https://www.kugou.com/',
  18. 'accept-language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7',
  19. 'cookie': 'kg_mid=1a8bf97ec26db1b38258848ec815e0a4',
  20. }
  21. def get_sign(params):
  22. '''
  23. return 'signature' parameter to be used in requests.
  24. Param: a dict of requests paramter
  25. '''
  26. string=''
  27. for i in params:
  28. temp=i+'='+params[i]
  29. string+=temp
  30. # print(string)
  31. string='NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt'+string+'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt' #add a string before and after the string
  32. return hashlib.md5(string.encode(encoding='utf-8')).hexdigest().upper() #md5 encrpted,then capitilized.
  33. def search_music(song_name):
  34. '''
  35. return a list of all searching results.
  36. '''
  37. search_results=[]
  38. params = {'bitrate':'0',
  39. 'callback': 'callback123',
  40. 'clienttime':str(int(time.time()*1000)),
  41. 'clientver':'2000',
  42. 'dfid':'-',
  43. 'inputtype':'0',
  44. 'iscorrection':'1',
  45. 'isfuzzy':'0',
  46. 'keyword': song_name,
  47. 'mid':str(int(time.time()*1000)),
  48. 'page': '1',
  49. 'pagesize': '30',
  50. 'platform':'WebFilter',
  51. 'privilege_filter':'0',
  52. 'srcappid':'2919',
  53. 'tag':'em',
  54. 'token':'',
  55. 'userid':'0',
  56. 'uuid':str(int(time.time()*1000)),
  57. }
  58. params['signature']=get_sign(params)
  59. # print(params['signature'])
  60. # print(params)
  61. response = requests.get('https://complexsearch.kugou.com/v2/search/song', headers=headers, params=params)
  62. # print(response.status_code)
  63. text=response.text[12:-2]
  64. search_data=json.loads(text)['data']['lists']
  65. # pprint.pprint(search_results)
  66. # print(len(search_results))
  67. for i in search_data:
  68. # print(i)
  69. music_list={}
  70. music_list['FileName']=i['FileName'].replace('<em>','').replace('</em>','')
  71. music_list['FileHash']=i['FileHash']
  72. music_list['AlbumID']=i['AlbumID']
  73. print(music_list['FileName'])
  74. # print(i['FileName'].replace('<em>','').replace('</em>',''),i['FileHash'],i['AlbumID'])
  75. search_results.append(music_list)
  76. # print(search_results)
  77. return search_results
  78. def get_song_address(search_results):
  79. filehash=search_results[0]['FileHash']
  80. album_id=search_results[0]['AlbumID']
  81. url=f'https://www.kugou.com/song/#hash={filehash}&album_id={album_id}'
  82. # print(url)
  83. options=webdriver.ChromeOptions()
  84. options.add_argument('user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"')
  85. options.add_argument('--headless')
  86. options.add_experimental_option('excludeSwitches', ['enable-logging']) #remove all annoying reminder like DevTools listening on ws://127.0.0.1:51589/devtools/browse
  87. driver=webdriver.Chrome(options=options)
  88. # driver=webdriver.PhantomJS() #no working
  89. driver.get(url)
  90. time.sleep(1)
  91. # html=driver.page_source
  92. # print(type(html))
  93. music_address=driver.find_element_by_id('myAudio').get_attribute('src')
  94. driver.close()
  95. print(music_address)
  96. return music_address
  97. def get_song(music_address):
  98. with open('D:\\kugoumusic\\'+song_name+'.mp3','wb') as file: #downloading songs
  99. res=requests.get(music_address,headers=headers)
  100. file.write(res.content)
  101. if __name__=='__main__':
  102. song_name=input('请输入要下载的歌名:')
  103. print(f'开始搜索: {song_name} 请耐心等待!')
  104. search_results=search_music(song_name)
  105. print(f'正在抓取歌曲地址:')
  106. music_address=get_song_address(search_results)
  107. get_song(music_address)
  108. print(song_name,"下载完成!")

   

总结:

1、要有足够的耐心阅读JS代码,找到参与的生成原理。

2、实际破解过程并非上述过程。
其实是这样的:
a.先搜索歌名,点击其中一个搜索结果,打开窗口播放歌曲,找到歌曲下载地址。
b.找到后,发现地址很请求地址完全没有联系,至少我没看出来。并且请求结果是没有歌曲地址的。于是想到selenium请求。
c.那问题是请求地址如何构造?从如下歌曲播放的窗口地址可以看出来,只需要filehash和albumid。https://www.kugou.com/song/#hash=CADCA036BF15D4D06EFAD005DD2F40F2&album_id=970586
这两个参数都可以从歌曲搜索的结果里找到。
d.所以问题转化为如何完成搜索?也就是如何通过生成加参数,然后构造请求获得搜索结果。这就是本文开始一大半篇幅的内容所在。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/89918
推荐阅读
相关标签
  

闽ICP备14008679号