kmisc 2.1.121__tar.gz → 2.1.123__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.
- {kmisc-2.1.121 → kmisc-2.1.123}/PKG-INFO +1 -1
- {kmisc-2.1.121 → kmisc-2.1.123}/kmisc/__init__.py +208 -15
- {kmisc-2.1.121 → kmisc-2.1.123}/kmisc.egg-info/PKG-INFO +1 -1
- {kmisc-2.1.121 → kmisc-2.1.123}/LICENSE +0 -0
- {kmisc-2.1.121 → kmisc-2.1.123}/README.md +0 -0
- {kmisc-2.1.121 → kmisc-2.1.123}/kmisc.egg-info/SOURCES.txt +0 -0
- {kmisc-2.1.121 → kmisc-2.1.123}/kmisc.egg-info/dependency_links.txt +0 -0
- {kmisc-2.1.121 → kmisc-2.1.123}/kmisc.egg-info/top_level.txt +0 -0
- {kmisc-2.1.121 → kmisc-2.1.123}/pyproject.toml +0 -0
- {kmisc-2.1.121 → kmisc-2.1.123}/setup.cfg +0 -0
- {kmisc-2.1.121 → kmisc-2.1.123}/setup.py +0 -0
@@ -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
|
-
|
3470
|
-
|
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
|
-
|
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
|
-
|
3545
|
-
|
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
|
-
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|