使用automation.py自动化重命名pdf书签,使全大写字母变成首字母大写

今天下载了一个英文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书签右键菜单的控件树层次结构。

最后代码如下:

#!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‘)

  代码可在GitHub下载

另外此代码是根据FoxReader6.2.3实现的,其它版本不一定支持。

还有运行此程序时要关闭迅雷,在测试时发现如果运行了迅雷,会使pdf右键菜单获取有问题。

时间: 2024-08-08 22:06:29

使用automation.py自动化重命名pdf书签,使全大写字母变成首字母大写的相关文章

提取论文标题并自动重命名pdf文件

在我们确定一个研究课题之后,我们总是会先下载一堆相关的paper,看看这个领域现在已经做到一个什么地步,也看看别人是怎么做的,后面自己写paper的时候可以参考参考.当我们把相关的文章都下载到一个文件夹之后,有一个问题,一般我们从IEEE或是ACM相关站点下载的PDF文件的文件名不是相应文章的标题.我们希望文件名尽量能够反映文件的主要内容,文章的标题显然是最能概括文张内容的.昨天上午,一个小时的时间就花在把下载下来的文件重命名上了.因为太费时间,想自己写个简单的小程序来完成这个工作.上网一找,嗬

重命名PDF打印文件名

Odoo系统默认打印出来的PDF文件都是以当前文档模型对象对应的模板文件名命名的,对用户来说,这样的命名很不友好. 我们希望能够将打印出来的文件名以单号命名,下面是实现这种目的的方法. 在report_download的controller中,将对应的文件名用单据的名称替换掉即可 response.headers.add('Content-Disposition', 'attachment; filename=%s.pdf;' % filename)

C# rename方法重命名文件

记得C# File类中是没有rename这个方法 所以网上很多都用的是move moveTo copy+delete等这些方法 其实以上的方法 虽然可以实现功能 但看起来总觉得很蛋疼 今天百度 突然发现了一个正宗的解决方案 仔细回想 vb.net中有My.Computer.FileSystem.RenameFile这个方法 但是在C#中如何使用呢?? 其实很简单 只需以下几步 1.先添加引用:Microsoft.VisualBasic,再加上using Microsoft.VisualBasic

C# 重命名文件 (正宗的方法)

突然想起这个问题 所以就思考一下 记得C# File类中是没有rename这个方法 所以网上很多都用的是move moveTo copy+delete等这些方法 其实以上的方法 虽然可以实现功能 但看起来总觉得很蛋疼 今天百度 突然发现了一个正宗的解决方案 仔细回想 vb.net中有My.Computer.FileSystem.RenameFile这个方法 但是在C#中如何使用呢?? 其实很简单 只需以下几步 1.先添加引用:Microsoft.VisualBasic,再加上using Micr

C# 文件重命名

记得C# File类中是没有rename这个方法 所以网上很多都用的是move moveTo copy+delete等这些方法 其实以上的方法 虽然可以实现功能 但看起来总觉得很蛋疼 今天百度 突然发现了一个正宗的解决方案 仔细回想 vb.NET中有My.Computer.FileSystem.RenameFile这个方法 但是在C#中如何使用呢?? 其实很简单 只需以下几步 1.先添加引用:Microsoft.VisualBasic,再加上using Microsoft.VisualBasic

Python脚本的实现文件重命名

第一次尝试用python写一个完整有用的程序,这个脚本实现了能把当前文件的指定文件按一定顺序进行重新命名,还是有一定的适用价值 下面贴代码 #coding:utf-8import osperfix='test' #perfix为重命名后的文件起始字符length=2 #length为除去perfix后,文件名要达到的长度base=1 #文件名的起始数format='txt' #文件的后缀#函数PadLeft将文件名补全到指定长度#str为将要补全的字符#num为要达到的长度#padstr 为达到

批量重命名

# -*- coding:utf-8 -*- #python 2.7 #XiaoDeng #批量重命名文件 import os #抓取py当前目录 path=os.getcwd() for file in os.listdir(path): #使用os.listdir()函数获得指定目录中的内容 if 'apk' in file: if "a_signed_zipalign" in file:#多了一层逻辑,暂时先不管 RenameFile=file.replace("a_s

linux下rename用法--批量重命名

Linux的rename 命令有两个版本,一个是C语言版本的,一个是Perl语言版本的,早期的Linux发行版基本上使用的是C语言版本的,现在已经很难见到C语言版本的了, 由于历史原因,在Perl语言大红大紫的时候,Linux的工具开发者们信仰Perl能取代C,所以大部分工具原来是C版本的都被Perl改写了,因为 Perl版本的支持正则处理,所以功能更加强大,已经不再需要C语言版本的了.   1.如何区分系统里的rename命令是哪个版本的?   输入man rename 看到第一行是 RENA

Java 单文件下载及重命名

代码(仅供参考): 1 /* 2 * 另存为 3 */ 4 @RequestMapping("/saveAs.do") 5 public @ResponseBody void saveAs(String filePath,String fileName){ 6 7 try { 8 File file=new File(filePath); 9 //设置文件MIME类型 10 getResponse().setContentType(getMIMEType(file)); 11 //设置