Python 文本解析器

一、項目介紹

本教程講解一個使用 Python 來解析純文本生成一個 HTML 頁面的小程序。

詳細教程及在線練習地址:Python - Python文本解析器

二、相關技術

Python:一種面向對象、解釋型計算機程序設計語言,用它可以做 Web 開發、圖形處理、文本處理和數學處理等等。

HTML:超文本標記語言,主要用來實現網頁。

三、項目截圖

純文本文件:

Welcome to ShiYanLouShiYanLou is the first experiment with IT as the core of online education platform.*Our aim is to do the experiment, easy to learn IT*.Course-Basic Course-Project Course-Evaluation CourseContact us-Web:http://www.shiyanlou.com-QQ Group:241818371-E-mail:support@shiyanlou.com

解析後生成的 HTML 頁面如下圖

四、項目講解

1. 文本塊生成器

首先我們需要有一個文本塊生成器把純文本分成一個一個的文本塊,以便接下來對每一個文本快進行解析,util.py 代碼如下:

#!/usr/bin/python# encoding: utf-8def 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 = []

2. 處理程序

通過文本生成器我們得到了一個一個的文本塊,然後需要有處理程序對不同的文本塊加相應的 HTML 標記,handlers.py 代碼如下:

#!/usr/bin/python# encoding: utf-8class 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: result = match.group(0) return result return substitutionclass HTMLRenderer(Handler): """ HTML 處理程序,給文本塊加相應的 HTML 標記 """ def start_document(self): print <html><head><title>ShiYanLou</title></head><body> def end_document(self): print </body></html> def start_paragraph(self): print <p stylex="color: #444;"> def end_paragraph(self): print </p> def start_heading(self): print <h2 stylex="color: #68BE5D;"> def end_heading(self): print </h2> def start_list(self): print <ul stylex="color: #363736;"> def end_list(self): print </ul> def start_listitem(self): print <li> def end_listitem(self): print </li> def start_title(self): print <h1 stylex="color: #1ABC9C;"> 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 target="_blank" stylex="text-decoration: none;color: #BC1A4B;" href="%s">%s</a> % (match.group(1), match.group(1)) def sub_mail(self, match): return <a stylex="text-decoration: none;color: #BC1A4B;" href="mailto:%s">%s</a> % (match.group(1), match.group(1)) def feed(self, data): print data

3. 規則

有了處理程序和文本塊生成器,接下來就需要一定的規則來判斷每個文本塊交給處理程序將要加什麼標記,rules.py 代碼如下:

#!/usr/bin/python# encoding: utf-8class Rule: """ 規則父類 """ def action(self, block, handler): """ 加標記 """ handler.start(self.type) handler.feed(block) handler.end(self.type) return Trueclass HeadingRule(Rule): """ 一號標題規則 """ 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 = 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 Trueclass 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 Falseclass ParagraphRule(Rule): """ 段落規則 """ type = paragraph def condition(self, block): return True

4. 解析

最後我們就可以進行解析了,markup.py 代碼如下:

#!/usr/bin/python# encoding: utf-8import sys, refrom 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]+[a-zA-Z]+), mail)"""運行程序"""handler = HTMLRenderer()parser = BasicTextParser(handler)parser.parse(sys.stdin)

運行程序(純文本文件為 test.txt,生成 HTML 文件為 test.html)

python markup.py < test.txt > test.html

五、完整代碼

登錄實驗樓查看完整代碼。實驗樓為本項目提供了在線練習環境。

更多Python經典項目:Python項目課

六、小結

在這個小程序中,我們使用了 Python 來解析純文本文件並生成 HTML 文件,這個只是簡單實現,通過這個案例大家可以動手試試解析 Markdown 文件。

註:轉載需獲授權,並保留課程地址:shiyanlou.com/courses/7

推薦閱讀:

Python從零開始系列連載(19)——Python特色數據類型(列表)(下)
60分鐘用Django寫一個Python個人博客
一次散點圖數據可視化嘗試
5分鐘教你學會Django系統錯誤監控

TAG:Python | Python开发 | Python教程 |