类和对象

继续打磨PythonABC的教材中,下一个选题还没有敲定,暂时没精力帮忙网友们查找修改程序中的错误,见谅。

这个整理、审视、增补和纠错的过程收获很多,每修改一稿交上去时都很有成就感,因为感觉在越变越好。就算自知水平有限,也希望能把教程写到能力范围内的最好,还可以完成教程+视频+网站的闭环。

下一个选题考虑过joomla建网站和爬虫,多谢网友赵会钧分享的爬虫资料????。对爬虫越了解越觉得尺度不好把握,本来计划讲普通人的爬虫,浅浅地介绍够用就好,但以现在的反爬措施,不深入讲绕不过爬之前的重重障碍。有很多优秀的教学视频教我们如何在不引起网站反感和爬得到有用的数据之间压跷跷板,有兴趣的朋友可以自己去找。了解爬虫这门技术很有帮助,我学到的那点爬虫知识就自己用啦。joomla因为跳出python的势力范围,也暂时放一放。我大概已经想清楚接下来努力的方向,等深入研究确定下来会写相关的帖子。

回到PythonABC的基础编程,之前的帖子介绍在写这本基础教程为了出word那一章的思考题,想到可以在python-docx模块帮助下自动汇总作家作品及相关材料,生成图文并茂的word文档。以鲁迅先生的材料为例,先建一个鲁迅的文件夹,里面放鲁迅先生作品的段摘抄和跟作品相关的图片。任务是写一个程序,把这些原始素材组织起来自动编辑排版成图文表格俱全、字体格式都看着顺眼的word文档。详细见:3.2.2 自动汇总材料生成word文档并编辑和排版

因为“word文档也沦陷了”这一章是放过类和对象这一章之前,所以用的是面向过程的开发手法,平铺直叙把程序写完的。后面又做了些小小的修改,PythonABC网站-->应用实例-->word文件-->3.2.2 自动汇总材料生成word文档并编辑和排版 里的代码是修改过的。

学完类和对象后试着用类和对象来实现同样功能,在实际动手的过程中会更实际地体会到对面向对象相较于面向过程的设计和开发方面的优势。我还有个意外的收获就是对对象方法函数、类方法函数和静态方法函数的理解加深啦

继续这个例子,汇总材料生成word文档两个关键字是“汇总”和"word",所以我们建两个类来应对这两个关键字:Writer类负责把散落到各个文件的材料集中起来,即应对“汇总”,这个类注重的是提取作家的作品和图片。novelCollection负责生成word文档,即应对“word”,这个类关心的是往word文档里加段落加表格加图片设字体中间对齐。

from docx import Document					# 操控word
from docx.enum.table import WD_TABLE_ALIGNMENT			# 表格居中
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT		# 标题居中
from docx.shared import Cm					# 图片尺寸
from docx.oxml.ns import qn					# 设置中文字体用
from pathlib import Path					# 路径设置

class Writer():

    def __init__(self, name):
        self.name = name
        self.currentFolder = Path(name)
        self.novelCharacter = {}
        self.novelQuote = {}
        self.novelPic = {}
        self.getElem()

    def getElem(self):

        listFile = self.currentFolder.joinpath('list.txt')

        fileObj = listFile.open(encoding='utf-8')

        dataLine = fileObj.readline()  # 读出一行

        while dataLine:  # 读出内容为空,说明到了文章尾

            novel, character = dataLine.split()  # 从索引中获取作品和人物

            self.novelCharacter.setdefault(novel, character)  # 作品和人物对应起来

            for f in self.currentFolder.glob(novel + '.*'):  
            # 从作品名搜作品内容和作品的相关图片
                if f.suffix == '.txt':  # 作品内容放在txt文档
                    with f.open(encoding='utf-8') as qObj:  
                    # 打开文章内容文件,按段落放进列表
                        paragraphs = qObj.read().split('\n')
                        self.novelQuote.setdefault(novel, paragraphs)
                else:  # 图片文件
                    self.novelPic.setdefault(novel, str(f))  
                    # 作品和相关图像的位置字串

            dataLine = fileObj.readline()

class novelCollection():

    def __init__(self, author):
        self.title = author.name + '小说及人物'       # word文档的标题
        self.tableContent = author.novelCharacter   # 与小说对应的人物
        self.paragraphs = author.novelQuote         # 从小说中摘取的段落
        self.pictures = author.novelPic             # 跟小说对应的的图片
        self.filename = author.name + '.docx'       # 保存的word文档的文件名

    def launch(self):

        docObj = Document()                         # 整个word文档的标题
        docObj.add_heading(self.title, level=0).alignment = WD_PARAGRAPH_ALIGNMENT.CENTER

        novelCollection.addTable(docObj, self.tableContent)        # 加表格

        for k, v in self.tableContent.items():  
        # 遍历小说-人物字典元素,k获得键值(作品),v获得值(人物)

            docObj.add_heading(k).alignment = WD_PARAGRAPH_ALIGNMENT.CENTER  
            # 作品名做小标题

            docObj.add_paragraph(self.paragraphs[k][0])  # 写入文章第一段

            novelCollection.addPicture(docObj, self.pictures[k])    # 加入图片

            docObj.add_paragraph(self.paragraphs[k][1:])  # 加上剩余的文字

        for paragraph in docObj.paragraphs:               # 设置所有段落文字字体
            for run in paragraph.runs:
                novelCollection.setChineseFont(run, 'KaiTi')

        docObj.save(self.filename)

    # 作品人物表格
    @staticmethod
    def addTable(docObj, contents):

        # 添加表头,表格内容一行一行添加
        table = docObj.add_table(rows=1, cols=2, style='Light Grid Accent 1')
        table.alignment = WD_TABLE_ALIGNMENT.CENTER  # 表格居中

        table.allow_autofit = False  # 允许人工调节
        for row in table.rows:       # 设置表格每一列大小
            row.cells[0].width = Cm(4)
            row.cells[1].width = Cm(3)

        table.rows[0].cells[0].text = '作品'  # 表格头
        table.rows[0].cells[1].text = '人物'

        for k, v in contents.items():  # 遍历小说-人物字典元素,k获得键值(作品),v获得值(人物)
            rowObj = table.add_row()   # 表格加一行
            rowObj.cells[0].text = k   # 把作品和人物填进这一行
            rowObj.cells[1].text = v

        for row in table.rows:         # 设置所有表格文字字体
            for cell in row.cells:
                for paragraph in cell.paragraphs:
                    for run in paragraph.runs:
                        novelCollection.setChineseFont(run, 'KaiTi')

    @staticmethod
    def addPicture(docObj, pic):
        docObj.add_picture(pic, width=Cm(6))    # 加图片,设置图片尺寸
        last_paragraph = docObj.paragraphs[-1]  # 获得图片段落
        last_paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER  # 图片居中

    @staticmethod
    def setChineseFont(run, cFont):  # 设置中文字体
        font = run.font
        font.name = cFont
        r = run._element
        r.rPr.rFonts.set(qn('w:eastAsia'), cFont)

authorList = ['鲁迅']					
# 只要作家材料准备完善就可以加入这个列表,自动生成排好版的文章

for author in authorList:
    authorWorks = Writer(author)
    novelCollection(authorWorks).launch()