python练习一—文本转化渲染为html
想学习python已经很久了,以前使用ArcGIS的时候学习过一些简单的python语法,用来进行一些简单的GIS数据处理,但是后来并没有用到工作中也就荒废了,后来断断续续看过一些,最近想学习一门新的语言,就拿python下手了,仔细考(拼)虑(凑)出以下理由(喜欢就是喜欢,不用理由):
- python强大库支持,在科学计算、人工智能等高精尖的领域使用甚广
- 在运维中也算是除shell外的第二语言吧
- 学习渗透测试的时候很多poc都是使用python写的,为了不仅仅停留在使用工具上,进一步学习
- 在web中python也是快速开发的利器
本次学习主要是《python基础教程》第二版,简单回顾了前面几章基础知识后,开始拿后面的练习来学习,虽然代码大部分是直接参考书中源码,但是“纸上得来终觉浅,绝知此事要躬行”可不是废话,学习这件事不动手就是耍流氓,在自己动手编写书中例子的时候对python的语法和思想理解逐渐加深。先来一发
为了避免直接上代码略显突兀,显写出这个练习项目的思路:
先撇开具体实现,想想如果要实现将文本转化位html的做法:
- 文本一定时满足一定规则的
- 读取文本内容
- 根据预定义的规则分析读入的文本内容
- 符合某一种规则的文本加上对应的html标签
- 继续读入文本,回到2继续处理
再回来书中的项目,本项目共包含四个模块
- util.py:负责对文本进行一定的格式化,并读取文本
- rule.py:定义什么样的文本可以转化为什么样的html,两件事儿:
- 定义文本和html对应的规则
- 决定规则对应的处理程序(handler)
- handler.py:将给定规则的文本转换为html
- parse.py:调用util.py读取文本,调用rule.py判断文本对应的规则,调用handler处理给定规则的文本
这样子基本脉络已经清晰了,看代码
util.py
# -*- 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():
# line不是空行,属于一个块
block.append(line)
elif block:
# 当前行是空行,block不为空,块已经结束,返回块
yield ''.join(block).strip()
block = []
handler.py
# -*- coding=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 subtitution(match):
result = self.callback('sub_', name, match)
if result is None:
match.group(0)
return subtitution class HTMLRender(Handler):
def start_document(self):
print '<html><head><title>...</title></head><body>'
def end_document(self):
print '</body>'
def start_paragraph(self):
print '<p>'
def end_paragraph(self):
print '</p>'
def start_head(self):
print '<h2>'
def end_head(self):
print '</h2>'
def start_title(self):
print '<h1>'
def end_title(self):
print '</h1>'
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 sub_em(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_email(self, match):
return '<a href="mailto:%s">%s</a>' % (match.group(1), match.group(1))
def feed(self, data):
print data
rule.py
# -*- coding=utf-8 -*- class Rule:
def action(self, block, handler):
handler.start(self.type)
handler.feed(block)
handler.end(self.type)
return True class HeadRule(Rule):
'''
小标题的规则,没有换行符,长度小于70并且不以:结尾
''' type = 'head'
def condition(self, block):
return not '\n' in block and len(block) < 70 and block[-1] != ':'
class TitleRule(HeadRule):
'''
标题的规则,第一行是就是标题
'''
type = 'title'
first = True
def condition(self, block):
if not self.first:
return False
self.first = False
return HeadRule.condition(self, block)
class ListItemRule(Rule):
'''
li的规则,如果block以-开头就是listitem,在显示的时候去除-
''' 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):
'''
ul的规则,第一个li开始之前,添加ul,在第一个不是li的时候结束ul
'''
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)
# 每次返回False,在对block使用完本规则之后继续使用其他规则
return False class ParagraphRule(Rule):
'''
p段落规则,当前面所有的规则匹配的时候,默认使用本规则
''' type = 'paragraph'
def condition(self, block):
return True
parse.py
# -*- coding=utf-8
import re, sys
from util import *
from handler import *
from rule import *
import ipdb class Parser:
'''
解析器,利用rule对文本进行解析并转换为html,利用filter转换块内文本
''' 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):
#pdb.set_trace()
self.handler.start('document')
for block in blocks(file):
ipdb.set_trace()
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):
'''
基本文本解析器,只有h1,h2,p,ul,li,a,em,email
''' def __init__(self, handler):
Parser.__init__(self, handler)
self.addRule(ListRule())
self.addRule(ListItemRule())
self.addRule(TitleRule())
self.addRule(HeadRule())
self.addRule(ParagraphRule()) self.addFilter(r'\*(.+?)\*', 'em')
self.addFilter(r'(http://[\.a-zA-Z]+)', 'url')
self.addFilter(r'([\.a-zA-Z]+@[\.a-zA-Z]+[[a-zA-Z]+)', 'email') handler = HTMLRender()
parser = BasicTextParser(handler)
parser.parse(sys.stdin)
第一次练习就遇到这个项目显得略大,不过搞清楚思路之后整体把我就没问题了,在练习的过程中还遇到一些问题、学到一些东西,总结如下:
- 子类调用父类的方法(包括__init__)
父类名.方法名(self, 参数)
A类调用B类方法
b = B()
b.方法(参数)
- re模块的sub方法
re.sub(regex_str, replace_str, str)
将str中符合正则表达式regex_str的子串用replace_str代替
如果replace_str是正则表达式,可以使用分组替换,例如
re.sub(r'\*(.+)\*', r'---\1---', "asdasdasd*nskjdfnkjdsnf*sdfsdf")
re.sub(r'\*(.+)\*',lambda m: "---" + m.group(1) + "---" ,"asdasdasd*nskjdfnkjdsnf*sdfsdf")
其实作者里面有两个思想让我触动很深,甚是佩服:
- 一个模块做最少的事,制作自己必须做的事
- 事件的路由分发(借由python发挥的淋漓尽致)
这两种思想让项目整体架构变的很清晰,对扩展也很友好,大写的赞!
这个练习已经写完几天了,今天补上记录一下,代码位置
http://pan.baidu.com/s/1o7JVKKU
python练习一—文本转化渲染为html的更多相关文章
- 15.Python文本转化语音方法
1.用pywin32模块来将文本转化为语音 通过pip install pywin32安装模块,pywin32是个万金油的模块,太多的场景使用到它,但在文本转语音上,它却是个青铜玩家,简单无脑但效果不 ...
- 【NLP】Python NLTK获取文本语料和词汇资源
Python NLTK 获取文本语料和词汇资源 作者:白宁超 2016年11月7日13:15:24 摘要:NLTK是由宾夕法尼亚大学计算机和信息科学使用python语言实现的一种自然语言工具包,其收集 ...
- python Django教程 之模板渲染、循环、条件判断、常用的标签、过滤器
python3.5 manage.py runserver python Django教程 之模板渲染.循环.条件判断.常用的标签.过滤器 一.Django模板渲染模板 1. 创建一个 zqxt_tm ...
- Python数据类型之“文本序列(Text Sequence)”
Python中的文本序列类型 Python中的文本数据由str对象或字符串进行处理. 1.字符串 字符串是Unicode码值的不可变序列.字符串字面量有多种形式: 单引号:'允许嵌入"双&q ...
- Selenium2+python自动化23-富文本(自动发帖)
前言 富文本编辑框是做web自动化最常见的场景,有很多小伙伴遇到了不知道无从下手,本篇以博客园的编辑器为例,解决如何定位富文本,输入文本内容 一.加载配置 1.打开博客园写随笔,首先需要登录,这里为了 ...
- python实现的文本编辑器 - Skycrab - 博客频道 - CSDN.NET
Download Qt, the cross-platform application framework | Qt Project Qt 5.2.1 for Windows 64-bit (VS 2 ...
- 在微信小程序中使用富文本转化插件wxParse
在微信小程序中我们往往需要展示一些丰富的页面内容,包括图片.文本等,基本上要求能够解析常规的HTML最好,由于微信的视图标签和HTML标签不一样,但是也有相对应的关系,因此有人把HTML转换做成了一个 ...
- Python处理json字符串转化为字典
有一个需求,需要用python把json字符串转化为字典 inp_str = " {'k1':123, 'k2': '345','k3','ares'} " import json ...
- Python如何将整数转化成二进制字符串
Python 如何将整数转化成二进制字符串 1.你可以自己写函数采用 %2 的方式来算. >>> binary = lambda n: '' if n==0 else binary( ...
随机推荐
- jsonp 简单封装
import originJSONP from 'jsonp' // 引入 jsonp 模块 // 对外暴露方法 jsonp // 通常传给服务端的 url 地址带参数 设计目的是希望有纯净的 url ...
- python编程之如何在Windows上安装python
一.安装python 首先检查你的系统里是否安装了python,开始菜单里点击运行输入cmd打开一个命令窗口,或键盘快捷键windows+R打开,在窗口中输入python并回车,如果出现了Python ...
- 02.02.03第3章 餐饮项目案例(Power BI商业智能分析)
02.02.03第3章 餐饮项目案例 02.02.03.01餐饮数据理解与读入 00:06:12 02.02.03.02餐饮数据处理 00:29:57 处理生成的表为: 02.02.03.03餐饮数据 ...
- Linux 第十六天
十六.服务管理 1.服务分类 1)RPM包默认安装的服务:包括独立的服务.基于xinetd的服务 2)源码包安装的服务 3)RPM安装服务和源码包安装服务的区别就是安装位置的不同 >源码包安装在 ...
- Python的基本类型介绍和可变不可变
Python的基本类型介绍 前言 做python有一段时间了,从工作开始就在不断地学习和积累.但是有时候用到一些技术点,甚至是基础知识的时候,总是会遗忘.所以,从今天开始,就在这里记录下来,不仅可以分 ...
- openmp入门总结
Ref: https://wdxtub.com/2016/03/20/openmp-guide/ 简介 这门课作为 ECE 中少有的跟计算机科学相关的课,自然是必上不可.不过无论是 OpenMP 还是 ...
- lab-kvm
3)qemu帮助信息 qemu-kvm -h [root@Centos72 libvirt]#qemu-kvm -h QEMU emulator version (qemu-kvm--.el7_5.) ...
- 整理CSS中display flex(布局利器)
关于display:flex布局,有人了解颇深,我也是看着别人的东西学习的. display:flex的布局是什么.基本概念之类的我根本就不了解,只会用.每次看到概念之类的东西,我都是扫一眼就过去. ...
- 《python语言程序设计》_第二章笔记
#2.2_编写一个简单的程序 项目1: 设计:radius=20,求面积area? 程序: radius=20 #给变量radius复制area=radius*radius*3.14159 #编写ar ...
- 2018/9/6 spring框架的整理
spring知识的巩固整理AOP和ioc概念,以及了解到了为何要使用spring框架的目的,作用:变换资源获取的方向.更像是按需所求.配置bean的方式:利用XML的方式,基于注解的方式两种.1通过全 ...