kmisc 2.1.121__py3-none-any.whl → 2.1.123__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
kmisc/__init__.py CHANGED
@@ -23,12 +23,13 @@ import fnmatch
23
23
  import smtplib
24
24
  import zipfile
25
25
  import tarfile
26
+ import warnings
26
27
  import email.utils
27
28
  from sys import modules
28
29
  from pprint import pprint
29
30
  import fcntl,socket,struct
30
31
  from email import encoders
31
- from threading import Thread
32
+ from threading import Thread, Lock
32
33
  from datetime import datetime
33
34
  from http.cookies import Morsel # This module for requests when you use build by pyinstaller command
34
35
  import xml.etree.ElementTree as ET
@@ -39,6 +40,10 @@ Process=multiprocessing.Process
39
40
  Queue=multiprocessing.Queue
40
41
  #from multiprocessing import Process, Queue
41
42
  from email.mime.multipart import MIMEMultipart
43
+
44
+ warning_message='ignore'
45
+ warnings.filterwarnings(warning_message)
46
+
42
47
  try:
43
48
  from kmport import *
44
49
  import kmport
@@ -3448,7 +3453,7 @@ def Upper(src,default='org'):
3448
3453
  if default in ['org',{'org'}]: return src
3449
3454
  return default
3450
3455
 
3451
- def web_capture(url,output_file,image_size='1920,1080',wait_time=3,ignore_certificate_error=False,username=None,password=None,auth_fields={'auth':{'type':'name','name':('username','password')},'submit':{'type':'submit','name':None}},next_do={}):
3456
+ def web_capture(url,output_file,image_size='1920,1080',wait_time=3,ignore_certificate_error=False,username=None,password=None,auth_fields={'auth':{'type':'name','name':('username','password')},'submit':{'type':'submit','name':None}},next_do={},gpu=False,live_capture=0,capture_method='file',capture_type='png',video_file=None,find_string=None,found_space='\n',log=None,ocr_enhance=False,daemon=False,backup=False):
3452
3457
  #auth_fields.submit.type : name : login button with name
3453
3458
  # : id : login button with id
3454
3459
  # : submit : submit button without name or id
@@ -3458,20 +3463,36 @@ def web_capture(url,output_file,image_size='1920,1080',wait_time=3,ignore_certif
3458
3463
  #auth_fields.auth.name : (usernane,password) : username/password field string for name or id
3459
3464
  #next_do : put data and click submit
3460
3465
 
3466
+ _url=url.split('/')
3467
+ url=WEB().url_join(*_url[1:],method=_url[0])
3461
3468
  if isinstance(image_size,str):
3462
3469
  if 'x' in image_size:
3463
3470
  image_size=image_size.split('x')
3464
3471
  elif ',' in image_size:
3465
3472
  image_size=image_size.split(',')
3473
+ elif '*' in image_size:
3474
+ image_size=image_size.split('*')
3475
+ elif ':' in image_size:
3476
+ image_size=image_size.split(':')
3466
3477
  if isinstance(image_size,(list,tuple)) and len(image_size) == 2:
3467
3478
  image_size=','.join([str(i) for i in image_size])
3468
3479
  else:
3469
- #Set it to default image size
3470
- image_size='1920,1080'
3480
+ if not IsIn(image_size,[None,'full','fullscreen','full_screen','auto']):
3481
+ #Set it to default image size
3482
+ image_size='1920,1080'
3471
3483
 
3472
3484
  if Import('import selenium'):
3473
3485
  return False,'Can not install selenium package'
3474
3486
  else:
3487
+ if backup:
3488
+ Import('filecmp')
3489
+ Import('shutil')
3490
+ if capture_type in ['mov','mp4']:
3491
+ Import('cv2',install_name='opencv-python')
3492
+
3493
+ ocr=None
3494
+ if capture_method != 'file':
3495
+ ocr=OCR(enhance=ocr_enhance)
3475
3496
  # Configure Chrome options for headless mode
3476
3497
  from selenium.webdriver.chrome.options import Options
3477
3498
  from selenium.webdriver.common.by import By
@@ -3481,12 +3502,18 @@ def web_capture(url,output_file,image_size='1920,1080',wait_time=3,ignore_certif
3481
3502
  chrome_options.add_argument('--headless') # Run in headless mode
3482
3503
  chrome_options.add_argument('--no-sandbox')
3483
3504
  chrome_options.add_argument('--disable-dev-shm-usage')
3484
- chrome_options.add_argument(f"--window-size={image_size}") # Set window size
3505
+
3506
+ if image_size.lower() not in ['full','fullscreen','full_screen','auto']:
3507
+ chrome_options.add_argument(f"--window-size={image_size}") # Set window size
3508
+ if not gpu:
3509
+ chrome_options.add_argument("--disable-gpu")
3485
3510
  if ignore_certificate_error:
3486
3511
  chrome_options.add_argument('--ignore-certificate-errors') # gnore-certificate-errors
3487
3512
  chrome_options.add_argument('--allow-insecure-localhost') # gnore-certificate-errors
3488
3513
  # Initialize the Chrome driver
3489
3514
  driver = selenium.webdriver.Chrome(options=chrome_options)
3515
+ if image_size.lower() in ['full','fullscreen','full_screen','auto']:
3516
+ driver.maximize_window()
3490
3517
  rc=False,output_file
3491
3518
  try:
3492
3519
  # Navigate to the URL
@@ -3541,20 +3568,186 @@ def web_capture(url,output_file,image_size='1920,1080',wait_time=3,ignore_certif
3541
3568
  next_do_button = driver.find_element(By.XPATH, "//button[@type='submit']")
3542
3569
  next_do_button.click()
3543
3570
 
3544
- # Wait for the page to load
3545
- time.sleep(wait_time)
3571
+ def _capture_(live_capture,driver,output_file,wait_time,capture_method,backup,ocr,log,find_string,daemon,video_file):
3572
+ def wait_body(driver,timeout=10):
3573
+ #wait until get screen data
3574
+ try:
3575
+ selenium.webdriver.support.ui.WebDriverWait(driver,timeout).until(
3576
+ EC.presence_of_element_located((By.TAG_NAME,"body"))
3577
+ )
3578
+ return
3579
+ except:
3580
+ try:
3581
+ selenium.webdriver.support.ui.WebDriverWait(driver,timeout).until(
3582
+ lambda d: d.execute_script("return document.readyState") == "complete"
3583
+ )
3584
+ return
3585
+ except:
3586
+ pass
3587
+ time.sleep(timeout)
3588
+
3589
+ live_capture=Int(live_capture)
3590
+ if not isinstance(wait_time,(int,float)):
3591
+ wait_time=Int(wait_time,10)
3592
+ backup_idx=0
3593
+ if backup:
3594
+ backup=Int(backup,2)
3595
+ if isinstance(live_capture,int) and live_capture > wait_time*2:
3596
+ #Keep capture
3597
+ Time=TIME()
3598
+ if capture_type in ['mov','mp4']:
3599
+ frame_rate=1/wait_time
3600
+ window_size = driver.get_window_size()
3601
+ width = window_size['width']
3602
+ height = window_size['height']
3603
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v') # Codec for MP4
3604
+ video_writer = cv2.VideoWriter(video_file, fourcc, frame_rate, (width, height))
3605
+ while True:
3606
+ if Time.Out(live_capture):
3607
+ driver.quit()
3608
+ if capture_type in ['mov','mp4']:
3609
+ video_writer.release()
3610
+ return True
3611
+ else:
3612
+ #Do something, but not return until timeout. So return False
3613
+ return False
3614
+ # Capture screenshot
3615
+ if log:
3616
+ if IsIn(log,['screen','log','print',print]):
3617
+ printf(Dot(),direct=True)
3618
+ else:
3619
+ printf(Dot(),log=log,direct=True)
3620
+ if backup and capture_type not in ['mov','mp4']:
3621
+ save_file='{}.{}'.format(output_file,backup_idx%backup)
3622
+ else:
3623
+ save_file=output_file
3624
+ #wait
3625
+ wait_body(driver,timeout=wait_time)
3626
+ #capture
3627
+ driver.save_screenshot(save_file)
3628
+ if capture_type in ['mov','mp4']:
3629
+ #Make a video file
3630
+ frame = cv2.imread(save_file)
3631
+ frame = cv2.resize(frame, (width, height))
3632
+ video_writer.write(frame)
3633
+ else:
3634
+ #do something with picture file
3635
+ if backup:
3636
+ if backup == 2:
3637
+ comp_a=f'{output_file}.0'
3638
+ comp_b=f'{output_file}.1'
3639
+ if os.path.isfile(comp_a) and os.path.isfile(comp_b):
3640
+ if filecmp.cmp(comp_a,comp_b):
3641
+ if log:
3642
+ if IsIn(log,['screen','log','print',print]):
3643
+ printf(Dot(),direct=True)
3644
+ else:
3645
+ printf(Dot(),log=log,direct=True)
3646
+ time.sleep(wait_time)
3647
+ backup_idx+=1
3648
+ continue
3649
+ shutil.copy2(save_file,output_file)
3650
+ if IsIn(capture_method,['log','screen','text']):
3651
+ found_words=ocr.Text(image_file=save_file)
3652
+ found_strings=found_space.join(found_words)
3653
+ if IsIn(log,['screen','log','print',print,None]):
3654
+ printf(found_strings,mode='s')
3655
+ else:
3656
+ printf(found_strings,log=log,mode='d')
3657
+ if find_string:
3658
+ if find_string in found_strings:
3659
+ #Find exit string, So True, So True, So True, So True
3660
+ driver.quit()
3661
+ return True
3662
+ backup_idx+=1
3663
+ #capture interval
3664
+ time.sleep(wait_time)
3665
+ else:
3666
+ #Single capture
3667
+ #wait
3668
+ #wait_body(driver,timeout=wait_time)
3669
+ time.sleep(wait_time)
3670
+ #capture
3671
+ driver.save_screenshot(output_file)
3672
+ if IsIn(capture_method,['log','screen','text']):
3673
+ found_words=ocr.Text(image_file=output_file)
3674
+ found_strings=found_space.join(found_words)
3675
+ if IsIn(log,['screen','log','print',print,None]):
3676
+ printf(found_strings,mode='s')
3677
+ else:
3678
+ printf(found_strings,log=log,mode='d')
3679
+ if find_string:
3680
+ if find_string in found_strings:
3681
+ driver.quit()
3682
+ return True
3683
+ driver.quit()
3684
+ if IsIn(capture_method,['text']):
3685
+ return found_strings
3686
+ return True
3687
+
3688
+ ##
3689
+ if IsIn(capture_type,['mov','mp4']):
3690
+ if not video_file:
3691
+ video_file='{}.mp4'.format('.'.join(output_file.split('.')[:-1]))
3692
+
3693
+ #Background running
3694
+ if daemon:
3695
+ t=kThread(target=_capture_, args=(live_capture,driver,output_file,wait_time,capture_method,backup,ocr,log,find_string,daemon,video_file))
3696
+ return t
3697
+ else:
3698
+ #Single process running
3699
+ rc=_capture_(live_capture,driver,output_file,wait_time,capture_method,backup,ocr,log,find_string,daemon,video_file)
3700
+ if IsIn(capture_type,['mov','mp4']):
3701
+ return rc,video_file
3702
+ else:
3703
+ return rc,output_file
3546
3704
 
3547
- # Capture screenshot
3548
- driver.save_screenshot(output_file)
3549
- #print(f"Screenshot saved to {output_file}")
3550
- rc=True,output_file
3551
3705
  except Exception as e:
3552
3706
  #print(f"Error capturing screenshot: {str(e)}")
3553
- rc=False,str(e)
3554
- finally:
3555
- # Close the browser
3556
3707
  driver.quit()
3557
- return rc
3708
+ return False,str(e)
3709
+ # finally:
3710
+ # # Close the browser
3711
+ # driver.quit()
3712
+ # return rc
3713
+
3714
+ class OCR:
3715
+ def __init__(self,image_file=None,enhance=False,language=['en'],gpu=False,model_storage_directory=None,**opts):
3716
+ self.enhance=enhance
3717
+ self.image_file=image_file
3718
+ Import('easyocr')
3719
+ if self.enhance:
3720
+ Import('PIL',install_name='Pillow')
3721
+ Import('numpy')
3722
+ self.reader = easyocr.Reader(language,gpu=gpu,model_storage_directory=model_storage_directory)
3723
+ # Suppress Torch pin_memory warning
3724
+ warnings.filterwarnings("ignore", category=UserWarning, module="torch.utils.data.dataloader")
3725
+
3726
+ # Suppress EasyOCR CPU warning
3727
+ #warnings.filterwarnings("ignore", message="WARNING:easyocr.easyocr:Using CPU. Note: This module is much faster with a GPU.")
3728
+
3729
+ # Suppress NetworkX backend warning
3730
+ warnings.filterwarnings("ignore", category=RuntimeWarning, module="networkx.utils.backends")
3731
+
3732
+ def Text(self,detail=0,low_text=None,contrast_ths=None,image_file=None):
3733
+ if not image_file: image_file=self.image_file
3734
+ if not image_file: return False
3735
+ opts={}
3736
+ opts['detail']=detail
3737
+ if isinstance(low_text,float): opts['low_text']=low_test
3738
+ if isinstance(contrast_ths,float): opts['contrast_ths']=contrast_ths
3739
+ if self.enhance:
3740
+ image = PIL.Image.open(image_file)
3741
+ image = image.convert('L') #Grayscale
3742
+ image = PIL.ImageEnhance.Contrast(image).enhance(3.0) #high contrast
3743
+ image = PIL.ImageEnhance.Sharpness(image).enhance(2.0)#Sharpen
3744
+ image = image.convert('RGB').point(lambda p: 255 if p > 140 else 0) # Adjust threshold if needed
3745
+ # image = image.resize((800, int(800 * image.height / image.width)), PIL.Image.Resampling.LANCZOS)
3746
+ image.save(image_file)
3747
+ # image_np = numpy.array(image)
3748
+ # return self.reader.readtext(image_np,**opts)
3749
+ # else:
3750
+ return self.reader.readtext(image_file,**opts)
3558
3751
 
3559
3752
  ############################################
3560
3753
  #Temporary function map for replacement
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kmisc
3
- Version: 2.1.121
3
+ Version: 2.1.123
4
4
  Summary: Enginering useful library
5
5
  Home-page: https://github.com/kagepark/kmisc
6
6
  Author: Kage Park
@@ -0,0 +1,6 @@
1
+ kmisc/__init__.py,sha256=pu-2QG3sY7W_Vb6eJmpo7Mytvjs4DfaJseGNJN1GmgA,160300
2
+ kmisc-2.1.123.dist-info/LICENSE,sha256=mn9ekhb34HJxsrVhcxrLXJUzy55T62zg-Gh9Ro0mVJI,1066
3
+ kmisc-2.1.123.dist-info/METADATA,sha256=S9rNpdC9R3EUiB9m6p-DZyZcq16Sle34LwxrSzBaYoc,5523
4
+ kmisc-2.1.123.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
5
+ kmisc-2.1.123.dist-info/top_level.txt,sha256=wvdHf5aQTqcGYvxk-F9E_BMWLMhlwC8INBmwO-V6_X4,6
6
+ kmisc-2.1.123.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- kmisc/__init__.py,sha256=uXh4rvX7twUmd9o7TqICr5UCWlAa2i8kzKmpa4BpbSA,150362
2
- kmisc-2.1.121.dist-info/LICENSE,sha256=mn9ekhb34HJxsrVhcxrLXJUzy55T62zg-Gh9Ro0mVJI,1066
3
- kmisc-2.1.121.dist-info/METADATA,sha256=L084X4RVPGQGXITXXVrYSswc1agQNfiKVJRdkDu6S3s,5523
4
- kmisc-2.1.121.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
5
- kmisc-2.1.121.dist-info/top_level.txt,sha256=wvdHf5aQTqcGYvxk-F9E_BMWLMhlwC8INBmwO-V6_X4,6
6
- kmisc-2.1.121.dist-info/RECORD,,