本项目取材自《Python基础教程(第三版)》人民邮电出版社


目标:

本项目给纯文本文件添加格式,使文档转换成其他类型的文档(以HTML为例)

思路:

  1. 从原文件提取有用信息:

    • 文档结构---成为目标文档添加HTML标签的依据
    • 文档内容---成为目标文档的内容
  2. 制定原结构与HTML对应的规则
    • 一种是直接添加标签
    • 一种是用新标签替换旧标记
  3. 编写实际执行添加、置换操作的处理程序
  4. 编写主逻辑程序,创建实际的规则对象,并应用到原文档上,控制输入输出

具体实现:

#util.py
#这个模块的功能是为了将原文档分成块,以作为规则匹配程序的输入 def lines(file):
"""在文件末尾添加空行(结束标志)"""
for line in file: yield line #这里的一个line代表文档中的一段话
yield '\n' def blocks(file):
"""一段话生成一个文本块"""
block = []
for line in lines(file):
if line.strip():
block.append(line)
elif block:
yield ''.join(block).strip()
block = []
#handlers.py
#这个模块的作用是将已经匹配好规则的文本块进行标签加工,添加开始结束标签,或者将某类标记替换成HTML标签(注释、列表项等) class Handler:
"""
start()、end()根据传入的参数调用具体的标签方法,并具有一定的异常处理能力,忽略未定义的标签方法调用
sub()根据传入的MatchObject对象调用对应的置换方法
"""
def callback(self, prefix, name, *args):
method = getattr(self, prefix + name, None)
if callable(method): return method(*args)
def start(self, name):
self.callback('start_', name)
def end(self, name):
self.callback('end_', name)
def sub(self, name): def substitution(match):
result = self.callback('sub_', name, match)
if result is None: match.group(0)
return result
return substitution class HTMLRenderer(Handler):
"""
用于渲染HTML的具体处理程序,其中定义了各类标签方法的具体实现,这些方法由超类的方法来访问
feed方法用在start、end之间,给结果字符串添加文本内容
"""
def start_document(self):
print('<html><head><title>...</title></head><body>')
def end_document(self):
print('</body></html>')
def start_paragraph(self):
print('<p>')
def end_paragraph(self):
print('</p>')
def start_heading(self):
print('<h2>')
def end_heading(self):
print('</h2>')
def start_list(self):
print('<ul>')
def end_list(self):
print('</ul>')
def start_listitem(self):
print('<li>')
def end_listitem(self):
print('</li>')
def start_title(self):
print('<h1>')
def end_title(self):
print('</h1>') #下面这几个方法的实际调用者是re.sub(),如re.sub(pattern, sub_emphasis(), block),
#re.sub方法会将对block进行模式匹配后的结果(一个MatchObject对象)传入sub_emphasis,最终返回置换完成的字符串
def sub_emphasis(self, match):
return '<em>{}</em>'.format(match.group(1)) #等价于renturn '<em>/1</em>'
def sub_url(self, match):
return '<a href="{}">{}</a>'.format(match.group(1), match.group(1))
def sub_mail(self, match):
return '<a href="mailto:{}">{}</a>'.format(match.group(1), match.group(1)) def feed(self, data):
print(data)
#rules.py
#这个模块制定了一系列规则,这些规则会匹配各类文档块,并调用相应的标签处理程序 class Rule:
"""
所有规则的基类,定义了大多数情况通用的action方法
""" def action(self, block, handler):
handler.start(self.type)
handler.feed(block)
handler.end(self.type)
return True class HeadingRule(Rule):
"""
标题只包含一行,不超过70个字符且不以冒号结尾
"""
type = 'heading'
def condition(self, block):
return not '\n' in block and len(block) <= 70 and not block[-1] == ':' class TitleRule(HeadingRule):
"""
题目是文档中的第一个文本块,前提条件是它属于标题
"""
type = 'title'
first = True def condition(self, block):
if not self.first: return False
self.first = False
return HeadingRule.condition(self, block) class ListItemRule(Rule):
"""
列表项是以字符打头的段落。在设置格式的过程中,将把连字符删除
"""
type = 'listitem'
def condition(self, block):
return block[0] == '-'
def action(self, block, handler):
handler.start(self.type)
handler.feed(block[1:].strip())
handler.end(self.type)
return True class ListRule(ListItemRule):
"""
列表以紧跟在非列表项文本块后面的列表项打头,以相连的最后一个列表项结束
"""
type = 'list'
inside = False
def condition(self, block):
return True
def action(self, block, handler):
if not self.inside and ListItemRule.condition(self, block):
handler.start(self.type)
self.inside = True
elif self.inside and not ListItemRule.condition(self, block):
handler.end(self.type)
self.inside = False
return False class ParagraphRule(Rule):
"""
段落是不符合其他规则的文本块
"""
type = 'paragraph'
def condition(self, block):
return True
#markup.py
#负责整合调用各模块 import sys, re
from handlers import *
from util import *
from rules import * class Parser:
"""
Paeser读取文本文件,应用规则并控制处理程序
"""
def __init__(self, handler):
self.handler = handler
self.rules = []
self.filters = []
def addRule(self, rule):
self.rules.append(rule)
def addFilter(self, pattern, name):
def filter(block, handler):
return re.sub(pattern, handler.sub(name), block)
self.filters.append(filter) def parse(self, file):
self.handler.start('document')
for block in blocks(file):
for filter in self.filters:
block = filter(block, self.handler)
for rule in self.rules:
if rule.condition(block):
last = rule.action(block,
self.handler)
if last: break
self.handler.end('document') class BasicTextParser(Parser):
"""
在构造函数中添加规则和过滤器的Parser子类
注意:规则列表的添加顺序是有要求的,condition判断失败才会匹配下一条规则
"""
def __init__(self, handler):
Parser.__init__(self, handler)
self.addRule(ListRule())
self.addRule(ListItemRule())
self.addRule(TitleRule())
self.addRule(HeadingRule())
self.addRule(ParagraphRule()) self.addFilter(r'\*(.+?)\*', 'emphasis')
self.addFilter(r'(http://[\.a-zA-Z/]+)', 'url')
self.addFilter(r'([\.a-zA-Z]+@[\.a-zA-Z]+[a-zA-Z]+)', 'mail') handler = HTMLRenderer()
parser = BasicTextParser(handler) parser.parse(sys.stdin)

这样就完成了,可以用下面这段文本做个实验,看看结果如何。



Welcome to World Wide Spam, Inc.

These are the corporate web pages of *World Wide Spam*, Inc. We hope
you find your stay enjoyable, and that you will sample many of our
products. A short history of the company World Wide Spam was started in the summer of 2000. The business
concept was to ride the dot-com wave and to make money both through
bulk email and by selling canned meat online. After receiving several complaints from customers who weren't
satisfied by their bulk email, World Wide Spam altered their profile,
and focused 100% on canned goods. Today, they rank as the world's
13,892nd online supplier of SPAM. Destinations From this page you may visit several of our interesting web pages: - What is SPAM? (http://wwspam.fu/whatisspam) - How do they make it? (http://wwspam.fu/howtomakeit) - Why should I eat it? (http://wwspam.fu/whyeatit) How to get in touch with us You can get in touch with us in *many* ways: By phone (555-1234), by
email (wwspam@wwspam.fu) or by visiting our customer feedback page
(http://wwspam.fu/feedback).

Python项目1:自动添加标签的更多相关文章

  1. Pycharm创建项目时 自动添加头部信息

    1.打开PyCharm,选择File--Settings 2.依次选择Editor---Code Style-- File and Code Templates---Python Script 3.. ...

  2. 解决使用vue-cli生成项目后项目地址自动添加#号的问题

    vue-router官网https://router.vuejs.org/zh/guide/ vue的路由在默认的hash模式下,url会带有一个#,不美观,而且在微信分享,授权登录等都会有一些坑.所 ...

  3. Jenkins持续集成_02_添加python项目&设置定时任务

    前言 自动化测试脚本编写后,最终目的都是持续集.持续集成可以实现一天多次部署运行自动化脚本,对功能进行不断监控测试.由于小编使用python编写的自动化脚本,这里仅讲解下如何在Jenkins中添加py ...

  4. Jenkins 为Jenkins添加Windows Slave远程执行python项目脚本

    为Jenkins添加Windows Slave远程执行python项目脚本   by:授客 QQ:1033553122 测试环境 JAVA JDK 1.7.0_13 (jdk-7u13-windows ...

  5. Python项目在Jenkins中的自动化测试实践(语法检查、单元测试,coverage(代码覆盖率)、自动打包)

    原始链接:http://blog.csdn.net/a464057216/article/details/52934077 requirments OS: Ubuntu 14.04+ Gitlab 8 ...

  6. Discuz 3.X 门户文章插入图片自动添加 alt 标签

    最近用 Discuz 搭建了个网站--儿童安全座椅网(www.bbseat.com.cn),用到了门户功能,不得不说Discuz 的功能还是非常强大的,但在使用过程中发现在发表文章时添加了图片却不能像 ...

  7. python logging详解及自动添加上下文信息

    之前写过一篇文章日志的艺术(The art of logging),提到了输出日志的时候记录上下文信息的重要性,我认为上下文信息包括: when:log事件发生的时间 where:log事件发生在哪个 ...

  8. sphinx:python项目文档自动生成

    Sphinx: 发音: DJ音标发音: [sfiŋks] KK音标发音: [sfɪŋks] 单词本身释义: an ancient imaginary creature with a lion's bo ...

  9. Discuz! 3.3全站帖子自动添加图片alt标签

    网站想要更好的适应搜索引擎的话,就要把最基础的一些小优化标签做好, 虽然说现在搜索都很厉害能够识别图片,但是除非的你的图片每一张都是周杰伦.范冰冰等知名图片... 不然你还是要给你自己的图添加alt标 ...

随机推荐

  1. MeteoInfoLab脚本示例:加载地图图层

    应用最广泛的的地图数据应该是shape格式,网络上有很多免费下载资源.MeteoInfoLab中读取shape文件的函数是shaperead,参数即文件名,返回数据包含图形和属性信息的图层对象.矢量图 ...

  2. day08 Pyhton学习

    一.昨日内容回顾 .1.基础部分的补充 join()  把列表变成字符串, 拼接 split() 切割 删除: 列表和字典不能在循环的时候进行删除. 把要删除的内容记录在一个新列表中,然后循环新列表, ...

  3. day25 Pyhton学习 约束和异常处理

    一.类的约束 约束是对类的约束 有两种方法: 1.提取一个父类,在父类中给出一个方法,并且在方法中不给出任何代码,直接抛异常 class Base: def login(self): raise Ex ...

  4. set的运用 例题5-3 安迪的第一个字典(Andy's First Dictionary,Uva 10815)

    #include<bits/stdc++.h>using namespace std;set<string> dict;int main(){ string s, buf; w ...

  5. Jmeter之参数化函数助手__randomstring

    1.Tools->函数助手对话框,选择__Random String,2表示随机生成的字符长度:3表示从哪些字符中随机生成:然后点击生成,得到对应的变量: 5中372表示该函数随机生成的字符串, ...

  6. STM32芯片型号的命名规则

    意法半导体已经推出STM32基本型系列.增强型系列.USB基本型系列.增强型系列:新系列产品沿用增强型系列的72MHz处理频率.内存包括64KB到256KB闪存和20KB到64KB嵌入式SRAM.新系 ...

  7. Dubbo源码本地运行demo遇到的问题

    从github上拉下来的Dubbo源码,运行Dubbo项目的demo工程,报如下错误(Dubbo版本为2.7.6): Exception in thread "main" java ...

  8. Shell脚本学习指南笔记(一)

    脚本语言通常是解释型的,这类程序的运行.是由解释器读入程序代码,并将其转换成内部的形式, 再执行,解释器本身是一般的编译型程序. 第一行的开头处使用#!这两个字符,当内核扫描到改行的其余部分,看是否存 ...

  9. 文件开启关闭操作c语言模板

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <stri ...

  10. Luban图片压缩

    导入依赖: implementation 'top.zibin:Luban:1.1.3' public class MainActivity extends AppCompatActivity { p ...