Python项目1:自动添加标签
本项目取材自《Python基础教程(第三版)》人民邮电出版社
目标:
本项目给纯文本文件添加格式,使文档转换成其他类型的文档(以HTML为例)
思路:
- 从原文件提取有用信息:
- 文档结构---成为目标文档添加HTML标签的依据
- 文档内容---成为目标文档的内容
- 制定原结构与HTML对应的规则
- 一种是直接添加标签
- 一种是用新标签替换旧标记
- 编写实际执行添加、置换操作的处理程序
- 编写主逻辑程序,创建实际的规则对象,并应用到原文档上,控制输入输出
具体实现:
#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:自动添加标签的更多相关文章
- Pycharm创建项目时 自动添加头部信息
1.打开PyCharm,选择File--Settings 2.依次选择Editor---Code Style-- File and Code Templates---Python Script 3.. ...
- 解决使用vue-cli生成项目后项目地址自动添加#号的问题
vue-router官网https://router.vuejs.org/zh/guide/ vue的路由在默认的hash模式下,url会带有一个#,不美观,而且在微信分享,授权登录等都会有一些坑.所 ...
- Jenkins持续集成_02_添加python项目&设置定时任务
前言 自动化测试脚本编写后,最终目的都是持续集.持续集成可以实现一天多次部署运行自动化脚本,对功能进行不断监控测试.由于小编使用python编写的自动化脚本,这里仅讲解下如何在Jenkins中添加py ...
- Jenkins 为Jenkins添加Windows Slave远程执行python项目脚本
为Jenkins添加Windows Slave远程执行python项目脚本 by:授客 QQ:1033553122 测试环境 JAVA JDK 1.7.0_13 (jdk-7u13-windows ...
- Python项目在Jenkins中的自动化测试实践(语法检查、单元测试,coverage(代码覆盖率)、自动打包)
原始链接:http://blog.csdn.net/a464057216/article/details/52934077 requirments OS: Ubuntu 14.04+ Gitlab 8 ...
- Discuz 3.X 门户文章插入图片自动添加 alt 标签
最近用 Discuz 搭建了个网站--儿童安全座椅网(www.bbseat.com.cn),用到了门户功能,不得不说Discuz 的功能还是非常强大的,但在使用过程中发现在发表文章时添加了图片却不能像 ...
- python logging详解及自动添加上下文信息
之前写过一篇文章日志的艺术(The art of logging),提到了输出日志的时候记录上下文信息的重要性,我认为上下文信息包括: when:log事件发生的时间 where:log事件发生在哪个 ...
- sphinx:python项目文档自动生成
Sphinx: 发音: DJ音标发音: [sfiŋks] KK音标发音: [sfɪŋks] 单词本身释义: an ancient imaginary creature with a lion's bo ...
- Discuz! 3.3全站帖子自动添加图片alt标签
网站想要更好的适应搜索引擎的话,就要把最基础的一些小优化标签做好, 虽然说现在搜索都很厉害能够识别图片,但是除非的你的图片每一张都是周杰伦.范冰冰等知名图片... 不然你还是要给你自己的图添加alt标 ...
随机推荐
- OpenCV开发笔记(七十):红胖子带你傻瓜式编译VS2017x64版本的openCV4
前言 红胖子来也!!! opencv_contrib是opencv提供额外的工具,提供一些基础算法,之前编译了不带opencv_contrib的版本,不带opencv_contrib的cuda硬 ...
- 以太坊blockchain源码分析
blockchain关键元素 db:持久化到底层数据储存,即leveldb: genesisBlock:创始区块 currentBlock:当前区块,blockchain中并不是储存链所有的block ...
- 加密sqlite3数据库文件
目录 EncryptSqlite3 实现原理 使用方法 不足之处 GitHub地址 EncryptSqlite3 加密sqlite3数据库,产生的数据库文件别人打不开. 实现原理 在写入文件前对每个字 ...
- 【C语言C++编程学习笔记】基础语法,第一个简单的实例编程入门教程!
C语言/C++编程学习:一个简单的实例 让我们来看一个简单的C语言程序.从下面的程序可以看出编写C语言程序的一些基本特征. 如果你能知道该程序将会在显示器上显示一些内容,那说明你还是知道一些的! ...
- 【最短路】HDU 1688 Sightseeing
题目大意 给出一个有向图(可能存在重边),求从\(S\)到\(F\)最短路的条数,如果次短路的长度仅比最短路的长度多1,那么再加上次短路的条数. 输入格式 第一行是数据组数\(T\). 对于魅族数据, ...
- idea创建servlet工程初体验
servlet工程创建 前提:创建项目之前需要配置java环境变量 和tomcat配置,配置完成后进入如下操作. tomcat 安装和配置参考 https://www.cnblogs.com/xush ...
- xuexi
1.内存的编址方法就是内存地址与内存单元格一一对应且永久绑定.计算机的cpu只认识内存地址,不关心内存单元格的位置和内容.通过硬件的设计来达到通过内存地址找到内存单元格. 2.内存的编址是以字节为单位 ...
- 用CentOS 7自制Vagrant Box文件
写在前面 利用vagrant保持开发生产环境一致是一个很好的方法,不过vagrant官网上的box文件下载是真的很慢,因此,这里教大家如何自制box文件. 这篇文章你会接触到: vagrant使用 ...
- go 接口实现
package main import ( "fmt" ) // 定义接口 type Beahavior interface { Run() string Eat(thing st ...
- Ubuntu安装zookeeper问题
在Ubuntu系统安装zookeeper后,启动报错: root@host8:/usr/solrcould/service1/zookeeper-3.5.0-alpha# sh bin/zkServe ...