《Python编程快速上手—让繁琐工作自动化》实践项目答案

9.8.3 消除缺失的编号

编写一个程序, 在一个文件夹中, 找到所有带指定前缀的文件, 诸如spam001.txt, spam002.txt 等,并定位缺失的编号( 例如存在 spam001.txt 和 spam003.txt,但不存在 spam002.txt)。让该程序对所有后面的文件改名,消除缺失的编号。

#! python3

import shutil, os, re

def sortFileName(folder):
    # 查找并提取原始文件名路径列表
    originTextFile = []
    for foldername, subfolders, filenames in os.walk(folder):
        for filename in filenames:
            if re.compile(r'^spam(\d){3}\.txt$').search(filename):
                originTextFile.append(os.path.join(foldername, filename))

    # 建立目标序列文件名路径列表
    totalNum = []
    newTextFile = []
    for i in range(1, len(originTextFile) + 1):
        totalNum.append('%03d' % i)
        newTextFile.append(os.path.join(foldername, 'spam' + totalNum[-1] + '.txt'))

    # 对文件改名以消除缺失的编号
    for index in range(0, len(originTextFile)):
        shutil.move(originTextFile[index], newTextFile[index])

    print('Done.')

sortFileName('.')

12.13.1 乘法表

创建程序 multiplicationTable.py,从命令行接受数字 N,在一个 Excel 电子表格
中创建一个 N×N 的乘法表。例如,如果这样执行程序:
py multiplicationTable.py 6
它应该创建一个图 12-11 所示的电子表格。

图 12-11 在电子表格中生成的乘法表

行 1 和列 A 应该用做标签,应该使用粗体。

#! python3

import sys, openpyxl
from openpyxl.styles import Font

n = int(sys.argv[1])
wb = openpyxl.Workbook()
sheet = wb.active
font = Font(bold = True)

for rowNum in range(2, n + 2):
    sheet.cell(row = rowNum, column = 1).font = font
    sheet.cell(row = rowNum, column = 1).value = rowNum - 1
for colNum in range(2, n + 2):
    sheet.cell(row = 1, column = colNum).font = font
    sheet.cell(row = 1, column = colNum).value = colNum - 1
for x in range(2, n + 2):
    for y in range(2, n + 2):
        sheet.cell(row = x, column = y).value = (x - 1) * (y - 1)

wb.save('multiplicationTable.xlsx')
print('Done.')

12.13.2 空行插入程序

创建一个程序 blankRowInserter.py,它接受两个整数和一个文件名字符串作为
命令行参数。我们将第一个整数称为 N,第二个整数称为 M。程序应该从第 N 行开
始,在电子表格中插入 M 个空行。例如,如果这样执行程序:
python blankRowInserter.py 3 2 myProduce.xlsx
执行之前和之后的电子表格,应该如图 12-12 所示。

图 12-12 之前(左边)和之后(右边)在第三行插入两个空行

程序可以这样写:读入电子表格的内容,然后在写入新的电子表格时,利用 for
循环拷贝前面 N 行。对于剩下的行,行号加上 M,写入输出的电子表格。

#! python3

import openpyxl, sys

n = int(sys.argv[1])
m = int(sys.argv[2])
excelFilename = sys.argv[3]

wb = openpyxl.load_workbook(excelFilename)
sheet = wb.active
sheet1 = wb.create_sheet(title = 'Sheet1')
for row in range(1, n):
    for col in range(1, sheet.max_column + 1):
        sheet1.cell(row = row, column = col).value = sheet.cell(row = row, column = col).value
for row in range(n, sheet.max_row + 1):
    for col in range(1, sheet.max_column + 1):
        sheet1.cell(row = row + m, column = col).value = sheet.cell(row = row, column = col).value

wb.save(excelFilename)
print('Done.')

13.6.1 PDF 偏执狂

利用第 9 章的 os.walk()函数编写一个脚本,遍历文件夹中的所有 PDF(包含子文件夹),用命令行提供的口令对这些 PDF 加密。用原来的文件名加上_encrypted.pdf后缀,保存每个加密的 PDF。在删除原来的文件之前,尝试用一个程序读取并解密该文件,确保它被正确的加密。
然后编写一个程序,找到文件夹中所有加密的 PDF 文件(包括它的子文件夹),利用提供的口令,创建 PDF 的解密拷贝。如果口令不对,程序应该打印一条消息,并继续处理下一个 PDF 文件。

#! python3
# 使用方法:python *.py 加密口令

import PyPDF2, os, sys

# 利用os.walk()函数编写一个脚本,遍历文件夹中的所有 PDF(包含子文件夹)
path = 'C:\\folder'  # 文件夹路径
for folderName, subfolders, filenames in os.walk(path):
    for filename in filenames:
        if filename.endswith('.pdf'):

# 用命令行提供的口令对这些 PDF 加密。
            pdfFile = open(folderName + '\\' + filename, 'rb')  # 文件绝对路径
            pdfReader = PyPDF2.PdfFileReader(pdfFile)
            pdfWriter = PyPDF2.PdfFileWriter()
            for pageNum in range(pdfReader.numPages):
                pdfWriter.addPage(pdfReader.getPage(pageNum))
            print('encrypting...')
            pdfWriter.encrypt(sys.argv[1])  # 获取口令并加密

# 用原来的文件名加上_encrypted.pdf后缀,保存每个加密的 PDF。
            resultPdf = open(folderName + '\\' + filename[:-4] + '_encrypted.pdf', 'wb')
            pdfWriter.write(resultPdf)
            resultPdf.close()
            pdfFile.close()

# 在删除原来的文件之前,尝试用一个程序读取并解密该文件,确保它被正确的加密。
            encryptedPdfReader = PyPDF2.PdfFileReader(open(folderName + '\\' + filename[:-4] + '_encrypted.pdf', 'rb'))
            if encryptedPdfReader.isEncrypted and encryptedPdfReader.decrypt(sys.argv[1]):
                print(filename + ' is encrypted.')
                print('deleting... ' + filename)
                os.unlink(folderName + '\\' + filename)
            else:
                print(filename + ' is not encrypted or wrong password.')
        else:
            continue

print('Done.')
#! python3
# 使用方法:python *.py 解密口令

import PyPDF2, os, sys

# 然后编写一个程序,找到文件夹中所有加密的 PDF 文件(包括它的子文件夹)
path = 'C:\\folder'  # 文件夹路径
for folderName, subfolders, filenames in os.walk(path):
    for filename in filenames:
        if filename.endswith('.pdf'):

# 利用提供的口令,创建 PDF 的解密拷贝。
            pdfFile = open(folderName + '\\' + filename, 'rb')  # 文件绝对路径
            pdfReader = PyPDF2.PdfFileReader(pdfFile)
            if pdfReader.isEncrypted:
                if pdfReader.decrypt(sys.argv[1]):
                    print(filename + ' is decrypted.')
                    pdfWriter = PyPDF2.PdfFileWriter()
                    for pageNum in range(pdfReader.numPages):
                        pdfWriter.addPage(pdfReader.getPage(pageNum))
                    resultPdf = open(folderName + '\\' + filename[:-4] + '_decrypted.pdf', 'wb')
                    pdfWriter.write(resultPdf)
                    resultPdf.close()
                    pdfFile.close()

# 如果口令不对,程序应该打印一条消息,并继续处理下一个 PDF 文件。
                else:
                    print('wrong password!')
            else:
                continue

print('Done.')

13.6.3 暴力 PDF 口令破解程序

假定有一个加密的 PDF 文件,你忘记了口令,但记得它是一个英语单词。尝试猜测遗忘的口令是很无聊的任务。作为替代,你可以写一个程序,尝试用所可能的英语单词来解密这个 PDF 文件,直到找到有效的口令。这称为暴力口令攻击。从http://nostarch.com/automatestuff/下载文本文件 dictionary.txt。这个字典文件包含 44000多个英语单词,每个单词占一行。
利用第 8 章学过的文件读取技巧来读取这个文件,创建一个单词字符串的列表。然后循环遍历这个列表中的每个单词,将它传递给 decrypt()方法,如果这个方法返回整数 0,口令就是错的,程序应该继续尝试下一个口令。如果 decrypt()返回 1,程序就应该终止循环,打印出破解的口令。你应该尝试每个单词的大小写形式(在我的笔记本上,遍历来自字典文件的所有 88000 个大小写单词,只要几分钟时间。这就是不应该使用简单英语单词作为口令的原因)。

#! python3

import PyPDF2

def Decrypt(word):
    if pdfReader.decrypt(word):
        print('Password is %s' % word)
        return -1
    elif pdfReader.decrypt(word.lower()):
        print('Password is %s' % word.lower())
        return -1
    else:
        return 0

dictFilePath = 'C:\\dictFilename.txt'  # 字典文件绝对路径
dictFile = open(dictFilePath)
wordList = dictFile.read().split('\n')
dictFile.close()

pdfFilePath = 'C:\\pdfFilename.pdf'  # PDF文件绝对路径
pdfReader = PyPDF2.PdfFileReader(open(pdfFilePath, 'rb'))
if pdfReader.isEncrypted:
    print('Decrypting...')
    for word in wordList:
        if Decrypt(word):
            break
        else:
            continue
else:
    print('This PDF file is not encrypted.')

14.8.1 Excel 到 CSV 的转换程序

Excel 可以将电子表格保存为 CSV 文件,只要点几下鼠标,但如果有几百个 Excel文件要转换为 CSV,就需要点击几小时。利用第 12 章的 openpyxl 模块, 编程读取当前工作目录中的所有 Excel 文件,并输出为 CSV 文件。
一个 Excel 文件可能包含多个工作表,必须为每个表创建一个 CSV 文件。 CSV文件的文件名应该是<Excel 文件名>_<表标题>.csv,其中<Excel 文件名>是没有扩展名的 Excel 文件名(例如'spam_data',而不是'spam_data.xlsx'), <表标题>是Worksheet 对象的 title 变量中的字符串。
http://nostarch.com/automatestuff/下载 ZIP 文件 excelSpreadsheets.zip,将这些电子表格解压缩到程序所在的目录中。可以使用这些文件来测试程序。

#! python3

import openpyxl, csv, os

for excelFile in os.listdir('.'):
    # Skip non-xlsx files, load the workbook object.
    if excelFile.endswith('.xlsx'):
        wb = openpyxl.load_workbook(excelFile)
        for sheetName in wb.sheetnames:
            # Loop through every sheet in the workbook.
            sheet = wb[sheetName]

            # Create the CSV filename from the Excel filename and sheet title.
            csvFile = open(os.path.join(excelFile[:-5] + '_' + sheetName + '.csv'), 'w', newline = '')
            # Create the csv.writer object for this CSV file.
            csvWriter = csv.writer(csvFile)

            # Loop through every row in the sheet.
            for rowNum in range(1, sheet.max_row + 1):
                rowData = []  # append each cell to this list
                # Loop through each cell in the row.
                for colNum in range(1, sheet.max_column + 1):
                    # Append each cell's data to rowData.
                    rowData.append(sheet.cell(row = rowNum, column = colNum).value)
                # Write the rowData list to the CSV file.
                csvWriter.writerow(rowData)
                
            csvFile.close()
print('Done.')

15.12.1 美化的秒表

扩展本章的秒表项目,让它利用 rjust()和 ljust()字符串方法来“美化”的输出。(这些方法在第 6 章中介绍过)。输出不是像这样:

Lap #1: 3.56 (3.56)
Lap #2: 8.63 (5.07)
Lap #3: 17.68 (9.05)
Lap #4: 19.11 (1.43)

…而是像这样:

Lap # 1: 3.56 ( 3.56)
Lap # 2: 8.63 ( 5.07)
Lap # 3: 17.68 ( 9.05)
Lap # 4: 19.11 ( 1.43)

请注意,对于 lapNum、 lapTime 和 totalTime 等整型和浮点型变量,你需要字符串版本,以便对它们调用字符串方法。接下来,利用第 6 章中介绍的 pyperclip 模块,将文本输出复制到剪贴板,以便用户可以将输出快速粘贴到一个文本文件或电子邮件中。

#! python3

import time, pyperclip

# Display the program's instructions.
print('Press ENTER to begin. Afterwards, press ENTER to "click" the stopwatch. Press Ctrl-C to quit.')
input() # press Enter to begin
print('Started.')
startTime = time.time() # get the first lap's start time
lastTime = startTime
lapNum = 1
copyList = []

# Start tracking the lap times.
try:
    while True:
        input()
        lapTime = round(time.time() - lastTime, 2)
        totalTime = round(time.time() - startTime, 2)
        result = 'Lap #%s: %s (%s)' % (str(lapNum).rjust(2), str(totalTime).rjust(6), str(lapTime).rjust(5))
        print(result, end='')
        copyList.append(result)
        lapNum += 1
        lastTime = time.time() # reset the last lap time
except KeyboardInterrupt:
    # Handle the Ctrl-C exception to keep its error message from displaying.
    print('\nDone.')
    pyperclip.copy('\n'.join(copyList))

环境:python3

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,825评论 6 546
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,814评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,980评论 0 384
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 64,064评论 1 319
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,779评论 6 414
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 56,109评论 1 330
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 44,099评论 3 450
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,287评论 0 291
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,799评论 1 338
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,515评论 3 361
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,750评论 1 375
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,221评论 5 365
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,933评论 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,327评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,667评论 1 296
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,492评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,703评论 2 380

推荐阅读更多精彩内容