zoukankan      html  css  js  c++  java
  • Python练习1-文档格式化成html

    文档格式化成HTML

        把文档格式化成了THML,并没有处理所有thml规则,只是处理了一部分,功能不重要,重要的是复习熟悉下Python对文档的处理细节。毕竟Python大多数给我的印象都是处理文档。代码里有很多逻辑可能不严谨,这里再次强调只是为了复习字符串以及文档操作。

        同时提醒一下,如果运行失败,请删除注释,我是用vs2015编写的,返现当时中文注释导致编码错误运行失败。一共四个文档:


     入口文档是markup.py

    参数 python markup.py < xxx.txt > xxx.html

    执行效果和代码如下:



    Util.py

    def lines(file):
        for line in file:yield line
        yield '
    '
     
    def blocks(file):
        block = []
        for line in lines(file):
            if line.strip():   #'
    ','
    ','	',' '
                block.append(line);
            elif block:
                yield ''.join(block).strip()
                block = []
     
     

    Handlers.py

    class Handler:
        """
        处理从Parser调用的方法的对象。
     
        这个解析器会在每个块的开始部分调用start()和end()方法,使用合适的
        块名作为参数,sub()方法会用于正则表达式替换中。当使用了'emphasis'
        这样的名字调用时,它会返回合适的替换函数。
        """
        def callback(self ,prefix ,name ,*args):
            method = getattr(self ,prefix + name ,None)
            if callable(method) : return method(*agrs)
        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的具体处理程序
     
        THMLRenderer内容的方法都是可以通过超类处理程序的start()、
        end()和sub()方法来访问。他们实现了用于HTRML文档的基本标签。
        """
        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('<title>')
        def end_title(self):
            print('</title>')
        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):
        """
        标题占一行,最多70个字符,并且不以冒号结尾。
        """
        type = 'heading'
        def condition(self ,block):
            return not '
    ' 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 = 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(bolck ,handler):
                return re.sub(pattern ,handler.sub(name),bolck)
            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]+[a-zA-Z]+)' ,'mail')
     
    handler = HTMLRenderer()
    parser = BasicTextParser(handler)
     
    parser.parse(sys.stdin)


  • 相关阅读:
    《ASP.NET2.0揭秘》读书笔记——构建组合控件
    《ASP.NET2.0揭秘》读书笔记——构建自定义控件前你必须思考的两个问题
    《ASP.NET2.0揭秘》读书笔记——构建混合控件
    jQuery.bind事件 详解
    High Performance JavaScript(高性能JavaScript)读书笔记
    HTML5 新标签总汇
    前端攻略系列(三) javascript 设计模式(文章很长,请自备瓜子,水果和眼药水)
    node.js 初体验
    Fiddler 前端开发值得拥有
    JavaScript实现 页面滚动图片加载
  • 原文地址:https://www.cnblogs.com/csnd/p/12061964.html
Copyright © 2011-2022 走看看