kmisc 2.1.120__tar.gz → 2.1.122__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kmisc
3
- Version: 2.1.120
3
+ Version: 2.1.122
4
4
  Summary: Enginering useful library
5
5
  Home-page: https://github.com/kagepark/kmisc
6
6
  Author: Kage Park
@@ -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,12 +3453,25 @@ 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):
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',find_string=None,found_space='\n',log=None,ocr_enhance=False,daemon=False,backup=False):
3457
+ #auth_fields.submit.type : name : login button with name
3458
+ # : id : login button with id
3459
+ # : submit : submit button without name or id
3460
+ #auth_fields.submit.name : <string>: name or id's submit name string
3461
+ #auth_fields.auth.type : name : username/password with name field
3462
+ # : id : username/password with name id
3463
+ #auth_fields.auth.name : (usernane,password) : username/password field string for name or id
3464
+ #next_do : put data and click submit
3465
+
3452
3466
  if isinstance(image_size,str):
3453
3467
  if 'x' in image_size:
3454
3468
  image_size=image_size.split('x')
3455
3469
  elif ',' in image_size:
3456
3470
  image_size=image_size.split(',')
3471
+ elif '*' in image_size:
3472
+ image_size=image_size.split('*')
3473
+ elif ':' in image_size:
3474
+ image_size=image_size.split(':')
3457
3475
  if isinstance(image_size,(list,tuple)) and len(image_size) == 2:
3458
3476
  image_size=','.join([str(i) for i in image_size])
3459
3477
  else:
@@ -3463,34 +3481,211 @@ def web_capture(url,output_file,image_size='1920,1080',wait_time=3):
3463
3481
  if Import('import selenium'):
3464
3482
  return False,'Can not install selenium package'
3465
3483
  else:
3484
+ if backup:
3485
+ Import('filecmp')
3486
+ Import('shutil')
3487
+
3488
+ ocr=None
3489
+ if capture_method != 'file':
3490
+ ocr=OCR(enhance=ocr_enhance)
3466
3491
  # Configure Chrome options for headless mode
3467
3492
  from selenium.webdriver.chrome.options import Options
3493
+ from selenium.webdriver.common.by import By
3494
+ from selenium.webdriver.support.ui import WebDriverWait
3495
+ from selenium.webdriver.support import expected_conditions as EC
3468
3496
  chrome_options = Options()
3469
3497
  chrome_options.add_argument('--headless') # Run in headless mode
3470
3498
  chrome_options.add_argument('--no-sandbox')
3471
3499
  chrome_options.add_argument('--disable-dev-shm-usage')
3472
3500
  chrome_options.add_argument(f"--window-size={image_size}") # Set window size
3501
+ if not gpu:
3502
+ chrome_options.add_argument("--disable-gpu")
3503
+ if ignore_certificate_error:
3504
+ chrome_options.add_argument('--ignore-certificate-errors') # gnore-certificate-errors
3505
+ chrome_options.add_argument('--allow-insecure-localhost') # gnore-certificate-errors
3473
3506
  # Initialize the Chrome driver
3474
3507
  driver = selenium.webdriver.Chrome(options=chrome_options)
3475
3508
  rc=False,output_file
3476
3509
  try:
3477
3510
  # Navigate to the URL
3478
3511
  driver.get(url)
3479
-
3480
- # Wait for the page to load
3481
- time.sleep(wait_time)
3482
-
3483
- # Capture screenshot
3484
- driver.save_screenshot(output_file)
3485
- #print(f"Screenshot saved to {output_file}")
3486
- rc=True,output_file
3512
+
3513
+ #Login to web page
3514
+ if username and password:
3515
+ wait = WebDriverWait(driver, 10) # Wait up to 10 seconds
3516
+ #Search field name for username,password
3517
+ if auth_fields.get('auth').get('type') == 'id':
3518
+ by_type=By.ID
3519
+ else:
3520
+ by_type=By.NAME
3521
+ username_field = wait.until(EC.presence_of_element_located((by_type, auth_fields.get('auth').get('name')[0])))
3522
+ password_field = driver.find_element(by_type, auth_fields.get('auth').get('name')[1])
3523
+ #login submit
3524
+ if auth_fields.get('submit',{}).get('type') in ['id','name']:
3525
+ if auth_fields.get('submit',{}).get('type') == 'id':
3526
+ by_type=By.ID
3527
+ else:
3528
+ by_type=By.NAME
3529
+ login_button = driver.find_element(by_type, auth_fields.get('submit').get('name'))
3530
+ else: #button submit type
3531
+ login_button = driver.find_element(By.XPATH, "//button[@type='submit']")
3532
+ #put username/password into field
3533
+ username_field.send_keys(username)
3534
+ password_field.send_keys(password)
3535
+ #Login
3536
+ login_button.click()
3537
+
3538
+ if next_do and isinstance(next_do.get('datas'),(list,tuple)):
3539
+ wait = WebDriverWait(driver, 10) # Wait up to 10 seconds
3540
+ for do_i in next_do.get('datas'):
3541
+ if not isinstance(do_i,dict): continue
3542
+ if do_i.get('type') == 'id':
3543
+ do_type=By.ID
3544
+ else:
3545
+ do_type=By.NAME
3546
+ user_do_field = wait.until(EC.presence_of_element_located((do_type, do_i.get('name'))))
3547
+ if do_i.get('click'):
3548
+ user_do_field.click()
3549
+ else:
3550
+ user_do_field.send_keys(do_i.get('data'))
3551
+ #Submit data
3552
+ if next_do.get('type') in ['id','name']:
3553
+ if next_do.get('type') == 'id':
3554
+ by_type=By.ID
3555
+ else:
3556
+ by_type=By.NAME
3557
+ next_do_button = driver.find_element(by_type, next_do.get('name'))
3558
+ else: #button submit type
3559
+ next_do_button = driver.find_element(By.XPATH, "//button[@type='submit']")
3560
+ next_do_button.click()
3561
+
3562
+ def _capture_(live_capture,driver,output_file,wait_time,capture_method,backup,ocr,log,find_string,daemon):
3563
+ def wait_body(driver,timeout=10):
3564
+ #wait until get screen data
3565
+ try:
3566
+ selenium.webdriver.support.ui.WebDriverWait(driver,timeout).until(
3567
+ EC.presence_of_element_located((By.TAG_NAME,"body"))
3568
+ )
3569
+ return
3570
+ except:
3571
+ try:
3572
+ selenium.webdriver.support.ui.WebDriverWait(driver,timeout).until(
3573
+ lambda d: d.execute_script("return document.readyState") == "complete"
3574
+ )
3575
+ return
3576
+ except:
3577
+ pass
3578
+ time.sleep(timeout)
3579
+
3580
+ live_capture=Int(live_capture)
3581
+ wait_time=Int(wait_time,10)
3582
+ backup_idx=0
3583
+ if backup:
3584
+ backup=Int(backup,2)
3585
+ if isinstance(live_capture,int) and live_capture > wait_time*2:
3586
+ Time=TIME()
3587
+ while True:
3588
+ if Time.Out(live_capture):
3589
+ driver.quit()
3590
+ return False
3591
+ # Capture screenshot
3592
+ if log:
3593
+ if log in ['screen','log','print',print]:
3594
+ printf(Dot(),direct=True)
3595
+ else:
3596
+ printf(Dot(),log=log,direct=True)
3597
+ if backup:
3598
+ save_file='{}.{}'.format(output_file,backup_idx%backup)
3599
+ else:
3600
+ save_file=output_file
3601
+ #wait
3602
+ wait_body(driver,timeout=wait_time)
3603
+ #capture
3604
+ driver.save_screenshot(save_file)
3605
+ if backup:
3606
+ if backup == 2:
3607
+ comp_a=f'{output_file}.0'
3608
+ comp_b=f'{output_file}.1'
3609
+ if os.path.isfile(comp_a) and os.path.isfile(comp_b):
3610
+ if filecmp.cmp(comp_a,comp_b):
3611
+ if log:
3612
+ if log in ['screen','log','print',print]:
3613
+ printf(Dot(),direct=True)
3614
+ else:
3615
+ printf(Dot(),log=log,direct=True)
3616
+ time.sleep(wait_time)
3617
+ backup_idx+=1
3618
+ continue
3619
+ shutil.copy2(save_file,output_file)
3620
+ if IsIn(capture_method,['log','screen','text']):
3621
+ found_words=ocr.Text(image_file=save_file)
3622
+ found_strings=found_space.join(found_words)
3623
+ printf(found_strings,log=log,mode='d' if log else 's')
3624
+ if find_string:
3625
+ if find_string in found_strings:
3626
+ driver.quit()
3627
+ return True
3628
+ time.sleep(wait_time)
3629
+ backup_idx+=1
3630
+ else:
3631
+ #wait
3632
+ wait_body(driver,timeout=wait_time)
3633
+ #capture
3634
+ driver.save_screenshot(output_file)
3635
+ driver.quit()
3636
+ if daemon:
3637
+ t=kThread(target=_capture_, args=(live_capture,driver,output_file,wait_time,capture_method,backup,ocr,log,find_string,daemon))
3638
+ return t
3639
+ else:
3640
+ _capture_(live_capture,driver,output_file,wait_time,capture_method,backup,ocr,log,find_string,daemon)
3641
+ return True,output_file
3642
+
3487
3643
  except Exception as e:
3488
3644
  #print(f"Error capturing screenshot: {str(e)}")
3489
- rc=False,str(e)
3490
- finally:
3491
- # Close the browser
3492
3645
  driver.quit()
3493
- return rc
3646
+ return False,str(e)
3647
+ # finally:
3648
+ # # Close the browser
3649
+ # driver.quit()
3650
+ # return rc
3651
+
3652
+ class OCR:
3653
+ def __init__(self,image_file=None,enhance=False,language=['en'],gpu=False,model_storage_directory=None,**opts):
3654
+ self.enhance=enhance
3655
+ self.image_file=image_file
3656
+ Import('easyocr')
3657
+ if self.enhance:
3658
+ Import('PIL',install_name='Pillow')
3659
+ Import('numpy')
3660
+ self.reader = easyocr.Reader(language,gpu=gpu,model_storage_directory=model_storage_directory)
3661
+ # Suppress Torch pin_memory warning
3662
+ warnings.filterwarnings("ignore", category=UserWarning, module="torch.utils.data.dataloader")
3663
+
3664
+ # Suppress EasyOCR CPU warning
3665
+ #warnings.filterwarnings("ignore", message="WARNING:easyocr.easyocr:Using CPU. Note: This module is much faster with a GPU.")
3666
+
3667
+ # Suppress NetworkX backend warning
3668
+ warnings.filterwarnings("ignore", category=RuntimeWarning, module="networkx.utils.backends")
3669
+
3670
+ def Text(self,detail=0,low_text=None,contrast_ths=None,image_file=None):
3671
+ if not image_file: image_file=self.image_file
3672
+ if not image_file: return False
3673
+ opts={}
3674
+ opts['detail']=detail
3675
+ if isinstance(low_text,float): opts['low_text']=low_test
3676
+ if isinstance(contrast_ths,float): opts['contrast_ths']=contrast_ths
3677
+ if self.enhance:
3678
+ image = PIL.Image.open(image_file)
3679
+ image = image.convert('L') #Grayscale
3680
+ image = PIL.ImageEnhance.Contrast(image).enhance(3.0) #high contrast
3681
+ image = PIL.ImageEnhance.Sharpness(image).enhance(2.0)#Sharpen
3682
+ image = image.convert('RGB').point(lambda p: 255 if p > 140 else 0) # Adjust threshold if needed
3683
+ # image = image.resize((800, int(800 * image.height / image.width)), PIL.Image.Resampling.LANCZOS)
3684
+ image.save(image_file)
3685
+ # image_np = numpy.array(image)
3686
+ # return self.reader.readtext(image_np,**opts)
3687
+ # else:
3688
+ return self.reader.readtext(image_file,**opts)
3494
3689
 
3495
3690
  ############################################
3496
3691
  #Temporary function map for replacement
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kmisc
3
- Version: 2.1.120
3
+ Version: 2.1.122
4
4
  Summary: Enginering useful library
5
5
  Home-page: https://github.com/kagepark/kmisc
6
6
  Author: Kage Park
File without changes
File without changes
File without changes
File without changes
File without changes