Example #1
0
def login_by_access_token(access_token):
    """
    bilibili access token login.
    Args:
        access_token: Bilibili access token got by previous username/password login.

    Returns:
        sid: session id.
        mid: member id.
        expires_in: access token expire time
    """
    headers = {
        'Connection': 'keep-alive',
        'Accept-Encoding': 'gzip,deflate',
        'Host': 'passport.bilibili.com',
        'User-Agent': '',
    }

    login_params = {
        'appkey': APPKEY,
        'access_token': access_token,
        'platform': "pc",
        'ts': str(int(datetime.now().timestamp())),
    }
    login_params['sign'] = cipher.sign_dict(login_params, APPSECRET)

    r = requests.get(url="https://passport.bilibili.com/api/oauth2/info",
                     headers=headers,
                     params=login_params)

    login_data = r.json()['data']

    return r.cookies['sid'], login_data['mid'], login_data["expires_in"]
Example #2
0
def get_key(sid=None, jsessionid=None):
    """
    get public key, hash and session id for login.
    Args:
        sid: session id. only for captcha login.
        jsessionid: j-session id. only for captcha login.
    Returns:
        hash: salt for password encryption.
        pubkey: rsa public key for password encryption.
        sid: session id.
    """
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Accept': "application/json, text/javascript, */*; q=0.01"
    }
    post_data = {
        'appkey': APPKEY,
        'platform': "pc",
        'ts': str(int(datetime.now().timestamp()))
    }
    post_data['sign'] = cipher.sign_dict(post_data, APPSECRET)
    cookie = {}
    if sid:
        cookie['sid'] = sid
    if jsessionid:
        cookie['JSESSIONID'] = jsessionid
    r = requests.post("https://passport.bilibili.com/api/oauth2/getKey",
                      headers=headers,
                      data=post_data,
                      cookies=cookie)
    r_data = r.json()['data']
    if sid:
        return r_data['hash'], r_data['key'], sid
    return r_data['hash'], r_data['key'], r.cookies['sid']
Example #3
0
def upload_cover(access_token, sid, cover_file_path):
    with open(cover_file_path, "rb") as f:
        cover_pic = f.read()

    headers = {
        'Connection': 'keep-alive',
        'Host': 'member.bilibili.com',
        'Accept-Encoding': 'gzip,deflate',
        'User-Agent': '',
    }

    params = {
        "access_key": access_token,
    }

    params["sign"] = cipher.sign_dict(params, APPSECRET)

    files = {
        'file': ("cover.png", cover_pic, "Content-Type: image/png"),
    }

    r = requests.post(
        "http://member.bilibili.com/x/vu/client/cover/up",
        headers=headers,
        params=params,
        files=files,
        cookies={'sid': sid},
        verify=False,
    )

    return r.json()["data"]["url"]
Example #4
0
def get_capcha(sid, file_name=None):
    headers = {
        'User-Agent': '',
        'Accept-Encoding': 'gzip,deflate',
    }

    params = {
        'appkey': APPKEY,
        'platform': 'pc',
        'ts': str(int(datetime.now().timestamp()))
    }
    params['sign'] = cipher.sign_dict(params, APPSECRET)

    r = requests.get("https://passport.bilibili.com/captcha",
                     headers=headers,
                     params=params,
                     cookies={'sid': sid})

    print(r.status_code)

    capcha_data = r.content

    if file_name is not None:
        with open(file_name, 'wb+') as f:
            f.write(capcha_data)

    return r.cookies['JSESSIONID'], capcha_data
Example #5
0
def get_type_info(access_key):
    tag_get_data = {"access_key": access_key, "build": "1054"}

    tag_get_data["sign"] = cipher.sign_dict(tag_get_data, APPSECRET)

    r = requests.get(url=TYPE_INFO_ADDR, params=tag_get_data)

    data = r.json()["data"]

    typelist = data["typelist"]
    print(typelist)

    result = []

    for video_type_1 in typelist:
        vt1_str = "## {}: {}\n\n".format(video_type_1["id"],
                                         video_type_1["name"])
        if "children" in video_type_1:
            children = video_type_1["children"]
            children_list = []
            for video_type_2 in children:
                vt2_str = "{}: {}\n\n".format(video_type_2["id"],
                                              video_type_2["name"])
                children_list.append((video_type_2["id"], vt2_str))
            children_list.sort(key=lambda x: x[0])
            for i, s in children_list:
                vt1_str += s
        result.append((video_type_1["id"], vt1_str))
    result.sort(key=lambda x: x[0])

    for i, s in result:
        print(s)
Example #6
0
def get_post_data(access_token, sid, avid):
    headers = {
        'Connection': 'keep-alive',
        'Host': 'member.bilibili.com',
        'Accept-Encoding': 'gzip,deflate',
        'User-Agent': '',
    }

    params = {
        "access_key": access_token,
        "aid": avid,
        "build": "1054"
    }

    params["sign"] = cipher.sign_dict(params, APPSECRET)

    r = requests.get(
        url="http://member.bilibili.com/x/client/archive/view",
        headers=headers,
        params=params,
        cookies={
            'sid': sid
        }
    )

    return r.json()["data"]
Example #7
0
def login(username, password):
    """
    bilibili login.
    Args:
        username: plain text username for bilibili.
        password: plain text password for bilibili.

    Returns:
        access_token: token for further operation.
        refresh_token: token for refresh access_token.
        sid: session id.
        mid: member id.
        expires_in: access token expire time (30 days)
    """
    hash, pubkey, sid = get_key()

    encrypted_password = cipher.encrypt_login_password(password, hash, pubkey)
    url_encoded_username = parse.quote_plus(username)
    url_encoded_password = parse.quote_plus(encrypted_password)

    post_data = {
        'appkey': APPKEY,
        'password': url_encoded_password,
        'platform': "pc",
        'ts': str(int(datetime.now().timestamp())),
        'username': url_encoded_username
    }

    post_data['sign'] = cipher.sign_dict(post_data, APPSECRET)
    # avoid multiple url parse
    post_data['username'] = username
    post_data['password'] = encrypted_password

    headers = {
        'Connection': 'keep-alive',
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        'User-Agent': '',
        'Accept-Encoding': 'gzip,deflate',
    }

    r = requests.post("https://passport.bilibili.com/api/oauth2/login",
                      headers=headers,
                      data=post_data,
                      cookies={'sid': sid})
    login_data = r.json()['data']
    return login_data['access_token'], login_data[
        'refresh_token'], sid, login_data['mid'], login_data["expires_in"]
Example #8
0
def edit_videos(access_token,
                sid,
                mid,
                avid=None,
                bvid=None,
                parts=None,
                insert_index=None,
                copyright=None,
                title=None,
                tid=None,
                tag=None,
                desc=None,
                source=None,
                cover=None,
                no_reprint=None,
                open_elec=None,
                max_retry: int = 5,
                thread_pool_workers: int = 1):
    """
    insert videos into existed post.

    Args:
        access_token: oauth2 access token.
        sid: session id.
        mid: member id.
        avid: av number,
        bvid: bv string,
        parts: VideoPart list.
        insert_index: new video index.
        copyright: 原创/转载.
        title: 投稿标题.
        tid: 分区id.
        tag: 标签.
        desc: 投稿简介.
        source: 转载地址.
        cover: cover url.
        no_reprint: 可否转载.
        open_elec: 充电.
        max_retry: max retry time for each chunk.
        thread_pool_workers: max upload threads.

    Returns:
        (aid, bvid)
        aid: av号
        bvid: bv号
    """
    if not avid and not bvid:
        print("please provide avid or bvid")
        return None, None
    if not avid:
        avid = cipher.bv2av(bvid)
    if not isinstance(parts, list):
        parts = [parts]
    if type(avid) is str:
        avid = int(avid)

    post_video_data = get_post_data(access_token, sid, avid)

    status = True
    with ThreadPoolExecutor(max_workers=thread_pool_workers) as tpe:
        t_list = []
        for video_part in parts:
            print("upload {} added in pool".format(video_part.title))
            t_obj = tpe.submit(upload_video_part, access_token, sid, mid,
                               video_part, max_retry)
            t_obj.video_part = video_part
            t_list.append(t_obj)

        for t_obj in as_completed(t_list):
            status = status and t_obj.result()
            print("video part {} finished, status: {}".format(
                t_obj.video_part.title, t_obj.result()))
            if not status:
                print("upload failed")
                return None, None

    headers = {
        'Connection': 'keep-alive',
        'Content-Type': 'application/json',
        'User-Agent': '',
    }
    submit_data = {
        'aid': avid,
        'build': 1054,
        'copyright': post_video_data["archive"]["copyright"],
        'cover': post_video_data["archive"]["cover"],
        'desc': post_video_data["archive"]["desc"],
        'no_reprint': post_video_data["archive"]["no_reprint"],
        'open_elec':
        post_video_data["archive_elec"]["state"],  # open_elec not tested
        'source': post_video_data["archive"]["source"],
        'tag': post_video_data["archive"]["tag"],
        'tid': post_video_data["archive"]["tid"],
        'title': post_video_data["archive"]["title"],
        'videos': post_video_data["videos"]
    }

    # edit archive data
    if copyright:
        submit_data["copyright"] = copyright
    if title:
        submit_data["title"] = title
    if tid:
        submit_data["tid"] = tid
    if tag:
        submit_data["tag"] = tag
    if desc:
        submit_data["desc"] = desc
    if source:
        submit_data["source"] = source
    if cover:
        submit_data["cover"] = cover
    if no_reprint:
        submit_data["no_reprint"] = no_reprint
    if open_elec:
        submit_data["open_elec"] = open_elec

    if type(insert_index) is int:
        for i, video_part in enumerate(parts):
            submit_data['videos'].insert(
                insert_index + i, {
                    "desc": video_part.desc,
                    "filename": video_part.server_file_name,
                    "title": video_part.title
                })
    elif insert_index is None:
        for video_part in parts:
            submit_data['videos'].append({
                "desc": video_part.desc,
                "filename": video_part.server_file_name,
                "title": video_part.title
            })
    else:
        print("wrong insert index")
        return None, None

    params = {
        'access_key': access_token,
    }
    params['sign'] = cipher.sign_dict(params, APPSECRET)
    r = requests.post(
        url="http://member.bilibili.com/x/vu/client/edit",
        params=params,
        headers=headers,
        verify=False,
        cookies={'sid': sid},
        json=submit_data,
    )

    print("edit submit")
    print(r.status_code)
    print(r.content.decode())

    data = r.json()["data"]
    return data["aid"], data["bvid"]
Example #9
0
def upload(access_token,
           sid,
           mid,
           parts,
           copyright: int,
           title: str,
           tid: int,
           tag: str,
           desc: str,
           source: str = '',
           cover: str = '',
           no_reprint: int = 0,
           open_elec: int = 1,
           max_retry: int = 5,
           thread_pool_workers: int = 1):
    """
    upload video.

    Args:
        access_token: oauth2 access token.
        sid: session id.
        mid: member id.
        parts: VideoPart list.
        copyright: 原创/转载.
        title: 投稿标题.
        tid: 分区id.
        tag: 标签.
        desc: 投稿简介.
        source: 转载地址.
        cover: 封面图片文件路径.
        no_reprint: 可否转载.
        open_elec: 充电.
        max_retry: max retry time for each chunk.
        thread_pool_workers: max upload threads.

    Returns:
        (aid, bvid)
        aid: av号
        bvid: bv号
    """
    if not isinstance(parts, list):
        parts = [parts]

    status = True
    with ThreadPoolExecutor(max_workers=thread_pool_workers) as tpe:
        t_list = []
        for video_part in parts:
            print("upload {} added in pool".format(video_part.title))
            t_obj = tpe.submit(upload_video_part, access_token, sid, mid,
                               video_part, max_retry)
            t_obj.video_part = video_part
            t_list.append(t_obj)

        for t_obj in as_completed(t_list):
            status = status and t_obj.result()
            print("video part {} finished, status: {}".format(
                t_obj.video_part.title, t_obj.result()))
            if not status:
                print("upload failed")
                return None, None

    # cover
    if os.path.isfile(cover):
        try:
            cover = upload_cover(access_token, sid, cover)
        except:
            cover = ''
    else:
        cover = ''

    # submit
    headers = {
        'Connection': 'keep-alive',
        'Content-Type': 'application/json',
        'User-Agent': '',
    }
    post_data = {
        'build': 1054,
        'copyright': copyright,
        'cover': cover,
        'desc': desc,
        'no_reprint': no_reprint,
        'open_elec': open_elec,
        'source': source,
        'tag': tag,
        'tid': tid,
        'title': title,
        'videos': []
    }
    for video_part in parts:
        post_data['videos'].append({
            "desc": video_part.desc,
            "filename": video_part.server_file_name,
            "title": video_part.title
        })

    params = {
        'access_key': access_token,
    }
    params['sign'] = cipher.sign_dict(params, APPSECRET)
    r = requests.post(
        url="http://member.bilibili.com/x/vu/client/add",
        params=params,
        headers=headers,
        verify=False,
        cookies={'sid': sid},
        json=post_data,
    )

    print("submit")
    print(r.status_code)
    print(r.content.decode())

    data = r.json()["data"]
    return data["aid"], data["bvid"]
Example #10
0
def login_captcha(username, password, sid):
    """
    bilibili login with captcha.
    depend on captcha recognize service, please do not use this as first choice.
    Args:
        username: plain text username for bilibili.
        password: plain text password for bilibili.
        sid: session id
    Returns:
        code: login response code (0: success, -105: captcha error, ...).
        access_token: token for further operation.
        refresh_token: token for refresh access_token.
        sid: session id.
        mid: member id.
        expires_in: access token expire time (30 days)
    """

    jsessionid, captcha_img = get_capcha(sid)
    captcha_str = recognize_captcha(captcha_img)

    hash, pubkey, sid = get_key(sid, jsessionid)

    encrypted_password = cipher.encrypt_login_password(password, hash, pubkey)
    url_encoded_username = parse.quote_plus(username)
    url_encoded_password = parse.quote_plus(encrypted_password)

    post_data = {
        'appkey': APPKEY,
        'captcha': captcha_str,
        'password': url_encoded_password,
        'platform': "pc",
        'ts': str(int(datetime.now().timestamp())),
        'username': url_encoded_username
    }

    post_data['sign'] = cipher.sign_dict(post_data, APPSECRET)
    # avoid multiple url parse
    post_data['username'] = username
    post_data['password'] = encrypted_password
    post_data['captcha'] = captcha_str

    headers = {
        'Connection': 'keep-alive',
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        'User-Agent': '',
        'Accept-Encoding': 'gzip,deflate',
    }

    r = requests.post("https://passport.bilibili.com/api/oauth2/login",
                      headers=headers,
                      data=post_data,
                      cookies={
                          'JSESSIONID': jsessionid,
                          'sid': sid
                      })
    response = r.json()
    if response['code'] == 0:
        login_data = response['data']
        return response['code'], login_data['access_token'], login_data[
            'refresh_token'], sid, login_data['mid'], login_data["expires_in"]
    else:
        return response['code'], None, None, sid, None, None