1 #-*- coding:utf-8 -*-
2 __author__ = 'Administrator'
3
4 importtime5 importjson6 importre7 importrequests8 importexecjs9 importbase6410 from urllib.parse importurlencode11 from requests_toolbelt importMultipartEncoder12 from Crypto.Cipher importPKCS1_v1_513 from Crypto.PublicKey importRSA14 from hashlib importmd515 from zlib importcrc3216 #import progressbar
17 importsys18 from contextlib importclosing19 importtime20 importos21
22 try:23 requests.packages.urllib3.disable_warnings()24 except:25 pass
26
27 headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36'
28 '(KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',29 }30
31 #全局的session
32 session =requests.session()33 session.get('https://pan.baidu.com', headers=headers)34
35
36 classBufferReader(MultipartEncoder):37 """将multipart-formdata转化为stream形式的Proxy类38 """
39
40 def __init__(self, fields, boundary=None, callback=None, cb_args=(), cb_kwargs=None):41 self._callback =callback42 self._progress =043 self._cb_args =cb_args44 self._cb_kwargs = cb_kwargs or{}45 super(BufferReader, self).__init__(fields, boundary)46
47 def read(self, size=None):48 chunk =super(BufferReader, self).read(size)49 self._progress +=int(len(chunk))50 self._cb_kwargs.update({51 'size': self._len,52 'progress': self._progress53 })54 ifself._callback:55 try:56 self._callback(*self._cb_args, **self._cb_kwargs)57 except: #catches exception from the callback
58 #raise CancelledError('The upload was cancelled.')
59 pass
60 returnchunk61
62 classProgressBar():63 """
64 import progressbar65 使用第三方库显示上传进度66
67 """
68 def __init__(self):69 self.first_call =True70 def __call__(self, *args, **kwargs):71 ifself.first_call:72 self.widgets = [progressbar.Percentage(), ' ', progressbar.Bar(marker=progressbar.RotatingMarker('>')),73 ' ', progressbar.FileTransferSpeed()]74 self.pbar = progressbar.ProgressBar(widgets=self.widgets, maxval=kwargs['size']).start()75 self.first_call =False76
77 if kwargs['size'] <= kwargs['progress']:78 self.pbar.finish()79 else:80 self.pbar.update(kwargs['progress'])81
82
83 def_get_runntime():84 """
85 :param path: 加密js的路径,注意js中不要使用中文!估计是pyexecjs处理中文还有一些问题86 :return: 编译后的js环境,不清楚pyexecjs这个库的用法的请在github上查看相关文档87 """
88 phantom = execjs.get() #这里必须为phantomjs设置环境变量,否则可以写phantomjs的具体路径
89 with open('login.js', 'r') as f:90 source =f.read()91 returnphantom.compile(source)92
93 defget_gid():94 return _get_runntime().call('getGid')95
96 defget_callback():97 return _get_runntime().call('getCallback')98
99 def_get_curtime():100 return int(time.time()*1000)101
102 #抓包也不是百分百可靠啊,这里?getapi一定要挨着https://passport.baidu.com/v2/api/写,才会到正确的路由
103 defget_token(gid, callback):104 cur_time =_get_curtime()105 get_data ={106 'tpl': 'netdisk',107 'subpro': 'netdisk_web',108 'apiver': 'v3',109 'tt': cur_time,110 'class': 'login',111 'gid': gid,112 'logintype': 'basicLogin',113 'callback': callback114 }115 headers.update(dict(Referer='http://pan.baidu.com/', Accept='*/*', Connection='keep-alive', Host='passport.baidu.com'))116 resp = session.get(url='https://passport.baidu.com/v2/api/?getapi', params=get_data, headers=headers)117 if resp.status_code == 200 and callback inresp.text:118 #如果json字符串中带有单引号,会解析出错,只有统一成双引号才可以正确的解析
119 #data = eval(re.search(r'.*?\((.*)\)', resp.text).group(1))
120 data = json.loads(re.search(r'.*?\((.*)\)', resp.text).group(1).replace("'", '"'))121 return data.get('data').get('token')122 else:123 print('获取token失败')124 returnNone125
126 defget_rsa_key(token, gid, callback):127 cur_time =_get_curtime()128 get_data ={129 'token': token,130 'tpl': 'netdisk',131 'subpro': 'netdisk_web',132 'apiver': 'v3',133 'tt': cur_time,134 'gid': gid,135 'callback': callback,136 }137 resp = session.get(url='https://passport.baidu.com/v2/getpublickey', headers=headers, params=get_data)138 if resp.status_code == 200 and callback inresp.text:139 data = json.loads(re.search(r'.*?\((.*)\)', resp.text).group(1).replace("'", '"'))140 return data.get('pubkey'), data.get('key')141 else:142 print('获取rsa key失败')143 returnNone144
145 defencript_password(password, pubkey):146 """
147 import rsa148 使用rsa库加密(法一)149 pub = rsa.PublicKey.load_pkcs1_openssl_pem(pubkey.encode('utf-8'))150 encript_passwd = rsa.encrypt(password.encode('utf-8'), pub)151 return base64.b64encode(encript_passwd).decode('utf-8')152
153 """
154 #pubkey必须为bytes类型
155 pub=RSA.importKey(pubkey.encode('utf-8'))156 #构造“加密器”
157 encryptor=PKCS1_v1_5.new(pub)158 #加密的内容必须为bytes类型
159 encript_passwd =encryptor.encrypt(password.encode('utf-8'))160 return base64.b64encode(encript_passwd).decode('utf-8')161
162 deflogin(token, gid, callback, rsakey, username, password):163 post_data ={164 'staticpage': 'http://pan.baidu.com/res/static/thirdparty/pass_v3_jump.html',165 'charset': 'utf-8',166 'token': token,167 'tpl': 'netdisk',168 'subpro': 'netdisk_web',169 'apiver': 'v3',170 'tt': _get_curtime(),171 'codestring': '',172 'safeflg': 0,173 'u': 'http://pan.baidu.com/disk/home',174 'isPhone': '',175 'detect': 1,176 'gid': gid,177 'quick_user': 0,178 'logintype': 'basicLogin',179 'logLoginType': 'pc_loginBasic',180 'idc': '',181 'loginmerge': 'true',182 'foreignusername': '',183 'username': username,184 'password': password,185 'mem_pass': 'on',186 #返回的key
187 'rsakey': rsakey,188 'crypttype': 12,189 'ppui_logintime': 33554,190 'countrycode': '',191 'callback': 'parent.'+callback192 }193 resp = session.post(url='https://passport.baidu.com/v2/api/?login', data=post_data, headers=headers)194 if 'err_no=0' inresp.text:195 print('登录成功')196 else:197 print('登录失败')198 def progressbar(size=None, progress=None,progress_title="已完成",finish_title="全部完成"):199 #size:文件总字节数 progress:当前传输完成字节数
200 #print("{0} / {1}".format(size, progress))
201 if progress
&
&
<
&dlink
&&dlink