想学习python已经很久了,以前使用ArcGIS的时候学习过一些简单的python语法,用来进行一些简单的GIS数据处理,但是后来并没有用到工作中也就荒废了,后来断断续续看过一些,最近想学习一门新的语言,就拿python下手了,仔细考(拼)虑(凑)出以下理由(喜欢就是喜欢,不用理由):

  • python强大库支持,在科学计算、人工智能等高精尖的领域使用甚广
  • 在运维中也算是除shell外的第二语言吧
  • 学习渗透测试的时候很多poc都是使用python写的,为了不仅仅停留在使用工具上,进一步学习
  • 在web中python也是快速开发的利器

本次学习主要是《python基础教程》第二版,简单回顾了前面几章基础知识后,开始拿后面的练习来学习,虽然代码大部分是直接参考书中源码,但是“纸上得来终觉浅,绝知此事要躬行”可不是废话,学习这件事不动手就是耍流氓,在自己动手编写书中例子的时候对python的语法和思想理解逐渐加深。先来一发


为了避免直接上代码略显突兀,显写出这个练习项目的思路:

先撇开具体实现,想想如果要实现将文本转化位html的做法:

  1. 文本一定时满足一定规则的
  2. 读取文本内容
  3. 根据预定义的规则分析读入的文本内容
  4. 符合某一种规则的文本加上对应的html标签
  5. 继续读入文本,回到2继续处理

再回来书中的项目,本项目共包含四个模块

  1. util.py:负责对文本进行一定的格式化,并读取文本
  2. rule.py:定义什么样的文本可以转化为什么样的html,两件事儿:
    1. 定义文本和html对应的规则
    2. 决定规则对应的处理程序(handler)
  3. handler.py:将给定规则的文本转换为html
  4. 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的更多相关文章

  1. 15.Python文本转化语音方法

    1.用pywin32模块来将文本转化为语音 通过pip install pywin32安装模块,pywin32是个万金油的模块,太多的场景使用到它,但在文本转语音上,它却是个青铜玩家,简单无脑但效果不 ...

  2. 【NLP】Python NLTK获取文本语料和词汇资源

    Python NLTK 获取文本语料和词汇资源 作者:白宁超 2016年11月7日13:15:24 摘要:NLTK是由宾夕法尼亚大学计算机和信息科学使用python语言实现的一种自然语言工具包,其收集 ...

  3. python Django教程 之模板渲染、循环、条件判断、常用的标签、过滤器

    python3.5 manage.py runserver python Django教程 之模板渲染.循环.条件判断.常用的标签.过滤器 一.Django模板渲染模板 1. 创建一个 zqxt_tm ...

  4. Python数据类型之“文本序列(Text Sequence)”

    Python中的文本序列类型 Python中的文本数据由str对象或字符串进行处理. 1.字符串 字符串是Unicode码值的不可变序列.字符串字面量有多种形式: 单引号:'允许嵌入"双&q ...

  5. Selenium2+python自动化23-富文本(自动发帖)

    前言 富文本编辑框是做web自动化最常见的场景,有很多小伙伴遇到了不知道无从下手,本篇以博客园的编辑器为例,解决如何定位富文本,输入文本内容 一.加载配置 1.打开博客园写随笔,首先需要登录,这里为了 ...

  6. python实现的文本编辑器 - Skycrab - 博客频道 - CSDN.NET

    Download Qt, the cross-platform application framework | Qt Project Qt 5.2.1 for Windows 64-bit (VS 2 ...

  7. 在微信小程序中使用富文本转化插件wxParse

    在微信小程序中我们往往需要展示一些丰富的页面内容,包括图片.文本等,基本上要求能够解析常规的HTML最好,由于微信的视图标签和HTML标签不一样,但是也有相对应的关系,因此有人把HTML转换做成了一个 ...

  8. Python处理json字符串转化为字典

    有一个需求,需要用python把json字符串转化为字典 inp_str = " {'k1':123, 'k2': '345','k3','ares'} " import json ...

  9. Python如何将整数转化成二进制字符串

    Python 如何将整数转化成二进制字符串 1.你可以自己写函数采用 %2 的方式来算. >>> binary = lambda n: '' if n==0 else binary( ...

随机推荐

  1. FileReader实现图片预览,并上传(js代码)

    var rFilter = /^(image\/bmp|image\/gif|image\/jpeg|image\/png|image\/tiff)$/i; //控制格式 var iMaxFilesi ...

  2. 前端json导入excel中

    ExportToExcel: function () { var param = {}; var _this = this; param.beginDate = $("#beginDate& ...

  3. 如何安装ubuntu系统

    https://www.cnblogs.com/Chinasf/archive/2010/05/06/1728840.html    [Ubuntu 下挂ISO到虚拟光驱的方法] 各种方法参考如下论坛 ...

  4. 登陆页、注册页、会员中心页logo图的替换

                  关闭   PHP在线开发笔记       目录视图 摘要视图 订阅 异步赠书:9月重磅新书升级,本本经典           程序员9月书讯      每周荐书:ES6.虚 ...

  5. <笔记>更新某条数据库记录必须更新所有字段

    今天用TP更新数据库数据时,用id得到模型对象,再通过该对象更新其他字段的数据,发现报错

  6. Ubuntu 离线安装 docker

    1.下载离线包,网址:https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/ 离线安装docker需要下载3个 ...

  7. [纪录片] 鸟瞰中国 ——China from Above

    上周末我看了一部纪录片<鸟瞰中国>,觉得特别有意思,想要分享给你. 制作背景 <鸟瞰中国>是由中国五洲传播中心与美国国家地理频道联合拍摄的纪录片,由KNNY PNG.KLAUS ...

  8. SQL Server 2008 安装(lpt亲测)

    SQL Server安装真的遇到好多问题啊!!  于是就决定写个备忘,方便自己也方便别人. 1.下载安装包 2.打开安装包,就遇到了restart computer 那里failed的错误,导致无法继 ...

  9. java.lang.OutOfMemoryError: PermGen space (jvm内存泄漏解决办法)

    2.在myeclipse根目录 打开myeclipse.ini 3.在myeclipse中配置内存

  10. Xftp5软件使用详解

    一.首先运行Xftp5,然后导航栏上面有个小加号,点击进去. 二.接着出现如下界面,在这里填写名称(这个随意填写),主机填写要连接的主机的IP地址,然后协议的话,Linux系统一般选择SFTP协议,端 ...