Python-即时标记

该项目包含用于实时标记的Python代码,包括README文件,资源部分,以及util、handlers和rules等核心模块,详细解释了项目的运行逻辑和类型判定规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

README

项目详情

python基础编程 第20章 项目1:自动添加标签

运行

python markup.py < test_input.txt > test_output.html

部分逻辑说明

过滤器 filters 替换特定元素为HTML元素
规则器 rules 根据判定条件,打印特定HTML头尾及Data元素

类型判定规则

1.标题,只包含一行的文本块,长度最多为70个字符,以冒号结束的文本块不属于标题
2.题目,文档中的第一个文本块,前提条件是它属于标题
3.列表项, 以连字符(-)打头的文本块
4.列表,以紧跟在非列表项文本块后面的列表项开头,以后面紧跟着非列表项文本块的列表项结束

注意

规则的先后顺序很重要,比如列表项(li)/列表(ul)
Resource

util.py

#!/usr/bin/python
# -*- coding: UTF-8 -*-

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

handlers.py

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class Handler:
    """
    Handler类是所有处理程序的基类。
    """

    # 方法callback根据指定的 前缀 和 名称 查找相应的方法。
    def callback(self, prefix, name, *args):
        method = getattr(self, prefix + name, None)
        if callable(method): return method(*args)

    # 辅助方法start,调用callback
    def start(self, name):
        self.callback('start_', name)

    # 辅助方法end,调用callback
    def end(self, name):
        self.callback('end_', name)

    # 方法sub,不调用callback,而是返回一个函数
    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的具体处理程序
    """

    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>{}</em>'.format(match.group(1))

    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

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class Rule:
    """
    所有规则的基类
    """

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


class HeadingRule(Rule):
    """
    A heading is a single line that is at most 70 characters and
    that doesn't end with a colon.
    """
    type = 'heading'

    def condition(self, block):
        return not '\n' in block and len(block) <= 70 and not block[-1] == ':'


class TitleRule(HeadingRule):
    """
    The title is the first block in the document, provided that
    it is a heading.
    """
    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):
    """
    A list item is a paragraph that begins with a hyphen. As part of the
    formatting, the hyphen is removed.
    """
    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):
    """
    A list begins between a block that is not a list item and a
    subsequent list item. It ends after the last consecutive list item.
    """
    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):
    """
    A paragraph is simply a block that isn't covered by any of the other rules.
    """
    type = 'paragraph'

    def condition(self, block):
        return True

markup.py

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import sys, re
from handlers import *
from util import *
from rules import *


class Parser:
    """
    A Parser 读入文本, 使用 rules and 控制 a handler.
    """

    # 初始化成员,handler,rules(),filters()
    def __init__(self, handler):
        self.handler = handler
        self.rules = []
        self.filters = []

    # 添加rule,方便扩展
    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)

    # 方法parse,读取文本(调用util.py的blocks(file))并分成block,
    # 使用循环用规则(rule)和过滤器(filter(block, handler)处理block,
    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):
                    if rule.action(block,
                                   self.handler): break

        self.handler.end('document')


# Parser派生出的具体的类(通过添加具体的规则和过滤器):用于添加HTML标记
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]+[a-zA-Z]+)', 'mail')


# 主程序:构造handler实例,构造parser(使用对应的handler)实例,调用parser的方法parser进行对文本的处理
handler = HTMLRenderer()
parser = BasicTextParser(handler)

parser.parse(sys.stdin)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值