コード例 #1
0
 def upload(self, file_list):
     video = Data()
     with BiliBili(video) as bili:
         bili.login(self.persistence_path)
         for file in file_list:
             video_part = bili.upload_file(file)  # 上传视频
             video.videos.append(video_part)  # 添加已经上传的视频
         video.title = self.data["format_title"]
         video.desc = '''这个自动录制上传的小程序开源在Github:http://t.cn/RgapTpf(或者在Github搜索ForgQi)
             交流群:837362626'''
         video.source = self.data["url"]  # 添加转载地址说明
         # 设置视频分区,默认为174 生活,其他分区
         tid = engine.config['streamers'][self.principal].get('tid')
         if tid:
             video.tid = tid
         tags = engine.config['streamers'][self.principal].get(
             'tags', ['星际争霸2', '电子竞技'])
         if tags:
             video.set_tag(tags)
         img_path = engine.config['streamers'][self.principal].get(
             'cover_path')
         if img_path:
             video.cover = bili.cover_up(img_path).replace('http:', '')
         ret = bili.submit()  # 提交视频
     logger.info(f"上传成功: {ret}")
     self.remove_filelist(file_list)
コード例 #2
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
コード例 #3
0
 def upload_file(self, filepath: str):
     """上传本地视频文件,返回视频信息dict
     b站目前支持4种上传线路upos, kodo, gcs, bos
     kodo: {"os":"kodo","query": "bucket=bvcupcdnkodobm&probe_version=20200810",
     "probe_url":"//up-na0.qbox.me/crossdomain.xml"}
     gcs: {"os":"gcs","query":"bucket=bvcupcdngcsus&probe_version=20200810",
     "probe_url":"//storage.googleapis.com/bvcupcdngcsus/OK"},
     bos: {"os":"bos","query":"bucket=bvcupcdnboshb&probe_version=20200810",
     "probe_url":"??"}
     upos:
     {"os":"upos","query":"upcdn=ws&probe_version=20200810","probe_url":"//upos-sz-upcdnws.bilivideo.com/OK"}
     {"os":"upos","query":"upcdn=qn&probe_version=20200810","probe_url":"//upos-sz-upcdnqn.bilivideo.com/OK"}
     {"os":"upos","query":"upcdn=bda2&probe_version=20200810","probe_url":"//upos-sz-upcdnbda2.bilivideo.com/OK"}
     """
     if not self._auto_os:
         self._auto_os = self.probe()
         # self._auto_os = {"os": "kodo", "query": "bucket=bvcupcdnkodobm&probe_version=20200810",
         #                  "probe_url": "//up-na0.qbox.me/crossdomain.xml"}
         logger.info(
             f"自动线路选择{self._auto_os['os']}: {self._auto_os['query']}. time: {self._auto_os.get('cost')}"
         )
     profile = 'ugcupos/bup' if 'upos' == self._auto_os[
         'os'] else "ugcupos/bupfetch"
     query = f"r={self._auto_os['os']}&profile={quote(profile, safe='')}" \
             f"&ssl=0&version=2.8.9&build=2080900&{self._auto_os['query']}"
     if self._auto_os['os'] == 'upos':
         return self.upos(filepath, query)
     elif self._auto_os['os'] == 'kodo':
         return self.kodo(filepath, query)
     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']}")
コード例 #4
0
    def add_videos(self, videopath):
        formate_title = self.data["format_title"]
        WebDriverWait(self.driver, 20).until(
            ec.presence_of_element_located((By.NAME, 'buploader')))
        upload = self.driver.find_element_by_name('buploader')
        # logger.info(driver.title)
        upload.send_keys(videopath)  # send_keys
        logger.info('开始上传' + formate_title)
        time.sleep(2)
        button = r'//*[@class="new-feature-guide-v2-container"]/div/div/div/div/div[1]'
        if self.is_element_exist(self.driver, button):
            sb = self.driver.find_element_by_xpath(button)
            sb.click()
            sb.click()
            sb.click()
            logger.debug('点击')
        while True:
            try:
                info = self.driver.find_elements_by_class_name(r'item-upload-info')
                for t in info:
                    if t.text != '':
                        print(t.text)
                time.sleep(10)
                text = self.driver.find_elements_by_xpath(r'//*[@class="item-upload-info"]/span')
                aggregate = set()
                for s in text:
                    if s.text != '':
                        aggregate.add(s.text)
                        print(s.text)

                if len(aggregate) == 1 and ('Upload complete' in aggregate or '上传完成' in aggregate):
                    break
            except selenium.common.exceptions.StaleElementReferenceException:
                logger.exception("selenium.common.exceptions.StaleElementReferenceException")
        logger.info('上传%s个数%s' % (formate_title, len(info)))
コード例 #5
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": ""
        }
コード例 #6
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 = '''这个自动录制上传的小程序开源在Github:http://t.cn/RgapTpf(或者在Github搜索ForgQi)
             交流群:837362626'''
         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()  # 提交视频
     logger.info(f"上传成功: {ret}")
     self.remove_filelist(file_list)
コード例 #7
0
    def upload(self, file_list):

        filename = self.persistence_path
        videopath = self.assemble_videopath(file_list)

        # service_log_path = "{}/chromedriver.log".format('/home')
        options = webdriver.ChromeOptions()

        options.add_argument('headless')
        self.driver = webdriver.Chrome(executable_path=engine.config.get('chromedriver_path'), chrome_options=options)
        # service_log_path=service_log_path)
        try:
            self.driver.get("https://www.bilibili.com")
            # driver.delete_all_cookies()
            if os.path.isfile(filename):
                with open(filename) as f:
                    new_cookie = json.load(f)

                for cookie in new_cookie:
                    if isinstance(cookie.get("expiry"), float):
                        cookie["expiry"] = int(cookie["expiry"])
                    self.driver.add_cookie(cookie)

            self.driver.get("https://member.bilibili.com/video/upload.html")

            # print(driver.title)
            self.add_videos(videopath)

            # js = "var q=document.getElementsByClassName('content-header-right')[0].scrollIntoView();"
            # driver.execute_script(js)

            cookie = self.driver.get_cookies()
            with open(filename, "w") as f:
                json.dump(cookie, f)

            self.add_information()

            self.driver.find_element_by_xpath('//*[@class="upload-v2-container"]/div[2]/div[3]/div[5]/span[1]').click()
            # screen_shot = driver.save_screenshot('bin/1.png')
            # print('截图')
            time.sleep(3)
            upload_success = self.driver.find_element_by_xpath(r'//*[@id="app"]/div/div[3]/h3').text
            if upload_success == '':
                self.driver.save_screenshot('err.png')
                logger.info('稿件提交失败,截图记录')
                return
            else:
                logger.info(upload_success)
            # logger.info('%s提交完成!' % title_)
            self.remove_filelist(file_list)
        except selenium.common.exceptions.NoSuchElementException:
            logger.exception('发生错误')
        # except selenium.common.exceptions.TimeoutException:
        #     logger.exception('超时')
        except selenium.common.exceptions.TimeoutException:
            self.login(filename)

        finally:
            self.driver.quit()
            logger.info('浏览器驱动退出')
コード例 #8
0
 def login(self, filename):
     logger.info('准备更新cookie')
     # screen_shot = driver.save_screenshot('bin/1.png')
     WebDriverWait(self.driver, 10).until(
         ec.presence_of_element_located((By.XPATH, r'//*[@id="login-username"]')))
     username = self.driver.find_element_by_xpath(r'//*[@id="login-username"]')
     username.send_keys(engine.config['user']['account']['username'])
     password = self.driver.find_element_by_xpath('//*[@id="login-passwd"]')
     password.send_keys(engine.config['user']['account']['password'])
     self.driver.find_element_by_class_name("btn-login").click()
     # logger.info('第四步')
     # try:
     cracker = slider_cracker(self.driver)
     cracker.crack()
     # except:
     #     logger.exception('出错')
     time.sleep(5)
     if self.driver.title == '投稿 - 哔哩哔哩弹幕视频网 - ( ゜- ゜)つロ 乾杯~ - bilibili':
         cookie = self.driver.get_cookies()
         print(cookie)
         with open(filename, "w") as f:
             json.dump(cookie, f)
         logger.info('更新cookie成功')
     else:
         logger.info('更新cookie失败')
コード例 #9
0
    def submit(self):
        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)
        myinfo = self.__session.get(
            'https://member.bilibili.com/x/web/archive/pre?lang=cn',
            timeout=15).json()['data']['myinfo']
        myinfo['total_info'] = self.__session.get(
            'https://member.bilibili.com/x/web/index/stat',
            timeout=15).json()['data']
        user_weight = 2 if myinfo['level'] > 3 \
            and myinfo['total_info'] and myinfo['total_info']['total_fans'] > 100 else 1
        if user_weight == 2:
            logger.info(f'用户权重: {user_weight} => 网页端分p数量不受限制使用网页端api提交')
            ret = self.__session.post(
                f'https://member.bilibili.com/x/vu/web/add?csrf={self.__bili_jct}',
                timeout=5,
                json=asdict(self.video)).json()
            if ret["code"] == 0:
                return ret
            elif ret["code"] == 21138:
                logger.info(f'改用客户端接口提交{ret}')
            else:
                raise Exception(ret)

        logger.info(f'用户权重: {user_weight} => 网页端分p数量受到限制使用客户端api端提交')
        if not self.access_token:
            self.login_by_password(**engine.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(**engine.config['user']['account'])
                self.store()
                continue
            break

        if ret["code"] == 0:
            return ret
        else:
            raise Exception(ret)
コード例 #10
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=5,
                                        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": ""
        }
コード例 #11
0
 def upload_file(self, filepath: str, lines='AUTO', tasks=3):
     """上传本地视频文件,返回视频信息dict
     b站目前支持4种上传线路upos, kodo, gcs, bos
     gcs: {"os":"gcs","query":"bucket=bvcupcdngcsus&probe_version=20200810",
     "probe_url":"//storage.googleapis.com/bvcupcdngcsus/OK"},
     bos: {"os":"bos","query":"bucket=bvcupcdnboshb&probe_version=20200810",
     "probe_url":"??"}
     """
     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 = {
             '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,
             'name': f.name,
             'size': total_size,
         }
         ret = self.__session.get(
             f"https://member.bilibili.com/preupload?{self._auto_os['query']}",
             params=query,
             timeout=5)
         return asyncio.run(upload(f, total_size, ret.json(), tasks=tasks))
コード例 #12
0
    def upos(self, filepath, query):
        total = os.path.getsize(filepath)
        with open(filepath, 'rb') as f:
            name = f.name
            ret = self.__session.get(
                f'https://member.bilibili.com/preupload?name={quote(name)}&size={total}&{query}',
                timeout=5).json()
            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://', '')}"  # 视频上传路径

            # 向上传地址申请上传,得到上传id等信息
            upload_id = self.__session.post(f'{url}?uploads&output=json',
                                            timeout=5,
                                            headers={
                                                "X-Upos-Auth": auth
                                            }).json()["upload_id"]
            # 开始上传
            parts = []  # 分块信息
            chunks = math.ceil(total / chunk_size)  # 获取分块数量
            start = time.perf_counter()
            for i in range(chunks):
                chunks_data = f.read(chunk_size)  # 一次读取一个分块大小
                uploaded = i * chunk_size + len(chunks_data)
                self.__session.put(
                    f'{url}?partNumber={i + 1}&uploadId={upload_id}&chunk={i}&chunks={chunks}'
                    f'&size={len(chunks_data)}&start={i * chunk_size}'
                    f'&end={uploaded}&total={total}',
                    timeout=30,
                    data=chunks_data,
                    headers={"X-Upos-Auth": auth})

                parts.append({
                    "partNumber": i + 1,
                    "eTag": "etag"
                })  # 添加分块信息,partNumber从1开始
                # 输出上传进度
                cost = time.perf_counter() - start
                percent = (i + 1) / chunks
                sys.stdout.write(
                    f"\r{uploaded / 1000 / 1000 / cost:.2f}MB/s => {percent:.1%}"
                )
        logger.info(f'{name} uploaded >> {total / 1000 / 1000 / cost:.2f}MB/s')
        r = self.__session.post(
            f'{url}?output=json&name={quote(name)}&profile=ugcupos%2Fbup&uploadId={upload_id}&biz_id={biz_id}',
            json={
                "parts": parts
            },
            headers={
                "X-Upos-Auth": auth
            },
            timeout=15).json()
        if r["OK"] != 1:
            raise Exception(r)
        return {
            "title": splitext(name)[0],
            "filename": splitext(basename(upos_uri))[0],
            "desc": ""
        }