예제 #1
0
 def probe(self):
     ret = self.__session.get(
         'https://member.bilibili.com/preupload?r=probe', timeout=5).json()
     logger.info(f"线路:{ret['lines']}")
     data, auto_os = None, None
     min_cost = 0
     if ret['probe'].get('get'):
         method = 'get'
     else:
         method = 'post'
         data = bytes(int(1024 * 0.1 * 1024))
     for line in ret['lines']:
         start = time.perf_counter()
         test = self.__session.request(method,
                                       f"https:{line['probe_url']}",
                                       data=data,
                                       timeout=30)
         cost = time.perf_counter() - start
         print(line['query'], cost)
         if test.status_code != 200:
             return
         if not min_cost or min_cost > cost:
             auto_os = line
             min_cost = cost
     auto_os['cost'] = min_cost
     return auto_os
예제 #2
0
    async def kodo(self, file, total_size, ret, chunk_size=4194304, tasks=3):
        filename = file.name
        bili_filename = ret['bili_filename']
        key = ret['key']
        endpoint = f"https:{ret['endpoint']}"
        token = ret['uptoken']
        fetch_url = ret['fetch_url']
        fetch_headers = ret['fetch_headers']
        url = f'{endpoint}/mkblk'
        headers = {
            'Authorization': f"UpToken {token}",
        }
        # 开始上传
        parts = []  # 分块信息
        chunks = math.ceil(total_size / chunk_size)  # 获取分块数量

        async def upload_chunk(session, chunks_data, params):
            async with session.post(f'{url}/{len(chunks_data)}',
                                    data=chunks_data,
                                    headers=headers) as response:
                end = time.perf_counter() - start
                ctx = await response.json()
                parts.append({"index": params['chunk'], "ctx": ctx['ctx']})
                sys.stdout.write(
                    f"\r{params['end'] / 1000 / 1000 / end:.2f}MB/s "
                    f"=> {params['partNumber'] / chunks:.1%}")

        start = time.perf_counter()
        await self._upload({}, file, chunk_size, upload_chunk, tasks=tasks)
        cost = time.perf_counter() - start

        logger.info(
            f'{filename} uploaded >> {total_size / 1000 / 1000 / cost:.2f}MB/s'
        )
        parts.sort(key=lambda x: x['index'])
        self.__session.post(
            f"{endpoint}/mkfile/{total_size}/key/{base64.urlsafe_b64encode(key.encode()).decode()}",
            data=','.join(map(lambda x: x['ctx'], parts)),
            headers=headers,
            timeout=10)
        r = self.__session.post(f"https:{fetch_url}",
                                headers=fetch_headers,
                                timeout=5).json()
        if r["OK"] != 1:
            raise Exception(r)
        return {
            "title": splitext(filename)[0],
            "filename": bili_filename,
            "desc": ""
        }
예제 #3
0
 def submit_client(self):
     logger.info('使用客户端api端提交')
     if not self.access_token:
         self.login_by_password(**config['user']['account'])
         self.store()
     while True:
         ret = self.__session.post(
             f'http://member.bilibili.com/x/vu/client/add?access_key={self.access_token}',
             timeout=5,
             json=asdict(self.video)).json()
         if ret['code'] == -101:
             logger.info(f'刷新token{ret}')
             self.login_by_password(**config['user']['account'])
             self.store()
             continue
         return ret
예제 #4
0
 def upload(self, file_list):
     video = Data()
     with BiliBili(video) as bili:
         bili.login(self.persistence_path, self.user)
         for file in file_list:
             video_part = bili.upload_file(file, self.lines,
                                           self.threads)  # 上传视频
             video.videos.append(video_part)  # 添加已经上传的视频
         video.title = self.data["format_title"]
         video.desc = self.desc + ',喜欢点赞!'
         video.copyright = self.copyright
         if self.copyright == 2:
             video.source = self.data["url"]  # 添加转载地址说明
         # 设置视频分区,默认为174 生活,其他分区
         video.tid = self.tid
         video.set_tag(self.tags)
         if self.cover_path:
             video.cover = bili.cover_up(self.cover_path).replace(
                 'http:', '')
         ret = bili.submit(self.submit_api)  # 提交视频
     logger.info(f"上传成功: {ret}")
     return file_list
예제 #5
0
    def submit(self, submit_api=None):
        if not self.video.title:
            self.video.title = self.video.videos[0]["title"]
        self.__session.get('https://member.bilibili.com/x/geetest/pre/add',
                           timeout=5)

        if submit_api is None:
            myinfo = self.__session.get(
                'https://member.bilibili.com/x/web/archive/pre?lang=cn',
                timeout=15).json()['data']['myinfo']
            total_info = self.__session.get(
                'https://member.bilibili.com/x/web/index/stat',
                timeout=15).json()
            if total_info.get('data') is None:
                logger.error(total_info)
            myinfo['total_info'] = total_info.get('data')
            if myinfo['level'] > 3 and myinfo[
                    'total_info'] and myinfo['total_info']['total_fans'] > 100:
                user_weight = 2
            else:
                user_weight = 1
            logger.info(f'用户权重: {user_weight}')
            submit_api = 'web' if user_weight == 2 else 'client'
        ret = None
        if submit_api == 'web':
            ret = self.submit_web()
            if ret["code"] == 21138:
                logger.info(f'改用客户端接口提交{ret}')
                submit_api = 'client'
        if submit_api == 'client':
            ret = self.submit_client()
        if not ret:
            raise Exception(f'不存在的选项:{submit_api}')
        if ret["code"] == 0:
            return ret
        else:
            raise Exception(ret)
예제 #6
0
 def submit_web(self):
     logger.info('使用网页端api提交')
     return self.__session.post(
         f'https://member.bilibili.com/x/vu/web/add?csrf={self.csrf}',
         timeout=5,
         json=asdict(self.video)).json()
예제 #7
0
    async def upos(self, file, total_size, ret, tasks=3):
        filename = file.name
        chunk_size = ret['chunk_size']
        auth = ret["auth"]
        endpoint = ret["endpoint"]
        biz_id = ret["biz_id"]
        upos_uri = ret["upos_uri"]
        url = f"https:{endpoint}/{upos_uri.replace('upos://', '')}"  # 视频上传路径
        headers = {"X-Upos-Auth": auth}
        # 向上传地址申请上传,得到上传id等信息
        upload_id = self.__session.post(f'{url}?uploads&output=json',
                                        timeout=30,
                                        headers=headers).json()["upload_id"]
        # 开始上传
        parts = []  # 分块信息
        chunks = math.ceil(total_size / chunk_size)  # 获取分块数量

        async def upload_chunk(session, chunks_data, params):
            async with session.put(url,
                                   params=params,
                                   raise_for_status=True,
                                   data=chunks_data,
                                   headers=headers):
                end = time.perf_counter() - start
                parts.append({
                    "partNumber": params['chunk'] + 1,
                    "eTag": "etag"
                })
                sys.stdout.write(
                    f"\r{params['end'] / 1000 / 1000 / end:.2f}MB/s "
                    f"=> {params['partNumber'] / chunks:.1%}")

        start = time.perf_counter()
        await self._upload(
            {
                'uploadId': upload_id,
                'chunks': chunks,
                'total': total_size
            },
            file,
            chunk_size,
            upload_chunk,
            tasks=tasks)
        cost = time.perf_counter() - start
        p = {
            'name': filename,
            'uploadId': upload_id,
            'biz_id': biz_id,
            'output': 'json',
            'profile': 'ugcupos/bup'
        }
        r = self.__session.post(url,
                                params=p,
                                json={
                                    "parts": parts
                                },
                                headers=headers,
                                timeout=15).json()
        logger.info(
            f'{filename} uploaded >> {total_size / 1000 / 1000 / cost:.2f}MB/s. {r}'
        )
        if r.get('OK') != 1:
            raise Exception(r)
        return {
            "title": splitext(filename)[0],
            "filename": splitext(basename(upos_uri))[0],
            "desc": ""
        }
예제 #8
0
 def upload_file(self, filepath: str, lines='AUTO', tasks=3):
     if not self._auto_os:
         self._auto_os = self.probe()
         if lines == 'kodo':
             self._auto_os = {
                 "os": "kodo",
                 "query": "bucket=bvcupcdnkodobm&probe_version=20200810",
                 "probe_url": "//up-na0.qbox.me/crossdomain.xml"
             }
         if lines == 'bda2':
             self._auto_os = {
                 "os": "upos",
                 "query": "upcdn=bda2&probe_version=20200810",
                 "probe_url": "//upos-sz-upcdnbda2.bilivideo.com/OK"
             }
         if lines == 'ws':
             self._auto_os = {
                 "os": "upos",
                 "query": "upcdn=ws&probe_version=20200810",
                 "probe_url": "//upos-sz-upcdnws.bilivideo.com/OK"
             }
         if lines == 'qn':
             self._auto_os = {
                 "os": "upos",
                 "query": "upcdn=qn&probe_version=20200810",
                 "probe_url": "//upos-sz-upcdnqn.bilivideo.com/OK"
             }
         logger.info(
             f"线路选择 => {self._auto_os['os']}: {self._auto_os['query']}. time: {self._auto_os.get('cost')}"
         )
     if self._auto_os['os'] == 'upos':
         upload = self.upos
     elif self._auto_os['os'] == 'kodo':
         upload = self.kodo
     elif self._auto_os['os'] == "gcs":
         raise NotImplementedError('gcs')
     elif self._auto_os['os'] == "bos":
         raise NotImplementedError('bos')
     else:
         logger.error(f"NoSearch:{self._auto_os['os']}")
         raise NotImplementedError(self._auto_os['os'])
     total_size = os.path.getsize(filepath)
     with open(filepath, 'rb') as f:
         query = {
             'name': f.name,
             'size': int(total_size),
             'r': self._auto_os['os'],
             'profile': 'ugcupos/bup'
             if 'upos' == self._auto_os['os'] else "ugcupos/bupfetch",
             'ssl': 0,
             'version': '2.8.12',
             'build': 2081200,
         }
         self.__session.headers.update({
             'authority':
             'member.bilibili.com',
             'sec-ch-ua':
             '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
             'sec-ch-ua-mobile':
             '?0',
             'user-agent':
             'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
             'accept':
             '*/*',
             'sec-fetch-site':
             'same-origin',
             'sec-fetch-mode':
             'cors',
             'sec-fetch-dest':
             'empty',
             'referer':
             'https://member.bilibili.com/video/upload.html',
             'accept-language':
             'zh-CN,zh;q=0.9',
             'cookie':
             f'buvid3={self.buvid3}; SESSDATA={self.sessdata}; bili_jct={self.csrf}'
         })
         res = self.__session.get(
             f"https://member.bilibili.com/preupload?{self._auto_os['query']}",
             params=query,
             timeout=5)
         if res.status_code != 200:
             raise Exception(res)
         else:
             print(res)
         return asyncio.run(upload(f, total_size, res.json(), tasks=tasks))