From 03fcb3f7cbb99b92dcf491e3613b32772167306f Mon Sep 17 00:00:00 2001 From: qq_38870145 Date: Tue, 1 Apr 2025 20:53:00 +0800 Subject: [PATCH] Tue Apr 1 20:53:00 CST 2025 inscode --- main.py | 255 ++++++++++++++++++++++++++++++++++++++++++++++++++++- outlook.py | 191 +++++++++++++++++---------------------- 2 files changed, 335 insertions(+), 111 deletions(-) diff --git a/main.py b/main.py index 4c0c135..ad31917 100644 --- a/main.py +++ b/main.py @@ -1 +1,254 @@ -print('欢迎来到 InsCode') \ No newline at end of file +import uvicorn as uvicorn +from fastapi import ( + FastAPI, + Response, +) +from fastapi.middleware.cors import CORSMiddleware +from PIL import Image +import io + +from fastapi.responses import FileResponse + +app = FastAPI() +# 添加 CORS 中间件 +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], # 允许所有来源 + allow_credentials=True, # 允许凭证 + allow_methods=["*"], # 允许所有 HTTP 方法 + allow_headers=["*"], # 允许所有头部 +) +import time,math +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + +import os +from PIL import Image +from time import sleep + +cur_outlook_emai_img_path='' +# cut +cut_img_paths=[] +# full +full_img_paths=[] +def gen_dir(): + cur_timestemp = int(round(time.time() * 1000)) + + dir = './screen_shot/outlook/{ts}'.format(ts=cur_timestemp) + + os.makedirs(dir, exist_ok=True) + return dir +def cut_img(screenshot_path,element,baseDir,loc): + # 获取元素坐标和尺寸 + location = element.location # {x: number, y: number} + size = element.size # {width: number, height: number} + + # 计算裁剪区域 (左, 上, 右, 下) + left = location['x'] + top = location['y'] + right = location['x'] + size['width'] + bottom = location['y'] + size['height'] + + # 使用 Pillow 裁剪图像 + image = Image.open(screenshot_path) + cropped_image = image.crop((left, top, right, bottom)) + cut_file_name=f"{baseDir}/cut_{loc}.png" + cropped_image.save(cut_file_name) + global cut_img_paths + cut_img_paths.append(cut_file_name) + + + +def join_images(png1, png2, size=0, output=f'{dir}/temp_result.png'): + """ + 图片拼接 + :param png1: 图片1 + :param png2: 图片2 + :param size: 两个图片重叠的距离 + :param output: 输出的图片文件 + :return: + """ + size = size * 2 + img1, img2 = Image.open(png1), Image.open(png2) + size1, size2 = img1.size, img2.size + joint = Image.new('RGB', (size1[0], size1[1] + size2[1] - size)) + loc1, loc2 = (0, 0), (0, size1[1] - size) + joint.paste(img1, loc1) + joint.paste(img2, loc2) + joint.save(output) + sleep(.5) + +def vertical_concatenate_with_crop(image_paths, output_path, crop_height=100): + """ + 纵向拼接多图,并对第二张图裁剪指定高度 + :param image_paths: 图片路径列表(按顺序从上到下) + :param output_path: 输出文件路径 + :param crop_height: 第二张图裁剪的高度(默认 100px) + """ + images = [] + + # 读取并处理图片 + for idx, path in enumerate(image_paths): + img = Image.open(path) + if idx >= 1: # 第二张图之后裁剪 + width, height = img.size + # 确保裁剪高度不超出原图范围 + actual_crop = min(crop_height, height) + print('actual_crop',actual_crop) + # 左上 + img = img.crop((0, actual_crop, width, height)) + images.append(img) + + # 计算总高度和最大宽度 + total_height = sum(img.height for img in images) + max_width = max(img.width for img in images) + + # 创建空白画布并拼接 + merged = Image.new('RGB', (max_width, total_height)) + y_offset = 0 + for img in images: + # 居中处理宽度不一致的图片 + x_offset = (max_width - img.width) // 2 + merged.paste(img, (x_offset, y_offset)) + y_offset += img.height + + merged.save(output_path) + + global cur_outlook_emai_img_path + cur_outlook_emai_img_path=output_path +def screen_shot(driver): + global cut_img_paths + # cut + cut_img_paths = [] + global full_img_paths + # full + full_img_paths = [] + dir=gen_dir() + # 当前滚动高度 + scrollTop=driver.execute_script( + 'return document.getElementById("ConversationReadingPaneContainer").childNodes[1].childNodes[0].scrollTop;') + # 可滚动高度范围 + scrollHeight=driver.execute_script( + 'return document.getElementById("ConversationReadingPaneContainer").childNodes[1].childNodes[0].scrollHeight;') + # 渲染的可视区域 + clientHeight=driver.execute_script( + 'return document.getElementById("ConversationReadingPaneContainer").childNodes[1].childNodes[0].clientHeight;') + + print('scrollTop', scrollTop,type(scrollTop)) + print('scrollHeight',scrollHeight) + print('clientHeight', clientHeight) + lastScrollTop=scrollTop + # 次数索引 + i=0 + + # 等待元素加载并可见 + element = WebDriverWait(driver, 10).until( + EC.visibility_of_element_located((By.ID, "ConversationReadingPaneContainer")) + ) + + window_height = driver.execute_script('return window.innerHeight;') + + + if lastScrollTop2 and from_email in mailArr[1] and from_title in mailArr[2]: + # 找到则点击 + trItem.click() + sleep(5) + # 获取控制台日志 + logs = driver.execute_script("return window.logs;") + print("操作日志:", logs) + screen_shot(driver) + break + time.sleep(1) + +def run(from_email='',from_title=''): + global driver + options = webdriver.ChromeOptions() + options.add_experimental_option("detach", True) + # 步骤1获取到的User Data路径 + options.add_argument(r'--user-data-dir=C:\Users\v_bymyma\AppData\Local\Google\Chrome\User Data\Default') + # 步骤2获取到的--profile-directory值 + options.add_argument("--profile-directory=auto_py") + options.add_argument("--disable-web-security") + # driver_path = "C:\\Users\\v_bymyma\PycharmProjects\pythonProject\email\driver\chromedriver.exe" + driver = webdriver.Chrome(options=options) + driver.get('https://outlook.live.com/mail/0/') + mapMSg(from_email,from_title) + time.sleep(3) + driver.quit() + + + + + +# outlook 截图 api /api/outlook_email_img?from_email=1432448610@qq.com&title=字体减半 +@app.get("/api/outlook_email_img") +async def run_click_email(from_email: str, title: str): + try: + if from_email is None or title is None: + return {"code": -1, "msg": '参数from_email title 必填'} + run(from_email, title) + return FileResponse( + cur_outlook_emai_img_path, + media_type="image/png", + headers={"Cache-Control": "public, max-age=604800"} # 7天缓存 + ) + except Exception as e: + return {"code": -1, "msg": str(e)} + + + +# 启动应用 +if __name__ == "__main__": + uvicorn.run(app, host="127.0.0.1", port=9898) + + diff --git a/outlook.py b/outlook.py index ae98300..27d2ea2 100644 --- a/outlook.py +++ b/outlook.py @@ -39,6 +39,61 @@ def cut_img(screenshot_path,element,baseDir,loc): cut_img_paths.append(cut_file_name) + +def join_images(png1, png2, size=0, output=f'{dir}/temp_result.png'): + """ + 图片拼接 + :param png1: 图片1 + :param png2: 图片2 + :param size: 两个图片重叠的距离 + :param output: 输出的图片文件 + :return: + """ + size = size * 2 + img1, img2 = Image.open(png1), Image.open(png2) + size1, size2 = img1.size, img2.size + joint = Image.new('RGB', (size1[0], size1[1] + size2[1] - size)) + loc1, loc2 = (0, 0), (0, size1[1] - size) + joint.paste(img1, loc1) + joint.paste(img2, loc2) + joint.save(output) + sleep(.5) + +def vertical_concatenate_with_crop(image_paths, output_path, crop_height=100): + """ + 纵向拼接多图,并对第二张图裁剪指定高度 + :param image_paths: 图片路径列表(按顺序从上到下) + :param output_path: 输出文件路径 + :param crop_height: 第二张图裁剪的高度(默认 100px) + """ + images = [] + + # 读取并处理图片 + for idx, path in enumerate(image_paths): + img = Image.open(path) + if idx >= 1: # 第二张图之后裁剪 + width, height = img.size + # 确保裁剪高度不超出原图范围 + actual_crop = min(crop_height, height) + print('actual_crop',actual_crop) + # 左上 + img = img.crop((0, actual_crop, width, height)) + images.append(img) + + # 计算总高度和最大宽度 + total_height = sum(img.height for img in images) + max_width = max(img.width for img in images) + + # 创建空白画布并拼接 + merged = Image.new('RGB', (max_width, total_height)) + y_offset = 0 + for img in images: + # 居中处理宽度不一致的图片 + x_offset = (max_width - img.width) // 2 + merged.paste(img, (x_offset, y_offset)) + y_offset += img.height + + merged.save(output_path) def screen_shot(driver): dir=gen_dir() # 当前滚动高度 @@ -101,79 +156,7 @@ def screen_shot(driver): # 8px padding vertical_concatenate_with_crop(cut_img_paths, f'{dir}/result_email.png',crop_height+16) - -def vertical_concatenate_with_crop(image_paths, output_path, crop_height=100): - """ - 纵向拼接多图,并对第二张图裁剪指定高度 - :param image_paths: 图片路径列表(按顺序从上到下) - :param output_path: 输出文件路径 - :param crop_height: 第二张图裁剪的高度(默认 100px) - """ - images = [] - - # 读取并处理图片 - for idx, path in enumerate(image_paths): - img = Image.open(path) - if idx >= 1: # 第二张图之后裁剪 - width, height = img.size - # 确保裁剪高度不超出原图范围 - actual_crop = min(crop_height, height) - print('actual_crop',actual_crop) - # 左上 - img = img.crop((0, actual_crop, width, height)) - images.append(img) - - # 计算总高度和最大宽度 - total_height = sum(img.height for img in images) - max_width = max(img.width for img in images) - - # 创建空白画布并拼接 - merged = Image.new('RGB', (max_width, total_height)) - y_offset = 0 - for img in images: - # 居中处理宽度不一致的图片 - x_offset = (max_width - img.width) // 2 - merged.paste(img, (x_offset, y_offset)) - y_offset += img.height - - merged.save(output_path) -def join_images(png1, png2, size=0, output=f'{dir}/temp_result.png'): - """ - 图片拼接 - :param png1: 图片1 - :param png2: 图片2 - :param size: 两个图片重叠的距离 - :param output: 输出的图片文件 - :return: - """ - size = size * 2 - img1, img2 = Image.open(png1), Image.open(png2) - size1, size2 = img1.size, img2.size - joint = Image.new('RGB', (size1[0], size1[1] + size2[1] - size)) - loc1, loc2 = (0, 0), (0, size1[1] - size) - joint.paste(img1, loc1) - joint.paste(img2, loc2) - joint.save(output) - sleep(.5) - -def run(): - global driver - options = webdriver.ChromeOptions() - options.add_experimental_option("detach", True) - # 步骤1获取到的User Data路径 - options.add_argument(r'--user-data-dir=C:\Users\v_bymyma\AppData\Local\Google\Chrome\User Data\Default') - # 步骤2获取到的--profile-directory值 - options.add_argument("--profile-directory=auto_py") - options.add_argument("--disable-web-security") - # driver_path = "C:\\Users\\v_bymyma\PycharmProjects\pythonProject\email\driver\chromedriver.exe" - driver = webdriver.Chrome(options=options) - driver.get('https://outlook.live.com/mail/0/') - - - mapMSg() - - -def mapMSg(): +def mapMSg(from_email='',from_title=''): time.sleep(5) driver_msg_dom=driver.find_element(By.CLASS_NAME,"customScrollBar") print('driver_msg_dom',driver_msg_dom) @@ -181,51 +164,39 @@ def mapMSg(): driver_tbody_dom=driver_msg_dom.find_elements(By.CLASS_NAME,'EeHm8') print('driver_tbody_dom', driver_tbody_dom) - for trItem in driver_tbody_dom: - print('trItem',trItem) + for trItem in driver_tbody_dom : title=trItem.text print('title',title) - if 'VideoCover' in str(title): - # 找到则点击 VideoCover + print('title arr',title.split('\n')) + mailArr=title.split('\n') + if len(mailArr)>2 and from_email in mailArr[1] and from_title in mailArr[2]: + # 找到则点击 trItem.click() - - - time.sleep(2) - - time.sleep(5) + sleep(5) # 获取控制台日志 logs = driver.execute_script("return window.logs;") print("操作日志:", logs) - # html2canvas = """ - # if(!html2canvas){ - # var s=document.createElement('script'); - # s.src='https://html2canvas.hertzen.com/dist/html2canvas.min.js'; - # document.head.appendChild(s); - # } - # """ - # base64Data = driver.execute_script(html2canvas) - # - # time.sleep(2) - # driver.execute_script(""" - # // 执行截图(推荐配置高清和跨域支持) - # html2canvas(document.getElementById("ConversationReadingPaneContainer").childNodes[1].childNodes[0], { - # scale: 2, // 2倍分辨率防模糊[7](@ref) - # useCORS: true, // 处理跨域图片[2,8](@ref) - # logging: false // 关闭控制台日志 - # }).then(canvas=>{ - # const base64=canvas.toDataURL('image/jpeg', 0.85); - # // 转换为 Base64 JPG - # console.log(base64); - # return base64; - # }) - # """) screen_shot(driver) - # print('base64Data',base64Data) - # email_box=driver.find_element(By.ID,':mt') break time.sleep(1) - driver.quit() + +def run(from_email='',from_title=''): + global driver + options = webdriver.ChromeOptions() + options.add_experimental_option("detach", True) + # 步骤1获取到的User Data路径 + options.add_argument(r'--user-data-dir=C:\Users\v_bymyma\AppData\Local\Google\Chrome\User Data\Default') + # 步骤2获取到的--profile-directory值 + options.add_argument("--profile-directory=auto_py") + options.add_argument("--disable-web-security") + # driver_path = "C:\\Users\\v_bymyma\PycharmProjects\pythonProject\email\driver\chromedriver.exe" + driver = webdriver.Chrome(options=options) + driver.get('https://outlook.live.com/mail/0/') + mapMSg(from_email,from_title) time.sleep(3) - driver.close() + driver.quit() + + + if __name__ == '__main__': - run() \ No newline at end of file + run('1432448610@qq.com','字体减半') \ No newline at end of file -- GitLab