(.+?)<', html).group(1)
716 | d = modificate_text(artist_name + u' - top 20')
717 | dir_ = os.path.join(os.getcwdu(), d)
718 | self.dir_ = modificate_file_name_for_wget(dir_)
719 | amount_songs = unicode(len(song_ids))
720 | print(s % (2, 97, u'\n >> ' + amount_songs + u' 首歌曲将要下载.')) \
721 | if not args.play else ''
722 | n = 1
723 | for i in song_ids:
724 | songs = self.get_song(i)
725 | self.download(songs, amount_songs, n)
726 | self.html = ''
727 | self.disc_description_archives = {}
728 | n += 1
729 |
730 | def download_artist_radio(self):
731 | html = ss.get(url_artist_top_song % self.artist_id).text
732 | artist_name = re.search(
733 | r'(.+?)<', html).group(1)
734 | d = modificate_text(artist_name + u' - radio')
735 | dir_ = os.path.join(os.getcwdu(), d)
736 | self.dir_ = modificate_file_name_for_wget(dir_)
737 |
738 | url_artist_radio = "http://www.xiami.com/radio/xml/type/5/id/%s" \
739 | % self.artist_id
740 | n = 1
741 | while True:
742 | xml = ss.get(url_artist_radio).text
743 | song_ids = re.findall(r'(\d+)', xml)
744 | for i in song_ids:
745 | songs = self.get_song(i)
746 | self.download(songs, n=n)
747 | self.html = ''
748 | self.disc_description_archives = {}
749 | n += 1
750 |
751 | def download_user_songs(self, url, desc):
752 | dir_ = os.path.join(os.getcwdu(),
753 | u'虾米用户 %s %s' % (self.user_id, desc))
754 | self.dir_ = modificate_file_name_for_wget(dir_)
755 | ii = 1
756 | n = 1
757 | while True:
758 | html = ss.get(url % (self.user_id, str(ii))).text
759 | song_ids = re.findall(r'/song/(.+?)"', html)
760 | if song_ids:
761 | for i in song_ids:
762 | songs = self.get_song(i)
763 | self.download(songs, n)
764 | self.html = ''
765 | self.disc_description_archives = {}
766 | n += 1
767 | else:
768 | break
769 | ii += 1
770 |
771 | def download_user_shares(self, url_shares):
772 | d = modificate_text(u'%s 的分享' % self.user_id)
773 | dir_ = os.path.join(os.getcwdu(), d)
774 | self.dir_ = modificate_file_name_for_wget(dir_)
775 | page = 1
776 | while True:
777 | html = ss.get(url_shares % page).text
778 | shares = re.findall(r'play.*\(\'\d+\'\)', html)
779 | for share in shares:
780 | if 'album' in share:
781 | self.album_id = re.search(r'\d+', share).group()
782 | self.download_album()
783 | else:
784 | self.song_id = re.search(r'\d+', share).group()
785 | self.download_song()
786 | if not shares: break
787 | page += 1
788 |
789 | def download_user_radio(self, url_rndsongs):
790 | d = modificate_text(u'%s 的虾米推荐' % self.user_id)
791 | dir_ = os.path.join(os.getcwdu(), d)
792 | self.dir_ = modificate_file_name_for_wget(dir_)
793 | n = 1
794 | while True:
795 | xml = ss.get(url_rndsongs % self.user_id).text
796 | song_ids = re.findall(r'(\d+)', xml)
797 | for i in song_ids:
798 | songs = self.get_song(i)
799 | self.download(songs, n=n)
800 | self.html = ''
801 | self.disc_description_archives = {}
802 | n += 1
803 |
804 | def download_chart(self, type_):
805 | html = ss.get('http://www.xiami.com/chart/index/c/%s' \
806 | % self.chart_id).text
807 | title = re.search(r'(.+?)', html).group(1)
808 | d = modificate_text(title)
809 | dir_ = os.path.join(os.getcwdu(), d)
810 | self.dir_ = modificate_file_name_for_wget(dir_)
811 |
812 | html = ss.get(
813 | 'http://www.xiami.com/chart/data?c=%s&limit=200&type=%s' \
814 | % (self.chart_id, type_)).text
815 | song_ids = re.findall(r'/song/(\d+)', html)
816 | n = 1
817 | for i in song_ids:
818 | songs = self.get_song(i)
819 | self.download(songs, n=n)
820 | self.html = ''
821 | self.disc_description_archives = {}
822 | n += 1
823 |
824 | def download_genre(self, url_genre):
825 | html = ss.get(url_genre % (self.genre_id, 1)).text
826 | if '/gid/' in url_genre:
827 | t = re.search(
828 | r'/genre/detail/gid/%s".+?title="(.+?)"' \
829 | % self.genre_id, html).group(1)
830 | elif '/sid/' in url_genre:
831 | t = re.search(
832 | r'/genre/detail/sid/%s" title="(.+?)"' \
833 | % self.genre_id, html).group(1)
834 | d = modificate_text(u'%s - 代表曲目 - xiami' % t)
835 | dir_ = os.path.join(os.getcwdu(), d)
836 | self.dir_ = modificate_file_name_for_wget(dir_)
837 |
838 | n = 1
839 | page = 2
840 | while True:
841 | song_ids = re.findall(r'/song/(\d+)', html)
842 | if not song_ids: break
843 | for i in song_ids:
844 | songs = self.get_song(i)
845 | self.download(songs, n=n)
846 | self.html = ''
847 | self.disc_description_archives = {}
848 | n += 1
849 | html = ss.get(url_genre % (self.chart_id, page)).text
850 | page += 1
851 |
852 | def download_genre_radio(self, url_genre):
853 | html = ss.get(url_genre % (self.genre_id, 1)).text
854 | if '/gid/' in url_genre:
855 | t = re.search(
856 | r'/genre/detail/gid/%s".+?title="(.+?)"' \
857 | % self.genre_id, html).group(1)
858 | url_genre_radio = "http://www.xiami.com/radio/xml/type/12/id/%s" \
859 | % self.genre_id
860 | elif '/sid/' in url_genre:
861 | t = re.search(
862 | r'/genre/detail/sid/%s" title="(.+?)"' \
863 | % self.genre_id, html).group(1)
864 | url_genre_radio = "http://www.xiami.com/radio/xml/type/13/id/%s" \
865 | % self.genre_id
866 | d = modificate_text(u'%s - radio - xiami' % t)
867 | dir_ = os.path.join(os.getcwdu(), d)
868 | self.dir_ = modificate_file_name_for_wget(dir_)
869 |
870 | n = 1
871 | while True:
872 | xml = ss.get(url_genre_radio).text
873 | song_ids = re.findall(r'(\d+)', xml)
874 | for i in song_ids:
875 | songs = self.get_song(i)
876 | self.download(songs, n=n)
877 | self.html = ''
878 | self.disc_description_archives = {}
879 | n += 1
880 |
881 | def hack_luoo(self, url):
882 | # parse luoo.net
883 | theaders = headers
884 | theaders.pop('Referer')
885 | r = requests.get(url)
886 | if not r.ok:
887 | return None
888 | cn = r.content
889 | songs_info = re.findall(r'(.+?)
\s+'
890 | r'Artist: (.+?)
\s+'
891 | r'Album: (.+?)
', cn)
892 |
893 | # search song at xiami
894 | for info in songs_info:
895 | url = 'http://www.xiami.com/web/search-songs?key=%s' \
896 | % urllib.quote(' '.join(info))
897 | r = ss.get(url)
898 | j = r.json()
899 | if not r.ok or not j:
900 | print s % (1, 93, ' !! no find:'), ' - '.join(info)
901 | continue
902 | self.song_id = j[0]['id']
903 | self.download_song()
904 |
905 | def display_infos(self, i, nn, n):
906 | print n, '/', nn
907 | print s % (2, 94, i['file_name'])
908 | print s % (2, 95, i['album_name'])
909 | print 'http://www.xiami.com/song/%s' % i['song_id']
910 | print 'http://www.xiami.com/album/%s' % i['album_id']
911 | if i['durl_is_H'] == 'h':
912 | print s % (1, 97, 'MP3-Quality:'), s % (1, 92, 'High')
913 | else:
914 | print s % (1, 97, 'MP3-Quality:'), s % (1, 91, 'Low')
915 | print '—' * int(os.popen('tput cols').read())
916 |
917 | def get_mp3_quality(self, durl):
918 | if 'm3.file.xiami.com' in durl or 'm6.file.xiami.com' in durl:
919 | return 'h'
920 | else:
921 | return 'l'
922 |
923 | def play(self, songs, nn=u'1', n=1):
924 | if args.play == 2:
925 | songs = sorted(songs, key=lambda k: k['song_played'], reverse=True)
926 | for i in songs:
927 | self.record(i['song_id'])
928 | durl = self.get_durl(i['song_id'])
929 | if not durl:
930 | print s % (2, 91, ' !! Error: can\'t get durl'), i['song_name']
931 | continue
932 |
933 | mp3_quality = self.get_mp3_quality(durl)
934 | i['durl_is_H'] = mp3_quality
935 | self.display_infos(i, nn, n)
936 | n = int(n) + 1
937 | cmd = 'mpv --really-quiet ' \
938 | '--cache 8146 ' \
939 | '--user-agent "%s" ' \
940 | '--http-header-fields="Referer:http://img.xiami.com' \
941 | '/static/swf/seiya/1.4/player.swf?v=%s" ' \
942 | '"%s"' \
943 | % (headers['User-Agent'], int(time.time()*1000), durl)
944 | os.system(cmd)
945 | timeout = 1
946 | ii, _, _ = select.select([sys.stdin], [], [], timeout)
947 | if ii:
948 | sys.exit(0)
949 | else:
950 | pass
951 |
952 | def download(self, songs, amount_songs=u'1', n=1):
953 | dir_ = modificate_file_name_for_wget(self.dir_)
954 | cwd = os.getcwd()
955 | if dir_ != cwd:
956 | if not os.path.exists(dir_):
957 | os.mkdir(dir_)
958 |
959 | ii = 1
960 | for i in songs:
961 | num = random.randint(0, 100) % 8
962 | col = s % (2, num + 90, i['file_name'])
963 | t = modificate_file_name_for_wget(i['file_name'])
964 | file_name = os.path.join(dir_, t)
965 | if os.path.exists(file_name): ## if file exists, no get_durl
966 | if args.undownload:
967 | self.modified_id3(file_name, i)
968 | ii += 1
969 | n += 1
970 | continue
971 | else:
972 | ii += 1
973 | n += 1
974 | continue
975 |
976 | if not args.undownload:
977 | if n == None:
978 | print(u'\n ++ download: #%s/%s# %s' \
979 | % (ii, amount_songs, col))
980 | else:
981 | print(u'\n ++ download: #%s/%s# %s' \
982 | % (n, amount_songs, col))
983 | n += 1
984 |
985 | durl = self.get_durl(i['song_id'])
986 | if not durl:
987 | print s % (2, 91, ' |-- Error: can\'t get durl')
988 | continue
989 |
990 | mp3_quality = self.get_mp3_quality(durl)
991 | if mp3_quality == 'h':
992 | print ' |--', s % (1, 97, 'MP3-Quality:'), s % (1, 91, 'High')
993 | else:
994 | print ' |--', s % (1, 97, 'MP3-Quality:'), s % (1, 91, 'Low')
995 |
996 | file_name_for_wget = file_name.replace('`', '\`')
997 | quiet = ' -q' if args.quiet else ' -nv'
998 | cmd = 'wget -c%s ' \
999 | '-U "%s" ' \
1000 | '--header "Referer:http://img.xiami.com' \
1001 | '/static/swf/seiya/1.4/player.swf?v=%s" ' \
1002 | '-O "%s.tmp" %s' \
1003 | % (quiet, headers['User-Agent'], int(time.time()*1000),
1004 | file_name_for_wget, durl)
1005 | cmd = cmd.encode('utf8')
1006 | status = os.system(cmd)
1007 | if status != 0: # other http-errors, such as 302.
1008 | wget_exit_status_info = wget_es[status]
1009 | print('\n\n ----### \x1b[1;91mERROR\x1b[0m ==> \x1b[1;91m%d ' \
1010 | '(%s)\x1b[0m ###--- \n\n' % (status, wget_exit_status_info))
1011 | print s % (1, 91, ' ===> '), cmd
1012 | sys.exit(1)
1013 | else:
1014 | os.rename('%s.tmp' % file_name, file_name)
1015 |
1016 | self.modified_id3(file_name, i)
1017 | ii += 1
1018 | time.sleep(5)
1019 |
1020 | def _save_do(self, id_, type, tags):
1021 | data = {
1022 | "tags": tags,
1023 | "type": type,
1024 | "id": id_,
1025 | "desc": "",
1026 | "grade": "",
1027 | "share": 0,
1028 | "shareTo": "all",
1029 | "_xiamitoken": ss.cookies['_xiamitoken'],
1030 | }
1031 | url = 'http://www.xiami.com/ajax/addtag'
1032 | r = ss.post(url, data=data)
1033 | j = r.json()
1034 | if j['status'] == 'ok':
1035 | return 0
1036 | else:
1037 | return j['status']
1038 |
1039 | def save(self, urls):
1040 | tags = args.tags
1041 | for url in urls:
1042 | if '/collect/' in url:
1043 | collect_id = re.search(r'/collect/(\d+)', url).group(1)
1044 | print s % (1, 97, u'\n ++ save collect:'), \
1045 | 'http://www.xiami.com/song/collect/' + collect_id
1046 | result = self._save_do(collect_id, 4, tags)
1047 |
1048 | elif '/album/' in url:
1049 | album_id = re.search(r'/album/(\d+)', url).group(1)
1050 | print s % (1, 97, u'\n ++ save album:'), \
1051 | 'http://www.xiami.com/album/' + album_id
1052 | result = self._save_do(album_id, 5, tags)
1053 |
1054 | elif '/artist/' in url:
1055 | artist_id = re.search(r'/artist/(\d+)', url).group(1)
1056 | print s % (1, 97, u'\n ++ save artist:'), \
1057 | 'http://www.xiami.com/artist/' + artist_id
1058 | result = self._save_do(artist_id, 6, tags)
1059 |
1060 | elif '/song/' in url:
1061 | song_id = re.search(r'/song/(\d+)', url).group(1)
1062 | print s % (1, 97, u'\n ++ save song:'), \
1063 | 'http://www.xiami.com/song/' + song_id
1064 | result = self._save_do(song_id, 3, tags)
1065 |
1066 | else:
1067 | print(s % (2, 91, u' 请正确输入虾米网址.'))
1068 |
1069 | if result == 0:
1070 | print s % (1, 92, ' ++ success.\n')
1071 | else:
1072 | print s % (1, 91, ' !! Error at _save_do.'), result, '\n'
1073 |
1074 | def main(argv):
1075 | if len(argv) < 2:
1076 | sys.exit()
1077 |
1078 | ######################################################
1079 | # for argparse
1080 | p = argparse.ArgumentParser(description='downloading any xiami.com')
1081 | p.add_argument('xxx', type=str, nargs='*', \
1082 | help='命令对象.')
1083 | p.add_argument('-p', '--play', action='count', \
1084 | help='play with mpv')
1085 | p.add_argument('-l', '--low', action='store_true', \
1086 | help='low mp3')
1087 | p.add_argument('-q', '--quiet', action='store_true', \
1088 | help='quiet for download')
1089 | p.add_argument('-f', '--from_', action='store', \
1090 | default=1, type=int, \
1091 | help='从第几个开始下载,eg: -f 42')
1092 | p.add_argument('-d', '--undescription', action='store_true', \
1093 | help='no add disk\'s distribution')
1094 | p.add_argument('-t', '--tags', action='store', \
1095 | type=str, default='', help='tags. eg: piano,cello')
1096 | p.add_argument('-n', '--undownload', action='store_true', \
1097 | help='no download, using to renew id3 tags')
1098 | global args
1099 | args = p.parse_args(argv[2:])
1100 | comd = argv[1]
1101 | xxx = args.xxx
1102 |
1103 | if comd == 'login' or comd == 'g':
1104 | # or comd == 'logintaobao' or comd == 'gt':
1105 | # taobao has updated login algorithms which is hard to hack
1106 | # so remove it.
1107 | if len(xxx) < 1:
1108 | email = raw_input(s % (1, 97, ' username: ') \
1109 | if comd == 'logintaobao' or comd == 'gt' \
1110 | else s % (1, 97, ' email: '))
1111 | password = getpass(s % (1, 97, ' password: '))
1112 | elif len(xxx) == 1:
1113 | # for add_member_auth
1114 | if '@' not in xxx[0]:
1115 | x = xiami()
1116 | x.add_member_auth(xxx[0])
1117 | x.check_login()
1118 | return
1119 |
1120 | email = xxx[0]
1121 | password = getpass(s % (1, 97, ' password: '))
1122 | elif len(xxx) == 2:
1123 | email = xxx[0]
1124 | password = xxx[1]
1125 | else:
1126 | print s % (1, 91,
1127 | ' login\n login email\n \
1128 | login email password')
1129 |
1130 | x = xiami()
1131 | if comd == 'logintaobao' or comd == 'gt':
1132 | x.login_taobao(email, password)
1133 | else:
1134 | x.login(email, password)
1135 | is_signin = x.check_login()
1136 | if is_signin:
1137 | print s % (1, 92, ' ++ login succeeds.')
1138 | else:
1139 | print s % (1, 91, ' login failes')
1140 |
1141 | elif comd == 'signout':
1142 | g = open(cookie_file, 'w')
1143 | g.close()
1144 |
1145 | elif comd == 'd' or comd == 'download':
1146 | urls = xxx
1147 | x = xiami()
1148 | x.init()
1149 | x.url_parser(urls)
1150 |
1151 | elif comd == 'p' or comd == 'play':
1152 | if not args.play: args.play = 1
1153 | urls = xxx
1154 | x = xiami()
1155 | x.init()
1156 | x.url_parser(urls)
1157 |
1158 | elif comd == 's' or comd == 'save':
1159 | urls = xxx
1160 | x = xiami()
1161 | x.init()
1162 | x.save(urls)
1163 |
1164 | else:
1165 | print s % (2, 91, u' !! 命令错误\n')
1166 |
1167 | if __name__ == '__main__':
1168 | argv = sys.argv
1169 | main(argv)
1170 |
--------------------------------------------------------------------------------