update: driver proper exit
This commit is contained in:
74
邮件批量发送.py
74
邮件批量发送.py
@@ -4,14 +4,17 @@ import pandas
|
|||||||
import time
|
import time
|
||||||
import wx
|
import wx
|
||||||
|
|
||||||
from selenium import webdriver
|
|
||||||
from selenium.common.exceptions import StaleElementReferenceException, TimeoutException
|
from selenium.common.exceptions import StaleElementReferenceException, TimeoutException
|
||||||
|
from selenium.webdriver import Chrome, ChromeOptions
|
||||||
from selenium.webdriver.common.action_chains import ActionChains
|
from selenium.webdriver.common.action_chains import ActionChains
|
||||||
from selenium.webdriver.common.by import By
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.common.keys import Keys
|
||||||
from selenium.webdriver.support import expected_conditions as EC
|
from selenium.webdriver.support import expected_conditions as EC
|
||||||
from selenium.webdriver.support.wait import WebDriverWait
|
from selenium.webdriver.support.wait import WebDriverWait
|
||||||
from selenium.webdriver.remote.webelement import WebElement
|
from selenium.webdriver.remote.webelement import WebElement
|
||||||
|
from selenium.webdriver.remote.webdriver import WebDriver
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from zoneinfo import ZoneInfo
|
from zoneinfo import ZoneInfo
|
||||||
@@ -71,20 +74,7 @@ greetings = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
def main():
|
def main(driver: WebDriver):
|
||||||
try:
|
|
||||||
print('[信息] 程序初始化中...')
|
|
||||||
app = wx.App(None)
|
|
||||||
|
|
||||||
print('[信息] 正在启动 Chrome 自动化实例')
|
|
||||||
opts = webdriver.ChromeOptions()
|
|
||||||
opts.add_experimental_option("excludeSwitches", ["enable-logging"])
|
|
||||||
driver = webdriver.Chrome(opts)
|
|
||||||
driver.set_page_load_timeout(args.timeout)
|
|
||||||
except Exception as e:
|
|
||||||
print(f'[!!!!] 初始化时发生了错误:{e}')
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def locate(selector, condition=EC.presence_of_element_located, parent=driver) -> WebElement:
|
def locate(selector, condition=EC.presence_of_element_located, parent=driver) -> WebElement:
|
||||||
for attempt in range(args.retry):
|
for attempt in range(args.retry):
|
||||||
try:
|
try:
|
||||||
@@ -122,10 +112,6 @@ def main():
|
|||||||
except TimeoutException: continue
|
except TimeoutException: continue
|
||||||
except: break
|
except: break
|
||||||
|
|
||||||
def keyin(element: WebElement, value):
|
|
||||||
try: element.send_keys(value)
|
|
||||||
except: driver.execute_script(f"arguments[0].value = arguments[1];", element, value)
|
|
||||||
|
|
||||||
def ready(driver, predicate):
|
def ready(driver, predicate):
|
||||||
try:
|
try:
|
||||||
wait = WebDriverWait(driver, timeout=args.timeout)
|
wait = WebDriverWait(driver, timeout=args.timeout)
|
||||||
@@ -247,7 +233,7 @@ def main():
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
subject = locate("h1.subject").text.strip()
|
subject = locate("h1.subject").text.strip()
|
||||||
sender = locate("header div.from").text[6:].replace('\n', ' ').strip()
|
sender = locate("header div.from").text[6:].replace('\n', ' ').strip().lstrip('<').rstrip('>')
|
||||||
print(f'[信息] 已读取邮件:{subject}')
|
print(f'[信息] 已读取邮件:{subject}')
|
||||||
print(f'[信息] 指定发件人:{sender}')
|
print(f'[信息] 指定发件人:{sender}')
|
||||||
|
|
||||||
@@ -255,14 +241,22 @@ def main():
|
|||||||
print(f'[警告] 检测到发件人与设定不一致')
|
print(f'[警告] 检测到发件人与设定不一致')
|
||||||
print(f'[信息] 提示:请检查邮件是否正确')
|
print(f'[信息] 提示:请检查邮件是否正确')
|
||||||
|
|
||||||
|
class Status(Enum):
|
||||||
|
ACTIVE = 0
|
||||||
|
INACTIVE = 1
|
||||||
|
TERMINATED = 3
|
||||||
|
|
||||||
|
def isalive(self): return self != Status.TERMINATED
|
||||||
|
def isactive(self): return self == Status.ACTIVE
|
||||||
|
|
||||||
global date
|
global date
|
||||||
date = datetime.now()
|
date = datetime.now()
|
||||||
|
|
||||||
index = 0
|
index = 0
|
||||||
active = True
|
status = Status.ACTIVE
|
||||||
occurrences = {}
|
occurrences = {}
|
||||||
|
|
||||||
while active and index < limit:
|
while status.isactive() and index < limit:
|
||||||
global warnings
|
global warnings
|
||||||
global errors
|
global errors
|
||||||
global sent
|
global sent
|
||||||
@@ -288,7 +282,7 @@ def main():
|
|||||||
warnings += 1
|
warnings += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
while active:
|
while status.isactive():
|
||||||
try:
|
try:
|
||||||
clean = True
|
clean = True
|
||||||
attempt += 1
|
attempt += 1
|
||||||
@@ -337,12 +331,12 @@ def main():
|
|||||||
|
|
||||||
# 填入收件人
|
# 填入收件人
|
||||||
click(wrapper)
|
click(wrapper)
|
||||||
keyin(to, recipient)
|
to.send_keys(recipient + Keys.ENTER)
|
||||||
|
|
||||||
if to.get_attribute('value') != recipient:
|
if to.get_attribute('value') != recipient:
|
||||||
print(f'[警告] ({attempt}) 检测到收件人地址不正确,正在重试...')
|
print(f'[警告] ({attempt}): 检测到收件人地址不正确,正在重试...')
|
||||||
elif not clean:
|
elif not clean:
|
||||||
print(f'[警告] ({attempt}) 检测到邮件内容不正确,正在重试...')
|
print(f'[警告] ({attempt}): 检测到邮件内容不正确,正在重试...')
|
||||||
else:
|
else:
|
||||||
# 发送邮件
|
# 发送邮件
|
||||||
click("div.io-ox-mail-compose-window button[data-action='send']")
|
click("div.io-ox-mail-compose-window button[data-action='send']")
|
||||||
@@ -381,15 +375,15 @@ def main():
|
|||||||
break
|
break
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print('[信息] 程序中断')
|
print('[信息] 程序中断')
|
||||||
active = False
|
status = Status.TERMINATED
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'[警告] 发生错误:{e}')
|
print(f'[警告] ({attempt}): 发生错误:{e}')
|
||||||
|
|
||||||
key = input('[????] 重试 (r) / 跳过 (s) / 取消 (C): ')
|
key = input('[????] 重试 (r) / 跳过 (s) / 取消 (C): ')
|
||||||
if key in ['R', 'r']: continue
|
if key in ['R', 'r']: continue
|
||||||
elif key in ['S', 's']: break
|
elif key in ['S', 's']: break
|
||||||
else: active = False
|
else: status = Status.INACTIVE
|
||||||
|
|
||||||
progress = index / limit * 100
|
progress = index / limit * 100
|
||||||
print('[信息] 当前进度:%.2f %%' % progress)
|
print('[信息] 当前进度:%.2f %%' % progress)
|
||||||
@@ -401,13 +395,29 @@ def main():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'[警告] 写入文件时发生了错误:{e}')
|
print(f'[警告] 写入文件时发生了错误:{e}')
|
||||||
|
|
||||||
if active and input('[????] 继续运行 (c) / 退出程序 (W): ') in ['C', 'c']: continue
|
if status.isalive() and input('[????] 继续运行 (c) / 退出程序 (W): ') in ['C', 'c']: continue
|
||||||
else: break
|
else: break
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
try: status = main()
|
try:
|
||||||
except KeyboardInterrupt: status = 145
|
print('[信息] 程序初始化中...')
|
||||||
|
app = wx.App(None)
|
||||||
|
|
||||||
|
print('[信息] 正在启动 Chrome 自动化实例')
|
||||||
|
opts = ChromeOptions()
|
||||||
|
opts.add_experimental_option("excludeSwitches", ["enable-logging"])
|
||||||
|
driver = Chrome(opts)
|
||||||
|
driver.set_page_load_timeout(args.timeout)
|
||||||
|
status = main(driver)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print('[信息] 程序中断')
|
||||||
|
status = 145
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[!!!!] 致命错误:{e}')
|
||||||
|
status = 1
|
||||||
|
finally:
|
||||||
|
driver.quit()
|
||||||
|
|
||||||
print(f'[信息] 已发送 {sent} 封;发送失败 {errors} 封;跳过重复项 {warnings} 个')
|
print(f'[信息] 已发送 {sent} 封;发送失败 {errors} 封;跳过重复项 {warnings} 个')
|
||||||
print(f'[信息] 总耗时 {str(datetime.now() - date)}')
|
print(f'[信息] 总耗时 {str(datetime.now() - date)}')
|
||||||
|
|||||||
Reference in New Issue
Block a user