Python--自动添加标签

一、项目介绍

利用Python,使用包括正则表达式给txt纯文本文件简单地添加HTML标记,得到html文件,让浏览器去显示它。

 

二、功能及实现

1.util:把一个文本分成很多文本块,文本块之间以一行空行分隔。一个文本块在后面会附上一种标签。这个文件里面有两个生成器,一个是负责在文本末尾生成一个空行(否则无法确定最后一个文本块到哪里结束),另一个是负责将文本块里面的所有行、段落合并,生成一个文本块字符串(比如一篇作文的正文可能有多行、多个段落,但他都属于正文这一个文本块)。

2.util代码讲解:两个生成器lines和blocks。blocks将一个文本块的所有行合并(一个段落有很多行),并将每行两端的缩进和换行删除,得到一个表示文本块的字符串。lines则是在文件末尾添加一个空行。yield返回一个迭代对象,赋给blocks生成器里面的line

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 = []
 

3.rules:这个里面分为两块,condition、action。先讲condition:每个文本块会对应不同的标签,如heading、title、paragraph,存在属性type里。这些规则都是自己定义的,比如heading就是:....。再讲action:这个是借助于第四个版块handles过滤器来实现的,在handles里面主要就是打印标签,比如<p>、</p>。

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

4.handlers:Handler里面的callback:根据前缀和名称查找相应的方法、start和end都是辅助方法,通过前缀调用callback、sub返回一个函数传给re.sub(调用re.sub的地方),用于正则表达式替换,使用emphasis等名词调用的时候,这个方法将返回相应的替换函数(消除只能添加em标签)。Handler里面的HTMLRenderer:渲染HTML的具体处理程序。

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>

5.markup:整个应用程序的核心,也就是这里面的解析器Parser,它使用一系列的规则和过滤器将txt转化为带标签的HTML。init函数里面创建了两个列表rules和filter(过滤器)。在后面的addRule和addFilter里面添加规则和过滤器(过滤器是个函数,)。最后再parse这个函数里面遍历每个文本块应用过滤器和规则,应用完过滤器之后看rule,如果满足condition,就调用action。

6.markup代码讲解:parser读取文件,应用规则、BasicTextParser添加规则和过滤器的parser子类。 em标签默认的强调方式是斜体、\1表示与第一个小括号里面的内容要匹配。

import sys, re
from handles 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)
 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值