preface

Download all the videos uploaded by the designated UP host on B website. Without further ado, let’s begin happily ~

The development tools

Python version: 3.6.4
Related modules:

DecryptLogin module;

The argparse module;

And some modules that come with Python.

Environment set up

Install Python and add it to the environment variables. PIP installs the required modules.

Since this library needs to be updated frequently now, I have not uploaded it to PYPI. I will consider uploading it to PYPI later when the functions of this library are more perfect. The list of sites currently supported by the library for mock logins is as follows:

If you have any comments or suggestions about the library, you can open issues here:

https://github.com/CharlesPikachu/DecryptLogin
Copy the code

Introduction of the principle

Here is a brief introduction to the principle, because site B can only download 1080P videos when the user is logged in. So we first used my open DecryptLogin library to simulate logging in to Site B (after all, low quality videos don’t look good). This was simple, just a few lines of code:

from DecryptLogin import login
_, session = login.Login().bilibili(username, password)
Copy the code

Next is the cliche of catching packets, enter a main page of UP:

! [figure (upload images. Jianshu. IO/upload_imag…).

You don’t need this information to capture all of your videos. It’s just used to make sure that the userID you entered is the same as the userID you want to capture.

A few lines of code:

Def __getUserInfo(self, userid): params = {'mid': userid, 'jsonp': 'jsonp'} res = self.session.get(self.user_info_url, params=params, Headers =self.headers) res_json = res.json() user_info = {' username ': res_json['data']['name'], 'gender ': Res_json [' data '] [] 'sex', 'character signature: res_json [' data'] [' sign '], 'user rating: res_json [' data'] [' level '], 'birthday' : res_json['data']['birthday'] } return user_infoCopy the code

Next is to download all the videos of the UP main, because it may be more time to do it (the end of the time is relatively tight T_T), so directly go to you-get source code to find out whether there is a ready-made API, found that the main need for the following three interfaces:

'https://space.bilibili.com/ajax/member/getSubmitVideos'
'https://api.bilibili.com/x/web-interface/view'
'https://api.bilibili.com/x/player/playurl'
Copy the code

First, two interfaces are used to get the basic information of all the videos of the user. According to this information, then the third interface is used to get the download link of the video. Finally, it is OK to download these videos by calling Aria2c. Specifically, the code is implemented as follows:

Def __downloadVideos(self, userid): if not os.path.exists(userid): OS. The mkdir (userid) # non-members users can download the hd 1080 p quality = [(' 16 ', 'smooth 360 p), (' 32', 'clear 480 p), (' 64', 'hd 720 p), (' 74', 'hd 720 p60), (' 80', 'hd 1080 p), (' 112', 'hd 1080 p +), (' 116', 'hd 1080 p60)], [3] # user basic information of video video_info = {' AIDS' : [], 'cid_parts': [], 'titles': [], 'links': [], 'down_flags': []} params = {'mid': userid, 'pagesize': 30, 'tid': 0, 'page': 1, 'order': 'pubdate'} while True: res = self.session.get(self.submit_videos_url, headers=self.headers, params=params) res_json = res.json() for item in res_json['data']['vlist']: video_info['aids'].append(item['aid']) if len(video_info['aids']) < int(res_json['data']['count']): params['page'] += 1 else: break for aid in video_info['aids']: params = {'aid': aid} res = self.session.get(self.view_url, headers=self.headers, params=params) cid_part = [] for page in res.json()['data']['pages']: cid_part.append([page['cid'], page['part']]) video_info['cid_parts'].append(cid_part) title = res.json()['data']['title'] title = [' re. Sub (r "\ / \ \ \ \ \ *? \" \ "/ > \ | \ s']", "the title) video_info [' titles']. Append (title) : print (' access to the user ID of the < % s > < % d > a video... ' % (userid, len(video_info['titles']))) for idx in range(len(video_info['titles'])): aid = video_info['aids'][idx] cid_part = video_info['cid_parts'][idx] link = [] down_flag = False for cid, part in cid_part: params = {'avid': aid, 'cid': cid, 'qn': quality, 'otype': 'json', 'fnver': 0, 'fnval': 16} res = self.session.get(self.video_player_url, params=params, headers=self.headers) res_json = res.json() if 'dash' in res_json['data']: down_flag = True v, a = res_json['data']['dash']['video'][0], res_json['data']['dash']['audio'][0] link_v = [v['baseUrl']] link_a = [a['baseUrl']] if v['backup_url']: for item in v['backup_url']: link_v.append(item) if a['backup_url']: for item in a['backup_url']: link_a.append(item) link = [link_v, link_a] else: link = [res_json['data']['durl'][-1]['url']] if res_json['data']['durl'][-1]['backup_url']: for item in res_json['data']['durl'][-1]['backup_url']: Link.append (item) video_info['links'].append(link) video_info['down_flags'].append(down_flag) # Download out_pipe_QUIET = subprocess.PIPE out_pipe = None aria2c_path = os.path.join(os.getcwd(), 'tools/aria2c') ffmpeg_path = os.path.join(os.getcwd(), 'tools/ffmpeg') for idx in range(len(video_info['titles'])): title = video_info['titles'][idx] aid = video_info['aids'][idx] down_flag = video_info['down_flags'][idx] Print (' downloading video <%s>... ' % title) if down_flag: link_v, Link_a = video_info [' links'] [independence idx] # - video url = '" {} "'. The format (' "" '. Join (link_v) command = '{} {} - c - m - 1 k x - d" {} "- o  "{}" --referer="https://www.bilibili.com/video/av{}" {} {}' command = command.format(aria2c_path, len(link_v), userid, title+'.flv', aid, "", url) process = subprocess.Popen(command, stdout=out_pipe, stderr=out_pipe, Shell = True) process. The wait () # - audio url = '" {} "'. The format (' "" '. Join (link_a) command = '{} {} - c - m - 1 k x - d" {} "-o" {}" --referer="https://www.bilibili.com/video/av{}" {} {}' command = command.format(aria2c_path, len(link_v), userid, title+'.aac', aid, "", url) process = subprocess.Popen(command, stdout=out_pipe, stderr=out_pipe, Shell = True) process. The wait () # - merge command = '{} - I "{}" -i "{}" - c copy - f mp4 - "{}" y' command = command.format(ffmpeg_path, os.path.join(userid, title+'.flv'), os.path.join(userid, title+'.aac'), os.path.join(userid, title+'.mp4')) process = subprocess.Popen(command, stdout=out_pipe, stderr=out_pipe_quiet, shell=True) process.wait() os.remove(os.path.join(userid, title+'.flv')) os.remove(os.path.join(userid, title+'.aac')) else: link = video_info['links'][idx] url = '"{}"'.format('" "'.join(link)) command = '{} -c -k 1M -x {} -d "{}" -o "{}" --referer="https://www.bilibili.com/video/av{}" {} {}' command = command.format(aria2c_path, len(link), userid, title+'.flv', aid, "", url) process = subprocess.Popen(command, stdout=out_pipe, stderr=out_pipe, shell=True) process.wait() os.rename(os.path.join(userid, title+'.flv'), os.path.join(userid, Title +'.mp4')) print(' all videos downloaded, all videos saved in <%s> folder for this user... ' % (userid))Copy the code

After reading the article like friends point a like support, follow me every day to share Python simulation login series, the next article to share netease cloud personal playlist download device

All done~ complete source code see profile or private message to obtain related files.