Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
yma16
auto_python
提交
03fcb3f7
A
auto_python
项目概览
yma16
/
auto_python
与 Fork 源项目一致
Fork自
inscode / Python
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
auto_python
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
03fcb3f7
编写于
4月 01, 2025
作者:
Q
qq_38870145
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Tue Apr 1 20:53:00 CST 2025 inscode
上级
aa1e04bd
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
335 addition
and
111 deletion
+335
-111
main.py
main.py
+254
-1
outlook.py
outlook.py
+81
-110
未找到文件。
main.py
浏览文件 @
03fcb3f7
print
(
'欢迎来到 InsCode'
)
import
uvicorn
as
uvicorn
\ No newline at end of file
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
lastScrollTop
<
scrollHeight
:
img_path
=
f
'
{
dir
}
/custom_
{
i
}
.png'
driver
.
save_screenshot
(
img_path
)
cut_img
(
img_path
,
element
,
dir
,
i
)
full_img_paths
.
append
(
img_path
)
# 滚动底部 + 渲染高度 翻页滚动
while
math
.
ceil
(
lastScrollTop
+
1
)
<
scrollHeight
:
end_rect_top
=
driver
.
execute_script
(
'return document.querySelector(".g4Y3U").getBoundingClientRect().top;'
)
sleep
(.
5
)
# end 结束 节点出现在可视区域 dom rect top<window height
if
end_rect_top
<
window_height
:
break
i
+=
1
# 加渲染高度 翻页 好拼接
lastScrollTop
+=
clientHeight
driver
.
execute_script
(
'document.getElementById("ConversationReadingPaneContainer").childNodes[1].childNodes[0].scrollTop={scrollTop}'
.
format
(
scrollTop
=
lastScrollTop
))
sleep
(.
5
)
img_path
=
f
'
{
dir
}
/custom_
{
i
}
.png'
driver
.
save_screenshot
(
img_path
)
cut_img
(
img_path
,
element
,
dir
,
i
)
full_img_paths
.
append
(
img_path
)
else
:
# 完整email
img_path
=
f
'
{
dir
}
/full_screen_email.png'
driver
.
save_screenshot
(
img_path
)
# 裁剪顶部高度 渲染高度
crop_height
=
driver
.
execute_script
(
'return document.getElementById("ConversationReadingPaneContainer").firstChild.offsetHeight;'
)
# 8px padding
vertical_concatenate_with_crop
(
cut_img_paths
,
f
'
{
dir
}
/result_email.png'
,
crop_height
+
16
)
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
)
print
(
'driver_doms'
,
driver_msg_dom
)
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
:
title
=
trItem
.
text
print
(
'title'
,
title
)
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
()
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
)
outlook.py
浏览文件 @
03fcb3f7
...
@@ -39,6 +39,61 @@ def cut_img(screenshot_path,element,baseDir,loc):
...
@@ -39,6 +39,61 @@ def cut_img(screenshot_path,element,baseDir,loc):
cut_img_paths
.
append
(
cut_file_name
)
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
):
def
screen_shot
(
driver
):
dir
=
gen_dir
()
dir
=
gen_dir
()
# 当前滚动高度
# 当前滚动高度
...
@@ -101,79 +156,7 @@ def screen_shot(driver):
...
@@ -101,79 +156,7 @@ def screen_shot(driver):
# 8px padding
# 8px padding
vertical_concatenate_with_crop
(
cut_img_paths
,
f
'
{
dir
}
/result_email.png'
,
crop_height
+
16
)
vertical_concatenate_with_crop
(
cut_img_paths
,
f
'
{
dir
}
/result_email.png'
,
crop_height
+
16
)
def
mapMSg
(
from_email
=
''
,
from_title
=
''
):
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
():
time
.
sleep
(
5
)
time
.
sleep
(
5
)
driver_msg_dom
=
driver
.
find_element
(
By
.
CLASS_NAME
,
"customScrollBar"
)
driver_msg_dom
=
driver
.
find_element
(
By
.
CLASS_NAME
,
"customScrollBar"
)
print
(
'driver_msg_dom'
,
driver_msg_dom
)
print
(
'driver_msg_dom'
,
driver_msg_dom
)
...
@@ -181,51 +164,39 @@ def mapMSg():
...
@@ -181,51 +164,39 @@ def mapMSg():
driver_tbody_dom
=
driver_msg_dom
.
find_elements
(
By
.
CLASS_NAME
,
'EeHm8'
)
driver_tbody_dom
=
driver_msg_dom
.
find_elements
(
By
.
CLASS_NAME
,
'EeHm8'
)
print
(
'driver_tbody_dom'
,
driver_tbody_dom
)
print
(
'driver_tbody_dom'
,
driver_tbody_dom
)
for
trItem
in
driver_tbody_dom
:
for
trItem
in
driver_tbody_dom
:
print
(
'trItem'
,
trItem
)
title
=
trItem
.
text
title
=
trItem
.
text
print
(
'title'
,
title
)
print
(
'title'
,
title
)
if
'VideoCover'
in
str
(
title
):
print
(
'title arr'
,
title
.
split
(
'
\n
'
))
# 找到则点击 VideoCover
mailArr
=
title
.
split
(
'
\n
'
)
if
len
(
mailArr
)
>
2
and
from_email
in
mailArr
[
1
]
and
from_title
in
mailArr
[
2
]:
# 找到则点击
trItem
.
click
()
trItem
.
click
()
sleep
(
5
)
time
.
sleep
(
2
)
time
.
sleep
(
5
)
# 获取控制台日志
# 获取控制台日志
logs
=
driver
.
execute_script
(
"return window.logs;"
)
logs
=
driver
.
execute_script
(
"return window.logs;"
)
print
(
"操作日志:"
,
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
)
screen_shot
(
driver
)
# print('base64Data',base64Data)
# email_box=driver.find_element(By.ID,':mt')
break
break
time
.
sleep
(
1
)
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
)
time
.
sleep
(
3
)
driver
.
close
()
driver
.
quit
()
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
run
()
run
(
'1432448610@qq.com'
,
'字体减半'
)
\ No newline at end of file
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录