您的位置:首页 > 编程语言 > Python开发

Python项目之即时标记

2016-05-17 19:12 567 查看
这个项目是《Python基础教程》后面的项目之一。当从一个不想写HTML代码的人那里得到一个文本文件,希望把它转成HTML的格式来当作一个网页来使用。人工添加标签是繁琐的,因此想写一个程序来自动完成。这类问题称之为即时标记。

主要是应用Python出色的文本处理能力——使用正则表达式将纯文本文件改写成语言(如HTML)中的标记,要做的工作基本上是将各种文本元素分类,比如标题和被强调的文本,然后明确地标记它们。

使用的方法:

1.对文件进行读写,从标准注入读取(sys.stdin),利用print输出等。

2.对所输入的行进行迭代。

3.使用了一些字符串方法。

4.re模块

程序分为四个模块:语法分析器、规则、过滤器以及处理程序。

语法分析器:读取文本,管理其他类。

规则:为每个种类的块定制规则,检测适用的块类型并且进行适当的格式化。

过滤器:包装一些处理内嵌元素的正则表达式。

self.addFilter(r'\*(.+?)\*', 'emphasis')
self.addFilter(r'(http://[\.a-z0-9A-Z/]+)', 'url')
self.addFilter(r'([\.a-zA-Z]+@[\.a-zA-Z]+[a-zA-Z]+)','mail')
这三个过滤器分别是关于强调的内容,关于URL,关于email。

处理程序:产生不同种类的标记。

具体实现代码:

处理程序(handles.py):

class Handler:

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):

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>'
def sub_emphasis(self, match):
return '<em>%s</em>' %match.group(1)
def sub_url(self, match):
return '<a href="%s">%s</a>' % (match.group(1), match.group(1))
def sub_mail(self, match):
return '<a href="mailto:%s">%s</a>' % (match.group(1), match.group(1))
def feed(self, data):
print data

规则(rules.py):

class Rule:
"""

"""
def action(self, block, handler):
handler.start(self.type)
handler.feed(block)
handler.end(self.type)
return True

class HeadingRule(Rule):
"""

"""
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:

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):
"""

"""
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]+)', 'mail')

handler = HTMLRenderer()
parser = BasicTextParser(handler)

parser.parse(sys.stdin)


补充util.py

def lines(file):
for line in file:yield 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 = []


运行结果:

被处理的文本:



处理后的结果为:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: