1 """ 2 3 用selenium+PhantomJS配合,不需要进行逆向工程 4 python 3下的selenium不能默认安装,需要指定版本2.48.0 5 """ 6 from selenium import webdriver 7 import os,requests 8 9 10 11 url = 'https://music.163.com/#/playlist?id=884698131'#网易云音乐歌单 12 headers = { 13 'User-Agent':'User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36', 14 } 15 driver = webdriver.PhantomJS() 16 driver.get(url) 17 driver.implicitly_wait(20)#隐式等待20s 18 #pprint.pprint(driver.page_source)#查看源代码 19 20 def is_chinese(uchar): 21 """ 22 判断一个unicode是否是汉字 23 :param uchar: <char>字符 24 :return: <boolean> 25 """ 26 if uchar >= u'\u4e00' and uchar <= u'\u9fa5': 27 return True 28 else: 29 return False 30 31 def is_number(uchar): 32 """ 33 判断一个unicode是否是数字 34 :param uchar: <char>字符 35 :return: <boolean> 36 """ 37 if uchar >= u'\u0030' and uchar <= u'\u0039': 38 return True 39 else: 40 return False 41 42 43 def is_alphabet(uchar): 44 """ 45 判断一个unicode是否是英文字母 46 :param uchar: <char>字符 47 :return: <boolean> 48 """ 49 if (uchar >= u'\u0041' and uchar <= u'\u005a') or (uchar >= u'\u0061' and uchar <= u'\u007a'): 50 return True 51 else: 52 return False 53 def is_filename(uchar): 54 """ 55 排除文件名不可用的字符,这里请注意都是在英文输入法下的,若是中文输入法下的例如?“等是可以用来生成文件名的 56 \/:*?"<>| 57 :param uchar: 58 :return: 59 """ 60 if uchar == u'\u005c' or uchar == u'\u002f' or uchar == u'\u003a' or uchar == u'\u002a' or uchar == u'\u003f' or uchar == u'\u007c' \ 61 or uchar == u'\u003c' or uchar == u'\u003e' or uchar == u'\u007c': 62 return False 63 else: 64 return True 65 66 def format_str(content): 67 """ 68 将字符串content中的字符逐个判断 69 :param content: <str>输入文本 70 :return: <str>输出只包含中文、数字及英文字母的字符串 71 """ 72 content_str = '' 73 for i in content: 74 if is_chinese(i) or is_alphabet(i) or is_number(i): 75 content_str = content_str+i 76 print('处理后的content:',content_str) 77 return content_str 78 79 def format_str2(content): 80 81 content_str = '' 82 for i in content: 83 if is_filename(i): 84 content_str = content_str+i 85 print('处理后的content:',content_str) 86 return content_str 87 88 89 driver.switch_to.frame('g_iframe')#跳转到id为g_iframe的iframe框架下 90 91 92 list_name = driver.find_element_by_class_name('f-ff2').text #歌单名称 93 #大坑,源代码中是class=“f-ff2 f-brk”,属性值中间有空格,全写上报错 94 # #list_name2 = driver.find_element_by_xpath('//div[@class=\"m-info\"]/div[2]') 95 print(list_name) 96 97 #list_path = os.getcwd()+ '/网易云音乐歌单-' + format_str(list_name) 98 list_path = os.getcwd()+ '/网易云音乐歌单-' + format_str2(list_name) 99 100 if os.path.exists(list_path): 101 pass 102 else: 103 os.mkdir(list_path)#若文件夹不存在,则新建 104 105 ids = driver.find_elements_by_xpath('//a[starts-with(@href,"/song?id=")]') 106 names = driver.find_elements_by_xpath('//a[starts-with(@href,"/song?id=")]/b') 107 for i in range(0,len(ids)): 108 #id = ids[i].get_attribute('href').strip('https://music.163.com/song?id=')#有问题,获取的某些歌曲id不全,原因未知 109 id = ids[i].get_attribute('href').replace('https://music.163.com/song?id=','') 110 name = format_str2(names[i].get_attribute('title').strip().replace('/','')) 111 112 print(id,name) 113 link = 'http://music.163.com/song/media/outer/url?id=' + id + '.mp3' 114 #urllib.request.urlretrieve(link,'E:/'+id+'.mp3')#有时候下载下来的歌曲只有几十kb 115 116 if os.path.exists(list_path + '/' + str(i + 1) + '_' + name + '.mp3') \ 117 and (os.path.getsize(list_path + '/' + str(i + 1) + '_' + name + '.mp3')) >= 102400: 118 # 若歌曲存在且能正常播放(此处判断为大于100kb)则不再下载 119 pass 120 121 else: 122 with open(list_path + '/' + str(i + 1) + '_' + name + '.mp3', 'wb') as f: 123 f.write(requests.get(link, headers=headers).content) 124 125 #有些歌曲能下载下来但是只有67kb左右,也无法播放,也就是网易云上显示但是无法在线听的音乐 126 if os.path.getsize(list_path + '/' + str(i + 1) + '_' + name + '.mp3') < 102400: 127 os.remove(list_path + '/' + str(i + 1) + '_' + name + '.mp3') 128 else: 129 pass 130 131 driver.switch_to.default_content()#返回主文档