12
12
import threading
13
13
from bs4 import BeautifulSoup
14
14
from selenium .webdriver .common .by import By
15
+ from selenium import webdriver
15
16
from selenium .webdriver .support .wait import WebDriverWait
16
17
from selenium .webdriver .support import expected_conditions as EC
17
18
@@ -82,15 +83,15 @@ class Voice(Singleton):
82
83
__cookie = {}
83
84
__intervals = 3
84
85
__driver = None
85
- __gc_data = None
86
+ _gc_data = None
86
87
__try_time = 2
87
- __match = {}
88
+ _match = {}
88
89
89
90
def __init__ (self , email , passwd , debug = True ):
90
91
self .__email = email
91
92
self .__passwd = passwd
92
93
self .debug = debug
93
- self .__gc_data_name = '_gcData'
94
+ self ._gc_data_name = '_gcData'
94
95
self .__browser_name = 'PhantomJS' # 默认
95
96
self .__module = 'selenium.webdriver'
96
97
@@ -168,7 +169,10 @@ def __login(self):
168
169
self .status ['login' ] = True # login successful flag
169
170
e = self .__initial ()
170
171
e .send (None )
171
-
172
+ except TimeoutException as e : # 如果出现超时,就重试
173
+ time .sleep (1 )
174
+ e = self .__login ()
175
+ e .send (None )
172
176
except NotOpenGoogle as e : # 打不开谷歌
173
177
raise NotOpenGoogle ('Can not open google, pleasw use VPN, you know...' )
174
178
except Exception as e :
@@ -218,26 +222,26 @@ def __initial(self):
218
222
yield
219
223
if self .status ['login' ]:
220
224
self .log .send (('initialization data...' ,))
221
- self .__gc_data = self .__driver .execute_script ('return %s' % self .__gc_data_name )
222
- if self .__gc_data is None : # 如果获取不到这个参数就回去重新获取 直到获取到为止
225
+ self ._gc_data = self .__driver .execute_script ('return %s' % self ._gc_data_name )
226
+ if self ._gc_data is None : # 如果获取不到这个参数就回去重新获取 直到获取到为止
223
227
time .sleep (self .__try_time )
224
228
continue
225
229
# format url
226
230
self .__cookie_func (self .__driver .get_cookies ()) # process cookie 处理 cookie
227
- self .__send_msg_url = '{}/sms/send/' .format (self .__gc_data ['baseUrl' ]) # process send msg url
228
- self .__call_url = '{}/call/connect/' .format (self .__gc_data ['baseUrl' ]) # 拨打电话的请求地址
229
- self .__call_cancel_url = '{}/call/cancel/' .format (self .__gc_data ['baseUrl' ]) # 取消拨打电话的请求地址
230
- self .__mark_url = '{}/inbox/mark/' .format (self .__gc_data ['baseUrl' ]) # 标记为已读的请求地址
231
- self .__del_msg_url = '{}/inbox/deleteMessages/' .format (self .__gc_data ['baseUrl' ]) # 删除信息
232
- self .__star_url = '{}/inbox/star/' .format (self .__gc_data ['baseUrl' ]) # 收藏信息
233
- self .__dow_msg_url = '{}/inbox/recent/' .format (self .__gc_data ['baseUrl' ]) # 下载信息
234
- self .__quick_add_url = '{}//phonebook/quickAdd/' .format (self .__gc_data ['baseUrl' ])
231
+ self ._send_msg_url = '{}/sms/send/' .format (self ._gc_data ['baseUrl' ]) # process send msg url
232
+ self .__call_url = '{}/call/connect/' .format (self ._gc_data ['baseUrl' ]) # 拨打电话的请求地址
233
+ self .__call_cancel_url = '{}/call/cancel/' .format (self ._gc_data ['baseUrl' ]) # 取消拨打电话的请求地址
234
+ self .__mark_url = '{}/inbox/mark/' .format (self ._gc_data ['baseUrl' ]) # 标记为已读的请求地址
235
+ self .__del_msg_url = '{}/inbox/deleteMessages/' .format (self ._gc_data ['baseUrl' ]) # 删除信息
236
+ self .__star_url = '{}/inbox/star/' .format (self ._gc_data ['baseUrl' ]) # 收藏信息
237
+ self .__dow_msg_url = '{}/inbox/recent/' .format (self ._gc_data ['baseUrl' ]) # 下载信息
238
+ self .__quick_add_url = '{}//phonebook/quickAdd/' .format (self ._gc_data ['baseUrl' ])
235
239
self .__voicemail_ogg_str = '{0}/media/send_voicemail_ogg/{1}?read=0'
236
240
237
- if len (self .__gc_data ['phones' ]) > 1 : # 获取绑定的号码
238
- for k , v in self .__gc_data ['phones' ].items ():
239
- if self .__gc_data ['phones' ][k ]['name' ] != 'Google Talk' :
240
- self .__call_phone_for = self .__gc_data ['phones' ][k ]
241
+ if len (self ._gc_data ['phones' ]) > 1 : # 获取绑定的号码
242
+ for k , v in self ._gc_data ['phones' ].items ():
243
+ if self ._gc_data ['phones' ][k ]['name' ] != 'Google Talk' :
244
+ self .__call_phone_for = self ._gc_data ['phones' ][k ]
241
245
break
242
246
# 是否需要检测新消息
243
247
self .status ['init' ] = True # 初始化完成
@@ -267,21 +271,21 @@ def __check_msg_par(self):
267
271
268
272
data = {'xpc' : {'tp' : None , 'osh' : None , 'pru' : 'https://www.google.com/voice/xpc/relay' ,
269
273
'ppu' : 'https://www.google.com/voice/xpc/blank/' ,
270
- 'lpu' : '{}/voice/xpc/blank/' .format (self .__gc_data ['xpcUrl' ])}}
274
+ 'lpu' : '{}/voice/xpc/blank/' .format (self ._gc_data ['xpcUrl' ])}}
271
275
272
- url = '{}/voice/xpc/' .format (self .__gc_data ['xpcUrl' ])
273
- r = self .__requests (url , params = data )
276
+ url = '{}/voice/xpc/' .format (self ._gc_data ['xpcUrl' ])
277
+ r = self ._requests (url , params = data )
274
278
par = re .findall ("\' (.*?)\' " , r .text )[0 ]
275
279
self .log .send (('xpc: %s' % par ,))
276
280
277
281
# https://clientsx.google.com/voice/xpc/checkMessages?r=xxxxxxx
278
- self .check_msg_url ['url' ] = '{0}/voice/xpc/checkMessages' .format (self .__gc_data ['xpcUrl' ])
282
+ self .check_msg_url ['url' ] = '{0}/voice/xpc/checkMessages' .format (self ._gc_data ['xpcUrl' ])
279
283
self .check_msg_url ['par' ] = {'r' : par }
280
284
self .status ['check' ] = True
281
285
282
286
# 开启检测消息线程
283
287
if self .status ['auto' ]:
284
- t = threading .Thread (target = self .__check_sms , args = (self .reply_sms ,), name = 'check-new-sms' )
288
+ t = threading .Thread (target = self ._check_sms , args = (self .reply_sms ,), name = 'check-new-sms' )
285
289
t .setDaemon (True )
286
290
t .start ()
287
291
@@ -307,9 +311,9 @@ def current_url(self):
307
311
def __headers (self ):
308
312
'''send post headers 请求头'''
309
313
return {'host' : 'www.google.com' , 'user-agent' : self .__user_agent ,
310
- 'referer' : self .__gc_data ['baseUrl' ], 'content-type' : 'application/x-www-form-urlencoded;charset=UTF-8' }
314
+ 'referer' : self ._gc_data ['baseUrl' ], 'content-type' : 'application/x-www-form-urlencoded;charset=UTF-8' }
311
315
312
- def __requests (self , url , params = None , data = None , method = 'get' ):
316
+ def _requests (self , url , params = None , data = None , method = 'get' ):
313
317
'''
314
318
requests uniform, code reuse 封装请求方法
315
319
:param url: request url 请求的地址
@@ -327,6 +331,8 @@ def __requests(self, url, params=None, data=None, method='get'):
327
331
return r
328
332
else : # not support method #TODO img? 发送图片
329
333
pass
334
+ except AttributeError as e :
335
+ return None
330
336
except OSError as e : # 如果是本地测试出现这个报错要更换为全局代理
331
337
raise ProxyError ('please proxy global' )
332
338
except Exception as e :
@@ -339,19 +345,19 @@ def check_unread_msg(self):
339
345
:return dict
340
346
'''
341
347
if self .status ['login' ] and self .status ['check' ]:
342
- r = self .__requests (self .check_msg_url ['url' ], params = self .check_msg_url ['par' ]) # check...
348
+ r = self ._requests (self .check_msg_url ['url' ], params = self .check_msg_url ['par' ]) # check...
343
349
ret = r .json ()
344
350
return ret
345
351
self .log .send ((1 , 'check msg not ready' ))
346
352
347
- def __check_sms (self , func ):
353
+ def _check_sms (self , func ):
348
354
'''检测未读 sms, 并做出自定义的操作'''
349
355
while self .status ['login' ] and self .status ['check' ]:
350
356
res = self .check_unread_msg () # check sms...
351
357
if res ['data' ]['unreadCounts' ]['sms' ] > 0 : # have ...
352
358
sms_list = self .unsms
353
359
for i in sms_list :
354
- if i ['text' ].strip ().upper () in self .__match :
360
+ if i ['text' ].strip ().upper () in self ._match : # 匹配关键字
355
361
t = threading .Thread (target = func , args = (i ,), name = 'reply sms' )
356
362
t .setDaemon (True )
357
363
t .start ()
@@ -365,7 +371,7 @@ def reply_sms(self, data):
365
371
:param data: 需要回复的 sms 的数据
366
372
'''
367
373
self .log .send (('ready reply sms' ,))
368
- r = self .send_sms (data ['number' ], self .__match [data ['text' ]])
374
+ r = self .send_sms (data ['number' ], self ._match [data ['text' ]])
369
375
if r ['ok' ]:
370
376
self .log .send (('[success] reply sms to: %s' % data ['number' ],))
371
377
else :
@@ -399,10 +405,10 @@ def unsms(self):
399
405
获取未读的 sms
400
406
:return: dict
401
407
'''
402
- par = {'v' : self .__gc_data ['v' ]} # token
408
+ par = {'v' : self ._gc_data ['v' ]} # token
403
409
if self .status ['login' ]:
404
410
sms_list = []
405
- r = self .__requests (self .__dow_msg_url , params = par )
411
+ r = self ._requests (self .__dow_msg_url , params = par )
406
412
data = self .__process_xml (r )
407
413
msg_list = data ['soup' ].find_all (name = 'div' , class_ = 'gc-message-unread' ) # 所有的未读短信消息
408
414
# data = {'sms': [], 'voicemail': []}
@@ -411,10 +417,14 @@ def unsms(self):
411
417
if 'gc-message-sms' in attr : # sms
412
418
sms = {}
413
419
sms ['id' ] = msg ['id' ]
414
- sms ['number' ] = msg .find (name = 'span' , class_ = 'gc-message-sms-from' ).text .strip ()[
415
- :- 1 ] # 去掉空格并切掉最后的冒号
420
+ sms ['number' ] = msg .find (name = 'span' , class_ = 'gc-message-sms-from' ).text .strip ()[:- 1 ] # 去掉空格并切掉最后的冒号
421
+ # ----- 处理时间 -----
422
+ time_str = msg .find (name = 'span' , class_ = 'gc-message-sms-time' ).text .strip ()
423
+ local_time = time .strftime ("%Y-%m-%d" , time .localtime ())
424
+ sms_time_str = '' .join ((local_time , ' ' , time_str ))
425
+ sms_time = time .strptime (sms_time_str , '%Y-%m-%d %I:%M %p' )
426
+ sms ['time' ] = time .strftime ("%Y-%m-%d %X" , sms_time )
416
427
sms ['text' ] = msg .find (name = 'span' , class_ = 'gc-message-sms-text' ).text
417
- sms ['time' ] = msg .find (name = 'span' , class_ = 'gc-message-sms-time' ).text .strip ()
418
428
self .log .send (('[sms] time: {0}; id:{1} .' .format (sms ['time' ], sms ['id' ]),))
419
429
print (sms )
420
430
sms_list .append (sms )
@@ -426,10 +436,10 @@ def read_sms(self):
426
436
所有的已读读短信消息
427
437
:return: dict
428
438
'''
429
- par = {'v' : self .__gc_data ['v' ]} # token
439
+ par = {'v' : self ._gc_data ['v' ]} # token
430
440
if self .status ['login' ]:
431
441
sms_list = []
432
- r = self .__requests (self .__dow_msg_url , params = par )
442
+ r = self ._requests (self .__dow_msg_url , params = par )
433
443
data = self .__process_xml (r )
434
444
msg_list = data ['soup' ].select ('div.gc-message-sms.gc-message-read' ) # 所有的已读读短信消息
435
445
# data = {'sms': [], 'voicemail': []}
@@ -438,8 +448,7 @@ def read_sms(self):
438
448
if 'gc-message-sms' in attr : # sms
439
449
sms = {}
440
450
sms ['id' ] = msg ['id' ]
441
- sms ['number' ] = msg .find (name = 'span' , class_ = 'gc-message-sms-from' ).text .strip ()[
442
- :- 1 ] # 去掉空格并切掉最后的冒号
451
+ sms ['number' ] = msg .find (name = 'span' , class_ = 'gc-message-sms-from' ).text .strip ()[:- 1 ] # 去掉空格并切掉最后的冒号
443
452
sms ['text' ] = msg .find (name = 'span' , class_ = 'gc-message-sms-text' ).text
444
453
sms ['time' ] = msg .find (name = 'span' , class_ = 'gc-message-sms-time' ).text .strip ()
445
454
sms_list .append (sms )
@@ -451,10 +460,10 @@ def voicemail(self):
451
460
获取未读的 voicemail, 包括文本和语音(下载url 地址)
452
461
:return:
453
462
'''
454
- par = {'v' : self .__gc_data ['v' ]} # token
463
+ par = {'v' : self ._gc_data ['v' ]} # token
455
464
if self .status ['login' ]:
456
465
voice_list = []
457
- r = self .__requests (self .__dow_msg_url , params = par )
466
+ r = self ._requests (self .__dow_msg_url , params = par )
458
467
data = self .__process_xml (r )
459
468
msg_list = data ['soup' ].find_all (name = 'div' , class_ = 'gc-message-unread' ) # 所有的未读语音消息
460
469
for msg in msg_list :
@@ -466,7 +475,7 @@ def voicemail(self):
466
475
voicemail ['number' ] = msg .find (name = 'span' , class_ = 'gc-nobold' ).text
467
476
voicemail ['time' ] = msg .find (name = 'span' , class_ = 'gc-message-time' ).text
468
477
voicemail ['text' ] = msg .find (name = 'span' , class_ = 'gc-edited-trans-text' ).text
469
- voicemail ['ogg_url' ] = self .__voicemail_ogg_str .format (self .__gc_data ['baseUrl' ], voicemail ['id' ])
478
+ voicemail ['ogg_url' ] = self .__voicemail_ogg_str .format (self ._gc_data ['baseUrl' ], voicemail ['id' ])
470
479
471
480
if len (voicemail ['text' ]) < 1 :
472
481
voicemail ['text' ] = '[None] - please go to the website...'
@@ -480,7 +489,7 @@ def dow_voicemail(self, url):
480
489
:param url: voicemail 下载地址的url
481
490
:return: r.content 二进制数据
482
491
'''
483
- r = self .__requests (url )
492
+ r = self ._requests (url )
484
493
return r .content
485
494
486
495
def quick_add (self , name , number , phone_type = 0 ):
@@ -495,9 +504,9 @@ def quick_add(self, name, number, phone_type=0):
495
504
if self .status ['login' ]:
496
505
data = {'phoneNumber' : '+1%s' % number ,
497
506
'phoneType' : phone_type_dict [phone_type ],
498
- '_rnr_se' : self .__gc_data ['_rnr_se' ],
507
+ '_rnr_se' : self ._gc_data ['_rnr_se' ],
499
508
'needsCheck' : 1 }
500
- r = self .__requests (self .__quick_add_url , data = data , method = 'post' )
509
+ r = self ._requests (self .__quick_add_url , data = data , method = 'post' )
501
510
ret = r .json ()
502
511
if ret ['ok' ]:
503
512
return ret
@@ -514,8 +523,8 @@ def mark(self, msg_id, read=1):
514
523
:return:
515
524
'''
516
525
if self .status ['login' ]:
517
- data = {'_rnr_se' : self .__gc_data ['_rnr_se' ], 'messages' : msg_id , 'read' : read }
518
- r = self .__requests (self .__mark_url , data = data , method = 'post' )
526
+ data = {'_rnr_se' : self ._gc_data ['_rnr_se' ], 'messages' : msg_id , 'read' : read }
527
+ r = self ._requests (self .__mark_url , data = data , method = 'post' )
519
528
ret = r .json ()
520
529
if ret ['ok' ]:
521
530
return ret
@@ -527,8 +536,8 @@ def mark(self, msg_id, read=1):
527
536
def star (self , msg_id ):
528
537
''' 把信息标记为收藏 '''
529
538
if self .status ['login' ]:
530
- data = {'_rnr_se' : self .__gc_data ['_rnr_se' ], 'messages' : msg_id , 'star' : 1 }
531
- r = self .__requests (self .__star_url , data = data , method = 'post' )
539
+ data = {'_rnr_se' : self ._gc_data ['_rnr_se' ], 'messages' : msg_id , 'star' : 1 }
540
+ r = self ._requests (self .__star_url , data = data , method = 'post' )
532
541
ret = r .json ()
533
542
if ret ['ok' ]:
534
543
return ret
@@ -540,8 +549,8 @@ def star(self, msg_id):
540
549
def unstar (self , msg_id ):
541
550
''' 把已经标记收藏的消息取消收藏标记 '''
542
551
if self .status ['login' ]:
543
- data = {'_rnr_se' : self .__gc_data ['_rnr_se' ], 'messages' : msg_id , 'star' : 0 }
544
- r = self .__requests (self .__star_url , data = data , method = 'post' )
552
+ data = {'_rnr_se' : self ._gc_data ['_rnr_se' ], 'messages' : msg_id , 'star' : 0 }
553
+ r = self ._requests (self .__star_url , data = data , method = 'post' )
545
554
ret = r .json ()
546
555
if ret ['ok' ]:
547
556
return ret
@@ -553,8 +562,8 @@ def unstar(self, msg_id):
553
562
def del_msg (self , msg_id ):
554
563
''' 删除信息 '''
555
564
if self .status ['login' ]:
556
- data = {'_rnr_se' : self .__gc_data ['_rnr_se' ], 'messages' : msg_id , 'trash' : 1 }
557
- r = self .__requests (self .__del_msg_url , data = data , method = 'post' )
565
+ data = {'_rnr_se' : self ._gc_data ['_rnr_se' ], 'messages' : msg_id , 'trash' : 1 }
566
+ r = self ._requests (self .__del_msg_url , data = data , method = 'post' )
558
567
ret = r .json ()
559
568
if ret ['ok' ]:
560
569
return ret
@@ -577,8 +586,8 @@ def send_sms(self, number, text):
577
586
if self .status ['login' ]:
578
587
# 数据格式
579
588
msg = {'id' : None , 'phoneNumber' : number , 'text' : text , 'sendErrorSms' : 0 ,
580
- '_rnr_se' : self .__gc_data ['_rnr_se' ]}
581
- r = self .__requests (self .__send_msg_url , method = 'post' , data = msg ) # post sms
589
+ '_rnr_se' : self ._gc_data ['_rnr_se' ]}
590
+ r = self ._requests (self ._send_msg_url , method = 'post' , data = msg ) # post sms
582
591
ret = r .json ()
583
592
if ret ['ok' ]:
584
593
return ret
@@ -596,11 +605,11 @@ def call(self, number):
596
605
if self .status ['login' ]:
597
606
# 数据格式
598
607
data = {'outgoingNumber' : number , 'remember' : 0 , 'phoneType' : self .__call_phone_for ['type' ],
599
- 'subscriberNumber' : self .__gc_data ['number' ]['raw' ],
608
+ 'subscriberNumber' : self ._gc_data ['number' ]['raw' ],
600
609
'forwardingNumber' : self .__call_phone_for ['phoneNumber' ],
601
- '_rnr_se' : self .__gc_data ['_rnr_se' ]}
610
+ '_rnr_se' : self ._gc_data ['_rnr_se' ]}
602
611
603
- r = self .__requests (self .__call_url , data = data , method = 'post' ) # 拨打
612
+ r = self ._requests (self .__call_url , data = data , method = 'post' ) # 拨打
604
613
ret = r .json ()
605
614
if ret ['ok' ]:
606
615
return ret
@@ -620,9 +629,9 @@ def cancel_call(self, call_id):
620
629
data = {'outgoingNumber' : None ,
621
630
'forwardingNumber' : None ,
622
631
'cancelType' : 'C2C' ,
623
- '_rnr_se' : self .__gc_data ['_rnr_se' ],
632
+ '_rnr_se' : self ._gc_data ['_rnr_se' ],
624
633
'callId' : call_id }
625
- r = self .__requests (self .__call_cancel_url , data = data , method = 'post' )
634
+ r = self ._requests (self .__call_cancel_url , data = data , method = 'post' )
626
635
return r .json () # {"ok" : false}
627
636
return
628
637
@@ -647,14 +656,13 @@ def set_intervals(self, sec):
647
656
648
657
def set_match (self , data ):
649
658
'''设置匹配关键字,字典格式'''
650
- self .__match = data
659
+ self ._match = data
651
660
652
661
def __createInstance (self , module_name , class_name , * args , ** kwargs ):
653
662
'''
654
663
create user input browser object 动态导入浏览器浏览器类型模块
655
664
:return: object
656
665
'''
657
- from selenium import webdriver
658
666
659
667
headers = {'Accept' : '*/*' ,
660
668
'Accept-Encoding' : 'gzip, deflate, sdch' ,
@@ -706,7 +714,7 @@ def screenshots(self, driver, sleep=None):
706
714
if sleep :
707
715
time .sleep (sleep )
708
716
try :
709
- driver .save_screenshot ("./%s.png" % (time .strftime ("%Y-%m-%d %X" , time .localtime ())))
717
+ driver .save_screenshot ("./img/ %s.png" % (time .strftime ("%Y-%m-%d %X" , time .localtime ())))
710
718
except Exception :
711
719
pass
712
720
@@ -716,5 +724,5 @@ def get_js(self, js_str):
716
724
717
725
def __del__ (self ):
718
726
''' 退出模拟的浏览器 quit driver'''
719
- if isinstance (self .driver , type (None )):
727
+ if not isinstance (self .driver , type (None )):
720
728
self .driver .quit ()
0 commit comments