def get_token(cookie): '''获取一个页面访问的token, 这里需要之前得到的BAIDUID 这个cookie值 这个token的有效期还不确定. 返回的数据如下: {"errInfo":{"no": "0"}, "data": { "rememberedUserName" : "", "codeString" : "", "token" : "xxxxx", "cookie" : "1", "usernametype":"2", "spLogin" : "rate", "disable":"", "loginrecord":{ 'email':[ ], 'phone':[]} }} ''' url = ''.join([ const.PASSPORT_URL, '?getapi&tpl=pp&apiver=v3', '&tt=', util.timestamp(), '&class=login&logintype=basicLogin', ]) headers={ 'Cookie': cookie.header_output(), 'Accept': const.ACCEPT_HTML, 'Cache-control': 'max-age=0', } req = net.urlopen(url, headers=headers) if req: cookie = req.headers.get_all('Set-Cookie') content_obj = util.json_loads_single(req.data.decode()) if content_obj: return cookie, content_obj['data']['token'] return None
def rapid_upload(cookie, tokens, source_path, path, upload_mode): '''快速上传''' ondup = const.UPLOAD_ONDUP[upload_mode] if not ondup: ondup = 'newcopy' content_length = os.path.getsize(source_path) assert content_length > RAPIDUPLOAD_THRESHOLD, 'file size is not satisfied!' dir_name, file_name = os.path.split(path) content_md5 = hasher.md5(source_path) slice_md5 = hasher.md5(source_path, 0, RAPIDUPLOAD_THRESHOLD) url = ''.join([ const.PCS_URL_C, 'file?method=rapidupload&app_id=250528', '&ondup=newcopy', '&dir=', encoder.encode_uri_component(dir_name), '&filename=', encoder.encode_uri_component(file_name), '&content-length=', str(content_length), '&content-md5=', content_md5, '&slice-md5=', slice_md5, '&path=', encoder.encode_uri_component(path), '&', cookie.sub_output('BDUSS'), '&bdstoken=', tokens['bdstoken'], ]) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: return json.loads(req.data.decode()) else: return None
def enable_private_share(cookie, tokens, fid_list, passwd='smfx'): '''建立新的私密分享. 密码是在本地生成的, 然后上传到服务器. ''' url = ''.join([ const.PAN_URL, 'share/set?channel=chunlei&clienttype=0&web=1', '&bdstoken=', tokens['bdstoken'], '&channel=chunlei&clienttype=0&web=1', '&appid=250528', ]) data = encoder.encode_uri(''.join([ 'fid_list=', str(fid_list), '&schannel=4&channel_list=[]', '&pwd=', passwd, ])) req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), 'Content-type': const.CONTENT_FORM_UTF8, }, data=data.encode()) if req: content = req.data return json.loads(content.decode()), passwd else: return None, passwd
def enable_share(cookie, tokens, fid_list): '''建立新的分享. fid_list - 是一个list, 里面的每一条都是一个文件的fs_id 一次可以分享同一个目录下的多个文件/目录, 它们会会打包为一个分享链接, 这个分享链接还有一个对应的shareid. 我们可以用uk与shareid来在百度网盘里 面定位到这个分享内容. @return - 会返回分享链接和shareid. ''' url = ''.join([ const.PAN_URL, 'share/set?channel=chunlei&clienttype=0&web=1', '&bdstoken=', tokens['bdstoken'], ]) data = encoder.encode_uri( 'fid_list={0}&schannel=0&channel_list=[]'.format(fid_list)) req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), 'Content-type': const.CONTENT_FORM_UTF8, }, data=data.encode()) if req: content = req.data return json.loads(content.decode()) else: return None
def get_share_page(url): '''获取共享页面的文件信息''' req = net.urlopen(url) if req: content = req.data.decode() match = re.findall('applicationConfig,(.+)\]\);', content) share_files = {} if not match: match = re.findall('viewShareData=(.+");FileUtils.spublic', content) if not match: logger.error('get_share_page(): %s, %s' % (url, match)) return None list_ = json.loads(json.loads(match[0])) else: list_ = json.loads(json.loads(match[0])) if isinstance(list_, dict): share_files['list'] = [list_, ] else: share_files['list'] = list_ id_match = re.findall('FileUtils\.share_id="(\d+)"', content) uk_match = re.findall('/share/home\?uk=(\d+)" target=', content) sign_match = re.findall('FileUtils\.share_sign="([^"]+)"', content) if id_match and uk_match and sign_match: share_files['share_id'] = id_match[0] share_files['uk'] = uk_match[0] share_files['sign'] = sign_match[0] return share_files return None
def share_transfer(cookie, tokens, shareid, uk, filelist, dest, upload_mode): ''' 将其他用户的文件保存到自己网盘里. uk - 其他用户的uk filelist - 要转移文件的列表, 是绝对路径 ''' ondup = const.UPLOAD_ONDUP[upload_mode] url = ''.join([ const.PAN_URL, 'share/transfer?app_id=250528&channel=chunlei&clienttype=0&web=1', '&bdstoken=', tokens['bdstoken'], '&from=', uk, '&shareid=', shareid, '&ondup=', ondup, '&async=1', ]) data = ''.join([ 'path=', encoder.encode_uri_component(dest), '&filelist=', encoder.encode_uri_component(json.dumps(filelist)) ]) req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), 'Content-Type': const.CONTENT_FORM_UTF8 }, data=data.encode()) if req: content = req.data.decode() return json.loads(content) else: return None
def list_trash(cookie, tokens, path='/', page=1, num=100): '''获取回收站的信息. path - 目录的绝对路径, 默认是根目录 page - 页码, 默认是第一页 num - 每页有多少个文件, 默认是100个. 回收站里面的文件会被保存10天, 10天后会自动被清空. 回收站里面的文件不占用用户的存储空间. ''' url = ''.join([ const.PAN_API_URL, 'recycle/list?channel=chunlei&clienttype=0&web=1', '&num=', str(num), '&t=', util.timestamp(), '&dir=', encoder.encode_uri_component(path), '&t=', util.latency(), '&order=time&desc=1', '&_=', util.timestamp(), '&bdstoken=', tokens['bdstoken'], ]) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: content = req.data return json.loads(content.decode()) else: return None
def list_share_files(cookie, tokens, uk, shareid, dirname, page=1): '''列举出用户共享的某一个目录中的文件信息 这个对所有用户都有效 uk - user key shareid - 共享文件的ID值 dirname - 共享目录, 如果dirname为None, 说明这有可能是一个单独共享的文件, 这里, 需要调用list_share_single_file() ''' if not dirname: return list_share_single_file(cookie, tokens, uk, shareid) url = ''.join([ const.PAN_URL, 'share/list?channel=chunlei&clienttype=0&web=1&num=50', '&t=', util.timestamp(), '&page=', str(page), '&dir=', encoder.encode_uri_component(dirname), '&t=', util.latency(), '&shareid=', shareid, '&order=time&desc=1', '&uk=', uk, '&_=', util.timestamp(), '&bdstoken=', tokens['bdstoken'], ]) req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), 'Referer': const.SHARE_REFERER, }) if req: content = req.data info = json.loads(content.decode()) if info['errno'] == 0: return info['list'] return list_share_single_file(cookie, tokens, uk, shareid)
def list_share(cookie, tokens, uk, page=1): '''获取用户已经共享的所有文件的信息 uk - user key page - 页数, 默认为第一页. num - 一次性获取的共享文件的数量, 默认为100个. ''' num = 100 start = 100 * (page - 1) url = ''.join([ const.PAN_URL, 'pcloud/feed/getsharelist?', '&t=', util.timestamp(), '&categor=0&auth_type=1&request_location=share_home', '&start=', str(start), '&limit=', str(num), '&query_uk=', str(uk), '&channel=chunlei&clienttype=0&web=1', '&bdstoken=', tokens['bdstoken'], ]) req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), 'Referer': const.SHARE_REFERER, }) if req: content = req.data return json.loads(content.decode()) else: return None
def list_share_path(cookie, tokens, uk, path, share_id, page): '''列举出用户共享的某一个目录中的文件信息 uk - user key path - 共享目录 share_id - 共享文件的ID值 ''' url = ''.join([ const.PAN_URL, 'share/list?channel=chunlei&clienttype=0&web=1&num=100', '&t=', util.timestamp(), '&page=', str(page), '&dir=', encoder.encode_uri_component(path), '&t=', util.latency(), '&shareid=', share_id, '&order=time&desc=1', '&uk=', uk, '&_=', util.timestamp(), '&bdstoken=', tokens['bdstoken'], ]) req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), 'Referer': const.SHARE_REFERER, }) if req: content = req.data return json.loads(content.decode()) else: return None
def get_metas(cookie, tokens, filelist, dlink=True): '''获取多个文件的metadata. filelist - 一个list, 里面是每个文件的绝对路径. 也可以是一个字符串, 只包含一个文件的绝对路径. dlink - 是否包含下载链接, 默认为True, 包含. @return 包含了文件的下载链接dlink, 通过它可以得到最终的下载链接. ''' if isinstance(filelist, str): filelist = [filelist, ] url = ''.join([ const.PAN_API_URL, 'filemetas?channel=chunlei&clienttype=0&web=1', '&bdstoken=', tokens['bdstoken'], ]) if dlink: data = ('dlink=1&target=' + encoder.encode_uri_component(json.dumps(filelist))) else: data = ('dlink=0&target=' + encoder.encode_uri_component(json.dumps(filelist))) req = net.urlopen(url, headers={ 'Cookie': cookie.sub_output('BDUSS'), 'Content-type': const.CONTENT_FORM, }, data=data.encode()) if req: content = req.data return json.loads(content.decode()) else: return None
def verify_share_password(uk, shareid, pwd, vcode=''): '''验证共享文件的密码. 如果密码正确, 会在返回的请求头里加入一个cookie: BDCLND pwd - 四位的明文密码 vcode - 验证码; 目前还不支持 ''' url = ''.join([ const.PAN_URL, 'share/verify?&clienttype=0&web=1&channel=chunlei', '&shareid=', shareid, '&uk=', uk, ]) data = 'pwd={0}&vcode={1}'.format(pwd, vcode) req = net.urlopen(url, data=data.encode()) if req: content = req.data.decode() info = json.loads(content) errno = info.get('errno', 1) if errno == 0: return req.headers.get_all('Set-Cookie') elif errno in (-19, -62, -63): pass # TODO: need verify code return None
def cloud_query_magnetinfo(cookie, tokens, source_url, save_path): '''获取磁链的信息. 在新建磁链任务时, 要先获取这个磁链的信息, 比如里面包含哪些文件, 文件的名 称与大小等. source_url - 磁链的url, 以magent:开头. save_path - 保存到哪个目录 ''' url = ''.join([ const.PAN_URL, 'rest/2.0/services/cloud_dl?channel=chunlei&clienttype=0&web=1', '&bdstoken=', tokens['bdstoken'], ]) data = ''.join([ 'method=query_magnetinfo&app_id=250528', '&source_url=', encoder.encode_uri_component(source_url), '&save_path=', encoder.encode_uri_component(save_path), '&type=4', ]) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}, data=data.encode()) if req: content = req.data return json.loads(content.decode()) else: return None
def check_login(cookie, tokens, username): '''进行登录验证, 主要是在服务器上验证这个帐户的状态. 如果帐户不存在, 或者帐户异常, 就不需要再进行最后一步的登录操作了. 这一步有可能需要输入验证码. 返回的信息如下: {"errInfo":{ "no": "0" }, "data": { "codeString" : "", "vcodetype" : "" }} ''' url = ''.join([ const.PASSPORT_URL, '?logincheck', '&token=', tokens['token'], '&tpl=mm&apiver=v3', '&tt=', util.timestamp(), '&username='******'&isphone=false', ]) headers={ 'Cookie': cookie.header_output(), 'Referer': const.REFERER, } req = net.urlopen(url, headers=headers) if req: ubi = req.headers.get_all('Set-Cookie') return ubi, json.loads(req.data.decode()) else: return None
def refresh_signin_vcode(cookie, tokens, vcodetype): '''刷新验证码. vcodetype - 在调用check_login()时返回的vcodetype. ''' url = ''.join([ const.PASSPORT_BASE, 'v2/?reggetcodestr', '&token=', tokens['token'], '&tpl=pp&apiver=v3', '&tt=', util.timestamp(), '&fr=ligin', '&vcodetype=', encoder.encode_uri(vcodetype), ]) headers={ 'Cookie': cookie.header_output(), 'Referer': const.REFERER, } logger.debug('refresh vcode url: %s' % url) req = net.urlopen(url, headers=headers) if req: try: data = req.data.decode('gbk') logger.debug('refresh vcode: %s' % data) return json.loads(data) except ValueError: logger.error(traceback.format_exc()) return None
def get_category(cookie, tokens, category, page=1): '''获取一个分类中的所有文件信息, 比如音乐/图片 目前的有分类有: 视频 - 1 音乐 - 2 图片 - 3 文档 - 4 应用 - 5 其它 - 6 BT种子 - 7 ''' timestamp = util.timestamp() url = ''.join([ const.PAN_API_URL, 'categorylist?channel=chunlei&clienttype=0&web=1', '&category=', str(category), '&pri=-1&num=100', '&t=', timestamp, '&page=', str(page), '&order=time&desc=1', '&_=', timestamp, '&bdstoken=', cookie.get('STOKEN').value, ]) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: content = req.data return json.loads(content.decode()) else: return None
def post_login(cookie, token, username, password, rsakey, verifycode='', codestring=''): '''登录验证. password - 使用RSA加密后的base64字符串 rsakey - 与public_key相匹配的rsakey verifycode - 验证码, 默认为空 @return (status, info). 其中, status表示返回的状态: 0 - 正常, 这里, info里面存放的是auth_cookie -1 - 未知异常 4 - 密码错误 257 - 需要输入验证码, 此时info里面存放着(vcodetype, codeString)) ''' url = const.PASSPORT_LOGIN data = ''.join([ 'staticpage=https%3A%2F%2Fpassport.baidu.com%2Fstatic%2Fpasspc-account%2Fhtml%2Fv3Jump.html&charset=UTF-8', '&token=', token, '&tpl=pp&subpro=&apiver=v3', '&tt=', util.timestamp(), '&codestring=', codestring, '&safeflg=0&u=https%3A%2F%2Fpassport.baidu.com%2F&isPhone=', '&quick_user=0&logintype=basicLogin&logLoginType=pc_loginBasic&idc=', '&loginmerge=true', '&username='******'&password='******'&verifycode=', verifycode, '&mem_pass=on', '&rsakey=', rsakey, '&crypttype=12&ppui_logintime=',get_ppui_logintime(), '&callback=parent.bd__pcbs__m8g1kg', ]) logger.debug('auth.post_login: %s' % data) headers={ 'Cookie': cookie.header_output(), 'Content-Type': const.CONTENT_FORM, 'Referer': const.REFERER, 'Connection': 'Keep-Alive', } req = net.urlopen(url, headers=headers, data=data.encode()) if req: auth_cookie = req.headers.get_all('Set-Cookie') resp_content= req.data.decode() match = re.findall('"(err_no[^"]+)"', resp_content) if len(match) != 1: return (-1, None) query = dict(urllib.parse.parse_qsl(match[0])) err_no = int(query.get('err_no', '-1')) if err_no == 0: return (0, auth_cookie) if err_no != 257: return (err_no, None) vcodetype = query.get('vcodetype', '') codeString = query.get('codeString', '') if vcodetype and codeString: return (257, (vcodetype, codeString)) return (-1, None) else: return (-1, None) return (-1, None)
def dump_image(url, filepath): req = net.urlopen(url) if not req or not req.data: logger.warn('update_liststore_image(), failed to request %s' % url) return False with open(filepath, 'wb') as fh: fh.write(req.data) return True
def get_share_uk_and_shareid(cookie, url): '''从共享链接中提示uk和shareid. 如果共享文件需要输入密码, 就会将need_pwd设为True 如果成功, 返回(need_pwd, uk, shareid) 如果失败, 就返回None 目前支持的链接格式有: * http://pan.baidu.com/wap/link?uk=202032639&shareid=420754&third=0 * http://pan.baidu.com/share/link?uk=202032639&shareid=420754 * http://pan.baidu.com/s/1i3iQY48 ''' def parse_share_uk(content): '''代码片段如下: yunData.SHARE_ID = "677200861"; yunData.SHARE_UK = "1295729848"; ''' uk_reg = re.compile('yunData.SHARE_UK\s*=\s*"(\d+)"') shareid_reg = re.compile('yunData.SHARE_ID\s*=\s*"(\d+)"') uk_match = uk_reg.search(content) shareid_match = shareid_reg.search(content) if uk_match and shareid_match: return False, uk_match.group(1), shareid_match.group(1) else: return None def parse_uk_from_url(url): uk_reg = re.compile('uk=(\d+)') uk_match = uk_reg.search(url) shareid_reg = re.compile('shareid=(\d+)') shareid_match = shareid_reg.search(url) if not uk_match or not shareid_match: return '', '' uk = uk_match.group(1) shareid = shareid_match.group(1) return uk, shareid # 识别加密链接 req = net.urlopen_without_redirect(url, headers={ 'Cookie': cookie.header_output(), }) if req and req.headers.get('Location'): init_url = req.headers.get('Location') if init_url.find('share/init') > -1: uk, shareid = parse_uk_from_url(init_url) return True, uk, shareid # 处理短链接 if url.startswith('http://pan.baidu.com/s/'): req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), }) if req: return parse_share_uk(req.data.decode()) # 处理正常链接 uk, shareid = parse_uk_from_url(url) return False, uk, shareid
def get_BAIDUID(): '''获取一个cookie - BAIDUID. 这里, 我们访问百度首页, 返回的response header里面有我们需要的cookie ''' req = net.urlopen(const.REFERER) if req: return req.headers.get_all('Set-Cookie') else: return None
def get_user_uk(cookie, tokens): '''获取用户的uk''' url = 'http://yun.baidu.com' req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: content = req.data.decode() match = re.findall('/share/home\?uk=(\d+)" target=', content) if len(match) == 1: return match[0] return None
def get_bdstoken(cookie): '''从/disk/home页面获取bdstoken等token信息 这些token对于之后的请求非常重要. ''' url = const.PAN_REFERER req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: return parse_bdstoken(req.data.decode()) else: return None
def get_wap_signin_vcode(cookie, codeString): '''获取wap登录时的验证码''' url = 'http://wappass.baidu.com/cgi-bin/genimage?' + codeString req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), 'Referer': 'http://wappass.badu.com', }) if req: return req.data else: return None
def get_wap_passport(): '''WAP登录. 返回cookie和登录form''' url = 'http://wappass.baidu.com/passport' req = net.urlopen(url) if req: return (req.headers.get_all('Set-Cookie'), parse_wap_passport(req.data.decode())) else: return None, None
def get_user_uk(cookie, tokens): '''获取用户的uk''' url = 'http://yun.baidu.com' req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: content = req.data.decode() match = re.findall(',\"uk\":(\d+),', content) if len(match) == 1: return match[0] else: logger.warn('pcs.get_user_uk(), failed to parse uk, %s' % url) return None
def cloud_add_bt_task(cookie, tokens, source_url, save_path, selected_idx, file_sha1='', vcode='', vcode_input=''): '''新建一个BT类的离线下载任务, 包括magent磁链. source_path - BT种子所在的绝对路径 save_path - 下载的文件要存放到的目录 selected_idx - BT种子中, 包含若干个文件, 这里, 来指定要下载哪些文件, 从1开始计数. file_sha1 - BT种子的sha1值, 如果是magent的话, 这个sha1值可以为空 vcode - 验证码的vcode vcode_input - 用户输入的四位验证码 ''' url = ''.join([ const.PAN_URL, 'rest/2.0/services/cloud_dl?channel=chunlei&clienttype=0&web=1', '&bdstoken=', tokens['bdstoken'], ]) type_ = '2' url_type = 'source_path' if source_url.startswith('magnet:'): type_ = '4' url_type = 'source_url' if not save_path.endswith('/'): save_path = save_path + '/' data = [ 'method=add_task&app_id=250528', '&file_sha1=', file_sha1, '&save_path=', encoder.encode_uri_component(save_path), '&selected_idx=', ','.join(str(i) for i in selected_idx), '&task_from=1', '&t=', util.timestamp(), '&', url_type, '=', encoder.encode_uri_component(source_url), '&type=', type_ ] if vcode: data.append('&input=') data.append(vcode_input) data.append('&vcode=') data.append(vcode) data = ''.join(data) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}, data=data.encode()) if req: content = req.data return json.loads(content.decode()) else: return None
def get_quota(cookie, tokens): '''获取当前的存储空间的容量信息.''' url = ''.join([ const.PAN_API_URL, 'quota?channel=chunlei&clienttype=0&web=1', '&t=', util.timestamp(), ]) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: content = req.data return json.loads(content.decode()) else: return None
def get_bdstoken(cookie): '''从/disk/home页面获取bdstoken等token信息 这些token对于之后的请求非常重要. ''' url = const.PAN_REFERER req = net.urlopen(url, headers={'Cookie': cookie.header_output()}, cookie=cookie) if req: return parse_bdstoken(req.data.decode()) else: return None
def list_share_single_file(cookie, tokens, uk, shareid, surl): '''获取单独共享出来的文件. 目前支持的链接格式有: * http(s)://pan.baidu.com/wap/link?uk=202032639&shareid=420754&third=0 * http(s)://pan.baidu.com/share/link?uk=202032639&shareid=420754 * http(s)://pan.baidu.com/wap/init?surl=pMi4xab * http(s)://pan.baidu.com/share/init?surl=pMi4xab ''' def parse_share_page(content): tree = html.fromstring(content) script_sel = CSS('script') scripts = script_sel(tree) for script in scripts: if script.text and (script.text.find('yunData.setData') > -1 or script.text.find('window.yunData') > -1): break else: logger.warn('pcs.parse_share_page: failed to get filelist, %s', url) return None type1 = ',"third":0,"bdstoken":' type2 = ',"uk":' start = script.text.find('"file_list":') end = script.text.find(type1) if start == -1: return None if end == -1: end = script.text.find(type2) if end == -1: return None json_str = script.text[start + 12:end] try: return json.loads(json_str) except ValueError: logger.warn(traceback.format_exc()) return None url = ''.join([const.PAN_URL, 'wap/link', '?third=0']) if surl: url = '{0}&surl={1}'.format(url, surl) else: url = '{0}&uk={1}&shareid={2}'.format(url, uk, shareid) req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), 'Referer': const.SHARE_REFERER, }) if req: return parse_share_page(req.data.decode()) else: return None
def get_bdstoken(cookie): print( '/usr/local/lib/python3.4/dist-packages/bcloud/auth.py:get_bdstoken 281' ) '''从/disk/home页面获取bdstoken等token信息 这些token对于之后的请求非常重要. ''' url = const.PAN_REFERER req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: return parse_bdstoken(req.data.decode()) else: return None
def get_user_uk(cookie, tokens): print( '/usr/local/lib/python3.4/dist-packages/bcloud/pcs.py:get_user_uk 42') '''获取用户的uk''' url = 'http://yun.baidu.com' req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: content = req.data.decode() match = re.findall('/share/home\?uk=(\d+)" target=', content) if len(match) == 1: return match[0] else: logger.warn('pcs.get_user_uk(), failed to parse uk, %s' % url) return None
def list_share_single_file(cookie, tokens, uk, shareid): '''获取单独共享出来的文件. 目前支持的链接格式有: * http://pan.baidu.com/wap/link?uk=202032639&shareid=420754&third=0 * http://pan.baidu.com/share/link?uk=202032639&shareid=420754 ''' def parse_share_page(content): tree = html.fromstring(content) script_sel = CSS('script') scripts = script_sel(tree) for script in scripts: if (script.text and (script.text.find('viewsingle_param') > -1 or script.text.find('mpan.viewlist_param') > -1)): break else: logger.warn('pcs.parse_share_page: failed to get filelist, %s', url) return None start = script.text.find('viewsingle_param.list=JSON.parse(') end = script.text.find(');mpan.viewsingle_param.username') if start == -1 or end == -1: start = script.text.find('listArr:JSON.parse(') end = script.text.find('),rootPath:') if start == -1 or end == -1: return None else: json_str = script.text[start+19:end] else: json_str = script.text[start+33:end] try: return json.loads(json.loads(json_str)) except ValueError: logger.warn(traceback.format_exc()) return None url = ''.join([ const.PAN_URL, 'wap/link', '?shareid=', shareid, '&uk=', uk, '&third=0', ]) req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), 'Referer': const.SHARE_REFERER, }) if req: return parse_share_page(req.data.decode()) else: return None
def cloud_add_link_task(cookie, tokens, source_url, save_path, vcode='', vcode_input=''): '''新建离线下载任务. source_url - 可以是http/https/ftp等一般的链接 可以是eMule这样的链接 path - 要保存到哪个目录, 比如 /Music/, 以/开头, 以/结尾的绝对路径. ''' url = ''.join([ const.PAN_URL, 'rest/2.0/services/cloud_dl?channel=chunlei', '&clienttype=', const.PC_CLIENT_TYPE, '&web=1', '&bdstoken=', tokens['bdstoken'], ]) type_ = '' if source_url.startswith('ed2k'): type_ = '&type=3' if not save_path.endswith('/'): save_path = save_path + '/' data = [ 'method=add_task&app_id=250528', '&source_url=', encoder.encode_uri_component(source_url), '&save_path=', encoder.encode_uri_component(save_path), '&type=', type_, ] if vcode: data.append('&input=') data.append(vcode_input) data.append('&vcode=') data.append(vcode) data = ''.join(data) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}, data=data.encode()) if req: content = req.data return json.loads(content.decode()) else: return None
def send_sms(cookie, tokens): '''要求百度向绑定的手机号上发一条包含验证码的短信''' url = ''.join([ const.PASSPORT_BASE, 'v2/sapi/authwidgetverify', '?authtoken=', tokens['authtoken'], '&type=mobile&jsonp=1&apiver=v3&verifychannel=&action=send', '&vcode=&needsid=&rsakey=&subpro=', ]) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: return json.loads(req.data.decode()) else: return None
def cloud_clear_task(cookie, tokens): '''清空离线下载的历史(已经完成或者取消的).''' url = ''.join([ const.PAN_URL, 'rest/2.0/services/cloud_dl?method=clear_task&app_id=250528', '&channel=chunlei&clienttype=0&web=1', '&t=', util.timestamp(), '&bdstoken=', tokens['bdstoken'], ]) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: content = req.data return json.loads(content.decode()) else: return None
def get_quota(cookie, tokens): print('/usr/local/lib/python3.4/dist-packages/bcloud/pcs.py:get_quota 28') '''获取当前的存储空间的容量信息.''' url = ''.join([ const.PAN_API_URL, 'quota?channel=chunlei&clienttype=0&web=1', '&t=', util.timestamp(), ]) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: content = req.data return json.loads(content.decode()) else: return None
def get_BAIDUID(): '''获取一个cookie - BAIDUID. 这里, 我们访问百度首页, 返回的response header里面有我们需要的cookie ''' url = ''.join([ const.PASSPORT_URL, '?getapi&tpl=mn&apiver=v3', '&tt=', util.timestamp(), '&class=login&logintype=basicLogin', ]) req = net.urlopen(url, headers={'Referer': ''}) if req: return req.headers.get_all('Set-Cookie') else: return None
def clear_trash(cookie, tokens): '''清空回收站, 将里面的所有文件都删除.''' url = ''.join([ const.PAN_API_URL, 'recycle/clear?channel=chunlei&clienttype=0&web=1', '&t=', util.timestamp(), '&bdstoken=', tokens['bdstoken'], ]) # 使用POST方式发送命令, 但data为空. req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), }, data=''.encode()) if req: content = req.data return json.loads(content.decode()) else: return None
def list_inbox(cookie, tokens, start=0, limit=20): '''获取收件箱里的文件信息.''' url = ''.join([ const.PAN_URL, 'inbox/object/list?type=1', '&start=', str(start), '&limit=', str(limit), '&_=', util.timestamp(), '&channel=chunlei&clienttype=0&web=1', '&bdstoken=', tokens['bdstoken'], ]) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: content = req.data return json.loads(content.decode()) else: return None
def list_share_files(cookie, tokens, uk, shareid, dirname, page=1): print( '/usr/local/lib/python3.4/dist-packages/bcloud/pcs.py:list_share_files 105' ) '''列举出用户共享的某一个目录中的文件信息 这个对所有用户都有效 uk - user key shareid - 共享文件的ID值 dirname - 共享目录, 如果dirname为None, 说明这有可能是一个单独共享的文件, 这里, 需要调用list_share_single_file() ''' if not dirname: return list_share_single_file(cookie, tokens, uk, shareid) url = ''.join([ const.PAN_URL, 'share/list?channel=chunlei&clienttype=0&web=1&num=50', '&t=', util.timestamp(), '&page=', str(page), '&dir=', encoder.encode_uri_component(dirname), '&t=', util.latency(), '&shareid=', shareid, '&order=time&desc=1', '&uk=', uk, '&_=', util.timestamp(), '&bdstoken=', tokens['bdstoken'], ]) req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), 'Referer': const.SHARE_REFERER, }) if req: content = req.data info = json.loads(content.decode()) if info['errno'] == 0: return info['list'] return list_share_single_file(cookie, tokens, uk, shareid)
def get_sign_and_timestamp(cookie): '''获得部分API需要的timestamp和sign参数.''' req = net.urlopen(const.PAN_URL, headers={'Cookie': cookie.header_output()}) if req: content = req.data.decode() sign1_match = re.findall('"sign1":"(.+)","sign2"', content) sign3_match = re.findall('"sign3":"(.+)","timestamp"', content) timestamp_match = re.findall(',"timestamp":(\d+)', content) if len(sign1_match) == 1 and len(sign3_match) == 1 and len( timestamp_match) == 1: timestamp = int(timestamp_match[0]) sign1 = sign1_match[0] sign3 = sign3_match[0] sign = util.RC4_encrypt(sign3, sign1) if sign: return sign, timestamp return None, None
def get_user_info(tokens, uk): '''获取用户的部分信息. 比如头像, 用户名, 自我介绍, 粉丝数等. 这个接口可用于查询任何用户的信息, 只要知道他/她的uk. ''' url = ''.join([ const.PAN_URL, 'pcloud/user/getinfo?channel=chunlei&clienttype=0&web=1', '&bdstoken=', tokens['bdstoken'], '&query_uk=', uk, '&t=', util.timestamp(), ]) req = net.urlopen(url) if req: info = json.loads(req.data.decode()) if info and info['errno'] == 0: return info['user_info'] return None
def get_signin_vcode(cookie, codeString): '''获取登录时的验证码图片. codeString - 调用check_login()时返回的codeString. ''' url = ''.join([ const.PASSPORT_BASE, 'cgi-bin/genimage?', codeString, ]) headers={ 'Cookie': cookie.header_output(), 'Referer': const.REFERER, } req = net.urlopen(url, headers=headers) if req: return req.data else: return None
def get_streaming_playlist(cookie, path, video_type='M3U8_AUTO_480'): '''获取流媒体(通常是视频)的播放列表. 默认得到的是m3u8格式的播放列表, 因为它最通用. path - 视频的绝对路径 video_type - 视频格式, 可以根据网速及片源, 选择不同的格式. ''' url = ''.join([ const.PCS_URL, 'file?method=streaming', '&path=', encoder.encode_uri_component(path), '&type=', video_type, '&app_id=250528', ]) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: return req.data else: return None
def get_BAIDUID(): print( '/usr/local/lib/python3.4/dist-packages/bcloud/auth.py:get_BAIDUID 28') '''获取一个cookie - BAIDUID. 这里, 我们访问百度首页, 返回的response header里面有我们需要的cookie ''' url = ''.join([ const.PASSPORT_URL, '?getapi&tpl=mn&apiver=v3', '&tt=', util.timestamp(), '&class=login&logintype=basicLogin', ]) req = net.urlopen(url, headers={'Referer': ''}) if req: return req.headers.get_all('Set-Cookie') else: return None
def unzip_view(cookie, tokens, path, subpath="/", start=0, limit=100, return_path=False): '''查看压缩包的文件列表 path - 压缩包的绝对路径(支持2GB以内的rar,zip压缩包) subpath - 压缩包内的相对路径,默认是根目录“/” start - 从第几个文件开始 limit - 一次最大列出文件数 ''' url = ''.join([ const.PAN_API_URL, 'unzip/list?app_id=250528&channel=chunlei&clienttype=0&web=1&appid=250528', '&path=', encoder.encode_uri_component(path), '&subpath=', encoder.encode_uri_component(subpath), '&start=', str(start), '&limit=', str(limit), '&bdstoken=', tokens['bdstoken'], ]) req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), 'Referer': const.SHARE_REFERER, }) if req: content = json.loads(req.data.decode()) else: content = None if return_path: return content, path else: return content
def get_public_key(cookie, tokens): '''获取RSA公钥, 这个用于加密用户的密码 返回的数据如下: {"errno":'0',"msg":'',"pubkey":'-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDk\/ufXg3IBW8+h5i8L8NoXUzcN\nMeKrh4zEupGBkyrURIPUXKDFLWjrv4n2j3RpMZ8GQn\/ETcfoIHGBoCUKJWcfcvmi\nG+OkYeqT6zyJasF0OlKesKfz0fGogMtdCQ6Kqq7X2vrzBPL+4SNU2wgU31g\/tVZl\n3zy5qAsBFkC70vs5FQIDAQAB\n-----END PUBLIC KEY-----\n',"key":'lwCISJnvs7HRNCTxpX7vi25bV9YslF2J'} ''' url = ''.join([ const.PASSPORT_BASE, 'v2/getpublickey', '?token=', tokens['token'], '&tpl=pp&apiver=v3&tt=', util.timestamp(), ]) headers={ 'Cookie': cookie.header_output(), 'Referer': const.REFERER, } req = net.urlopen(url, headers=headers) if req: data = req.data return util.json_loads_single(req.data.decode()) return None
def cloud_query_sinfo(cookie, tokens, source_path): '''获取网盘中种子的信息, 比如里面的文件名, 文件大小等. source_path - BT种子的绝对路径. ''' url = ''.join([ const.PAN_URL, 'rest/2.0/services/cloud_dl?channel=chunlei&clienttype=0&web=1', '&method=query_sinfo&app_id=250528', '&bdstoken=', tokens['bdstoken'], '&source_path=', encoder.encode_uri_component(source_path), '&type=2', '&t=', util.timestamp(), ]) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: content = req.data return json.loads(content.decode()) else: return None
def delete_files(cookie, tokens, filelist): '''批量删除文件/目录. filelist - 待删除的文件/目录列表, 绝对路径 ''' url = ''.join([ const.PAN_API_URL, 'filemanager?channel=chunlei&clienttype=0&web=1&opera=delete', '&bdstoken=', tokens['bdstoken'], ]) data = 'filelist=' + encoder.encode_uri_component(json.dumps(filelist)) req = net.urlopen(url, headers={ 'Content-type': const.CONTENT_FORM_UTF8, 'Cookie': cookie.header_output(), }, data=data.encode()) if req: content = req.data return json.loads(content.decode()) else: return None
def cloud_list_task(cookie, tokens, start=0): '''获取当前离线下载的任务信息 start - 从哪个任务开始, 从0开始计数, 会获取这50条任务信息 ''' url = ''.join([ const.PAN_URL, 'rest/2.0/services/cloud_dl?channel=chunlei&clienttype=0&web=1', '&bdstoken=', tokens['bdstoken'], '&need_task_info=1&status=255', '&start=', str(start), '&limit=50&method=list_task&app_id=250528', '&t=', util.timestamp(), ]) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: content = req.data return json.loads(content.decode()) else: return None
def cloud_delete_task(cookie, tokens, task_id): '''删除一个离线下载任务, 不管这个任务是否已完成下载. 同时还会把它从下载列表中删除. ''' url = ''.join([ const.PAN_URL, 'rest/2.0/services/cloud_dl', '?bdstoken=', tokens['bdstoken'], '&task_id=', str(task_id), '&method=delete_task&app_id=250528', '&t=', util.timestamp(), '&channel=chunlei&clienttype=0&web=1', ]) req = net.urlopen(url, headers={'Cookie': cookie.header_output()}) if req: content = req.data return json.loads(content.decode()) else: return None
def disable_share(cookie, tokens, shareid_list): '''取消分享. shareid_list 是一个list, 每一项都是一个shareid ''' url = ''.join([ const.PAN_URL, 'share/cancel?channel=chunlei&clienttype=0&web=1', '&bdstoken=', tokens['bdstoken'], ]) data = 'shareid_list=' + encoder.encode_uri(json.dumps(shareid_list)) req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), 'Content-type': const.CONTENT_FORM_UTF8, }, data=data.encode()) if req: content = req.data return json.loads(content.decode()) else: return None
def share_transfer(cookie, tokens, shareid, uk, filelist, dest, upload_mode): print( '/usr/local/lib/python3.4/dist-packages/bcloud/pcs.py:share_transfer 342' ) ''' 将其他用户的文件保存到自己网盘里. uk - 其他用户的uk filelist - 要转移文件的列表, 是绝对路径 ''' ondup = const.UPLOAD_ONDUP[upload_mode] url = ''.join([ const.PAN_URL, 'share/transfer?app_id=250528&channel=chunlei&clienttype=0&web=1', '&bdstoken=', tokens['bdstoken'], '&from=', uk, '&shareid=', shareid, '&ondup=', ondup, '&async=1', ]) data = ''.join([ 'path=', encoder.encode_uri_component(dest), '&filelist=', encoder.encode_uri_component(json.dumps(filelist)) ]) req = net.urlopen(url, headers={ 'Cookie': cookie.header_output(), 'Content-Type': const.CONTENT_FORM_UTF8 }, data=data.encode()) if req: content = req.data.decode() return json.loads(content) else: return None
def get_UBI(cookie, tokens): '''检查登录历史, 可以获得一个Cookie - UBI. 返回的信息类似于: {"errInfo":{ "no": "0" }, "data": {'displayname':['*****@*****.**']}} ''' url = ''.join([ const.PASSPORT_URL, '?loginhistory', '&token=', tokens['token'], '&tpl=pp&apiver=v3', '&tt=', util.timestamp(), ]) headers={ 'Cookie': cookie.header_output(), 'Referer': const.REFERER, } req = net.urlopen(url, headers=headers) if req: return req.headers.get_all('Set-Cookie') else: return None