转自:www.cnblogs.com/Yinkaisheng/p/4820954.html
今天下载了一个英文pdf书籍,但书签全是大写英文字母,看上去有点别扭,于是想办法用自动化重命名pdf书签,
使书签全部变成首字母大写。
pdf原始书签如下图:
重命名后的pdf书签
自动化动态效果图,两三分钟完成重命名工作。
下面介绍下自动化过程。
automation.py是我封装的python调用UIAutomation的module,参考 http://www.cnblogs.com/Yinkaisheng/p/3444132.html
运行automation.py -h查看帮助
先使用automation.py -a 获取pdf书签树控件的层次结构,-a参数 是获取光标下的控件,并一直获取父控件直到顶层窗口
在cmd里输入automation.py -a回车后,马上把鼠标移到pdf书签上,3秒后,将打印出控件树
再用此方法获取右键pdf书签右键菜单的控件树层次结构。
最后代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#!python3
# -*- coding: utf-8 -*-
# rename pdf bookmarks with FoxitReader 6.2.3
import
time
import
string
import
automation
TreeDepth
=
2
#书签树只有前两层需要重命名
UpperWords
=
{
'amd'
:
'AMD'
,
'arp'
:
'ARP'
,
'dhcp'
:
'DHCP'
,
'dns'
:
'DNS'
,
'ip'
:
'IP'
,
'mac'
:
'MAC'
,
'unix'
:
'UNIX'
,
'pc'
:
'PC'
,
'pcs'
:
'PCs'
,
'tcp'
:
'TCP'
,
'tcp/ip'
:
'TCP/IP'
,
'vs'
:
'VS'
,
}
LowerWords
=
[
'a'
,
'an'
,
'and'
,
'at'
,
'for'
,
'in'
,
'of'
,
'the'
,
'to'
]
class
BookMark():
def
__init__(
self
, name, newName):
self
.name
=
name
self
.newName
=
newName
self
.children
=
[]
def
main():
window
=
automation.WindowControl(searchDepth
=
1
, ClassName
=
'classFoxitReader'
)
window.SetActive()
time.sleep(
1
)
tree
=
automation.TreeControl(searchFromControl
=
window, ClassName
=
'SysTreeView32'
)
childItems
=
tree.GetChildren()
bookMarks
=
[]
depth
=
1
for
treeItem
in
childItems:
if
treeItem.ControlType
=
=
automation.ControlType.TreeItemControl:
RenameTreeItem(tree, treeItem, bookMarks, depth)
fout
=
open
(
'rename_pdf_bookmark.txt'
,
'wt'
, encoding
=
'utf-8'
)
depth
=
1
for
bookMark
in
bookMarks:
DumpBookMark(fout, bookMark, depth)
fout.close()
def
DumpBookMark(fout, bookMark, depth):
fout.write(
' '
*
(depth
-
1
)
*
4
+
bookMark.newName
+
'\n'
)
for
child
in
bookMark.children:
DumpBookMark(fout, child, depth
+
1
)
def
RenameTreeItem(tree, treeItem, bookMarks, depth):
treeItem.ScrollIntoView()
if
depth > TreeDepth:
return
name
=
treeItem.Name
newName
=
Rename(name)
bookMark
=
BookMark(name, newName)
bookMarks.append(bookMark)
if
newName !
=
name:
treeItem.RightClick()
# FoxitReader书签右键菜单(BCGPToolBar,非Windows菜单)弹出后,枚举不到菜单,但从屏幕点上ControlFromPoint能获取到菜单, todo
# 采用特殊处理获取重命名菜单
time.sleep(
0.2
)
x, y
=
automation.Win32API.GetCursorPos()
menuItem
=
automation.ControlFromPoint(x
+
2
, y
+
2
)
if
menuItem.ControlType
=
=
automation.ControlType.MenuItemControl:
#鼠标右下方弹出菜单
while
not
(menuItem.Name
=
=
'重命名(R)'
or
menuItem.Name
=
=
'Rename'
):
y
+
=
20
menuItem
=
automation.ControlFromPoint(x
+
2
, y)
else
:
#鼠标右上方弹出菜单
menuItem
=
automation.ControlFromPoint(x
+
2
, y
-
2
)
while
not
(menuItem.Name
=
=
'重命名(R)'
or
menuItem.Name
=
=
'Rename'
):
y
-
=
20
menuItem
=
automation.ControlFromPoint(x
+
2
, y)
menuItem.Click()
edit
=
automation.EditControl(searchFromControl
=
tree, searchDepth
=
1
)
edit.SetValue(newName)
automation.Win32API.SendKeys(
'{Enter}'
)
print
(
'rename "{0}" to "{1}"'
.
format
(name, newName))
if
depth
+
1
> TreeDepth:
return
treeItem.Expand()
childItems
=
treeItem.GetChildren()
if
childItems:
treeItem.Expand()
for
child
in
childItems:
RenameTreeItem(tree, child, bookMark.children, depth
+
1
)
def
Rename(name):
newName
=
name.strip().replace(
'\n'
,
' '
)
#将CHAPTER 10变成10,删除前置CHAPTER
if
newName.startswith(
'CHAPTER '
):
newName
=
newName[
len
(
'CHAPTER '
):]
newName
=
newName.title()
words
=
newName.split()
skipIndex
=
1
if
words[
0
][
-
1
].isdigit()
else
0
for
i
in
range
(
len
(words)):
lowerWord
=
words[i].lower()
start_punctuation
=
''
end_punctuation
=
''
if
lowerWord[
0
]
in
string.punctuation:
start_punctuation
=
lowerWord[
0
]
lowerWord
=
lowerWord[
1
:]
if
lowerWord[
-
1
]
in
string.punctuation:
end_punctuation
=
lowerWord[
-
1
]
lowerWord
=
lowerWord[:
-
1
]
if
lowerWord
in
UpperWords:
words[i]
=
start_punctuation
+
UpperWords[lowerWord]
+
end_punctuation
continue
if
i > skipIndex
and
lowerWord
in
LowerWords:
if
words[i
-
1
][
-
1
] !
=
':'
:
words[i]
=
lowerWord
newName
=
' '
.join(words)
return
newName
if
__name__
=
=
'__main__'
:
main()
input
(
'\npress enter to exit'
)
|
代码可在https://git.oschina.net/yinkaisheng/PythonUIAutomation4Windows 或 GitHub下载
另外此代码是根据FoxReader6.2.3实现的,其它版本不一定支持。
还有运行此程序时要关闭迅雷,在测试时发现如果运行了迅雷,会使pdf右键菜单获取有问题。