Python 文本解析器
Python 文本解析器
一、课程介绍
本课程讲解一个使用 Python 来解析纯文本生成一个 HTML 页面的小程序。
二、相关技术
Python:一种面向对象、解释型计算机程序设计语言,用它可以做 Web 开发、图形处理、文本处理和数学处理等等。
HTML:超文本标记语言,主要用来实现网页。
三、项目截图
纯文本文件:
Welcome to ShiYanLou
ShiYanLou 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 Course
Contact us
-Web:http://www.shiyanlou.com
-QQ Group:241818371
-E-mail:support@shiyanlou.com
解析后生成的 HTML 页面如下图

四、项目讲解
1. 文本块生成器
首先我们需要有一个文本块生成器把纯文本分成一个一个的文本块,以便接下来对每一个文本快进行解析,util.py 代码如下:
#!/usr/bin/python
# encoding: 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 = []
2. 处理程序
通过文本生成器我们得到了一个一个的文本块,然后需要有处理程序对不同的文本块加相应的 HTML 标记,handlers.py 代码如下:
#!/usr/bin/python
# encoding: utf-8
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: result = match.group(0)
return result
return substitution
class 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 style="color: #444;">'
def end_paragraph(self):
print '</p>'
def start_heading(self):
print '<h2 style="color: #68BE5D;">'
def end_heading(self):
print '</h2>'
def start_list(self):
print '<ul style="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 style="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" style="text-decoration: none;color: #BC1A4B;" href="%s">%s</a>' % (match.group(1), match.group(1))
def sub_mail(self, match):
return '<a style="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-8
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
4. 解析
最后我们就可以进行解析了,markup.py 代码如下:
#!/usr/bin/python
# encoding: utf-8
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]+[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
五、代码下载
可以使用下列命令下载本课程相关代码:
$ git clone http://git.shiyanlou.com/shiyanlou/python_markup
六、小结
在这个小程序中,我们使用了 Python 来解析纯文本文件并生成 HTML 文件,这个只是简单实现,通过这个案例大家可以动手试试解析 Markdown 文件。
Python 文本解析器的更多相关文章
- 5. python 文本解析
5. python 文本解析 这一章节我们简单的聊聊文本解析的两种方法: 1.分片,通过分片,记录偏移处,然后提取想要的字符串 例子: >>> line='aaa bbb ccc' ...
- Python HTML解析器BeautifulSoup(爬虫解析器)
BeautifulSoup简介 我们知道,Python拥有出色的内置HTML解析器模块——HTMLParser,然而还有一个功能更为强大的HTML或XML解析工具——BeautifulSoup(美味的 ...
- Python 网页解析器
Python 有几种网页解析器? 1. 正则表达式 2.html.parser (Python自动) 3.BeautifulSoup(第三方)(功能比较强大) 是一个HTML/XML的解析器 4.lx ...
- python——BS解析器
- python 之网页解析器
一.什么是网页解析器 1.网页解析器名词解释 首先让我们来了解下,什么是网页解析器,简单的说就是用来解析html网页的工具,准确的说:它是一个HTML网页信息提取工具,就是从html网页中解析提取出“ ...
- 面试官问我:如何在 Python 中解析和修改 XML
摘要:我们经常需要解析用不同语言编写的数据.Python提供了许多库来解析或拆分用其他语言编写的数据.在此 Python XML 解析器教程中,您将学习如何使用 Python 解析 XML. 本文分享 ...
- 深入浅出 Vue.js 第九章 解析器---学习笔记
本文结合 Vue 源码进行学习 学习时,根据 github 上 Vue 项目的 package.json 文件,可知版本为 2.6.10 解析器 一.解析器的作用 解析器的作用就是将模版解析成 AST ...
- 28.解析器Parser
什么是解析器 因为前后端分离,可能有json.xml.html等各种不同格式的内容 后端也必须要有一个解析器来解析前端发送过来的数据 不然后端无法处理前端数据 后端有一个渲染器Render,和解析器是 ...
- python模块介绍- HTMLParser 简单的HTML和XHTML解析器
python模块介绍- HTMLParser 简单的HTML和XHTML解析器 2013-09-11 磁针石 #承接软件自动化实施与培训等gtalk:ouyangchongwu#gmail.comqq ...
随机推荐
- HTML之表格与表单
一.表格(table/tr/td) <table></table>表格 --不设高度 width:宽度.可以用像素或百分比表示. 常用960像素. border:边框,常用值为 ...
- 【转载】如何用Maven创建web项目(具体步骤)
使用eclipse插件创建一个web project 首先创建一个Maven的Project如下图 我们勾选上Create a simple project (不使用骨架) 这里的Packing 选择 ...
- 一个简单二叉树的C++实现(一)
很久没有接触二叉树了,写这个当作练手,接下来会比较详细地实现二叉树的各个功能及应用. /* * BinaryTree.cpp * Author: Qiang Xiao * Time: 2015-07- ...
- Arduino101 中使用 Mirf 库的问题(2016-04-04)
Mirf 库在使用 NRF24L01 的时候接触到,感觉很好用.但在用 Arduino101 的时候遇到一些问题,记录一下,对于底层不了解,希望有熟悉的同学能给点指点: 编译会提示 MirfHardw ...
- Sticks(poj 1011)
题目描述: Description George took sticks of the same length and cut them randomly until all parts became ...
- FluentConsole是一个托管在github的C#开源组件
FluentConsole是一个托管在github的C#开源组件 阅读目录 1.控制台能有啥滑头? 2.FluentConsole基本介绍 3.使用介绍 4.资源 从该系列的第一篇文章 .NET平台开 ...
- Windows Phone 8初学者开发—第3部分:编写第一个Windows Phone 8应用程序
原文 Windows Phone 8初学者开发—第3部分:编写第一个Windows Phone 8应用程序 原文地址: http://channel9.msdn.com/Series/Windows- ...
- oracle序列详解
tyle="margin:20px 0px 0px; font-size:14px; line-height:26px; font-family:Arial"> 序列: 是o ...
- poj 3984 迷宫问题(dfs)
题目链接:http://poj.org/problem?id=3984 思路:经典型的DFS题目.搜索时注意剪枝:越界处理,不能访问处理. 代码: #include <iostream> ...
- 饭卡------HDOJ杭电2546(还是01背包!!!!!!)
Problem Description 电子科大本部食堂的饭卡有一种非常诡异的设计,即在购买之前推断剩余金额. 假设购买一个商品之前,卡上的剩余金额大于或等于5元,就一定能够购买成功(即使购买后卡上剩 ...