想学习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

  1. # -*- coding=utf-8 -*-
  2.  
  3. def lines(file):
  4. '''
  5. 给每个段落强制添加一个空行
  6. '''
  7. for line in file :
  8. yield line
  9. yield '\n'
  10.  
  11. def blocks(file):
  12. '''
  13. 将输入的文件按按空行分块
  14. '''
  15. block = []
  16.  
  17. for line in lines(file):
  18. if line.strip():
  19. # line不是空行,属于一个块
  20. block.append(line)
  21. elif block:
  22. # 当前行是空行,block不为空,块已经结束,返回块
  23. yield ''.join(block).strip()
  24. block = []

handler.py

  1. # -*- coding=utf-8 -*-
  2.  
  3. class Handler:
  4. def callback(self, prefix, name, *args):
  5. method = getattr(self, prefix+name, None)
  6. if callable(method):
  7. return method(*args)
  8. def start(self, name):
  9. self.callback('start_', name)
  10. def end(self, name):
  11. self.callback('end_', name)
  12. def sub(self, name):
  13. def subtitution(match):
  14. result = self.callback('sub_', name, match)
  15. if result is None:
  16. match.group(0)
  17. return subtitution
  18.  
  19. class HTMLRender(Handler):
  20. def start_document(self):
  21. print '<html><head><title>...</title></head><body>'
  22. def end_document(self):
  23. print '</body>'
  24. def start_paragraph(self):
  25. print '<p>'
  26. def end_paragraph(self):
  27. print '</p>'
  28. def start_head(self):
  29. print '<h2>'
  30. def end_head(self):
  31. print '</h2>'
  32. def start_title(self):
  33. print '<h1>'
  34. def end_title(self):
  35. print '</h1>'
  36. def start_list(self):
  37. print '<ul>'
  38. def end_list(self):
  39. print '</ul>'
  40. def start_listitem(self):
  41. print '<li>'
  42. def end_listitem(self):
  43. print '</li>'
  44. def sub_em(self, match):
  45. return '<em>%s</em>' % match.group(1)
  46. def sub_url(self, match):
  47. return '<a href="%s">%s</a>' % (match.group(1), match.group(1))
  48. def sub_email(self, match):
  49. return '<a href="mailto:%s">%s</a>' % (match.group(1), match.group(1))
  50. def feed(self, data):
  51. print data

rule.py

  1. # -*- coding=utf-8 -*-
  2.  
  3. class Rule:
  4. def action(self, block, handler):
  5. handler.start(self.type)
  6. handler.feed(block)
  7. handler.end(self.type)
  8. return True
  9.  
  10. class HeadRule(Rule):
  11. '''
  12. 小标题的规则,没有换行符,长度小于70并且不以:结尾
  13. '''
  14.  
  15. type = 'head'
  16. def condition(self, block):
  17. return not '\n' in block and len(block) < 70 and block[-1] != ':'
  18. class TitleRule(HeadRule):
  19. '''
  20. 标题的规则,第一行是就是标题
  21. '''
  22. type = 'title'
  23. first = True
  24. def condition(self, block):
  25. if not self.first:
  26. return False
  27. self.first = False
  28. return HeadRule.condition(self, block)
  29. class ListItemRule(Rule):
  30. '''
  31. li的规则,如果block以-开头就是listitem,在显示的时候去除-
  32. '''
  33.  
  34. type = 'listitem'
  35. def condition(self, block):
  36. return block[0] == '-'
  37. def action(self, block, handler):
  38. handler.start(self.type)
  39. handler.feed(block[1:].strip())
  40. handler.end(self.type)
  41. return True
  42.  
  43. class ListRule(ListItemRule):
  44. '''
  45. ul的规则,第一个li开始之前,添加ul,在第一个不是li的时候结束ul
  46. '''
  47. type = 'list'
  48. inside = False
  49. def condition(self, block):
  50. return True
  51. def action(self, block, handler):
  52. if not self.inside and ListItemRule.condition(self, block):
  53. handler.start(self.type)
  54. self.inside = True
  55. elif self.inside and not ListItemRule.condition(self, block):
  56. handler.end(self.type)
  57. # 每次返回False,在对block使用完本规则之后继续使用其他规则
  58. return False
  59.  
  60. class ParagraphRule(Rule):
  61. '''
  62. p段落规则,当前面所有的规则匹配的时候,默认使用本规则
  63. '''
  64.  
  65. type = 'paragraph'
  66. def condition(self, block):
  67. return True

parse.py

  1. # -*- coding=utf-8
  2. import re, sys
  3. from util import *
  4. from handler import *
  5. from rule import *
  6. import ipdb
  7.  
  8. class Parser:
  9. '''
  10. 解析器,利用rule对文本进行解析并转换为html,利用filter转换块内文本
  11. '''
  12.  
  13. def __init__(self, handler):
  14. self.handler = handler
  15. self.rules = []
  16. self.filters = []
  17. def addRule(self, rule):
  18. self.rules.append(rule)
  19. def addFilter(self, pattern, name):
  20. def filter(block, handler):
  21. return re.sub(pattern, handler.sub(name), block)
  22. self.filters.append(filter)
  23. def parse(self, file):
  24. #pdb.set_trace()
  25. self.handler.start('document')
  26. for block in blocks(file):
  27. ipdb.set_trace()
  28. for filter in self.filters:
  29. block = filter(block, self.handler)
  30. for rule in self.rules:
  31. if rule.condition(block):
  32. last = rule.action(block, self.handler)
  33. if last:
  34. break
  35. self.handler.end('document')
  36.  
  37. class BasicTextParser(Parser):
  38. '''
  39. 基本文本解析器,只有h1,h2,p,ul,li,a,em,email
  40. '''
  41.  
  42. def __init__(self, handler):
  43. Parser.__init__(self, handler)
  44. self.addRule(ListRule())
  45. self.addRule(ListItemRule())
  46. self.addRule(TitleRule())
  47. self.addRule(HeadRule())
  48. self.addRule(ParagraphRule())
  49.  
  50. self.addFilter(r'\*(.+?)\*', 'em')
  51. self.addFilter(r'(http://[\.a-zA-Z]+)', 'url')
  52. self.addFilter(r'([\.a-zA-Z]+@[\.a-zA-Z]+[[a-zA-Z]+)', 'email')
  53.  
  54. handler = HTMLRender()
  55. parser = BasicTextParser(handler)
  56. 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. day 34

    1 .内容回顾 #__author : 'liuyang' #date : 2019/4/17 0017 上午 9:01 # 利大于弊,则做之 # 会死于斯,则不去 # 2个 人 晚上 5个题 面试题 ...

  2. SAS 函数

    SAS 函数 SAS函数是编程语言的一个组件,可接受参数.执行计算或进行其他操作并返回值.返回值是字符型或数值型的结果,可用于赋值语句或 表达式中.SAS包含很多函数,也可以自定义函数.在BASE S ...

  3. 【翻译】Flume 1.8.0 User Guide(用户指南) source

    翻译自官网flume1.8用户指南,原文地址:Flume 1.8.0 User Guide 篇幅限制,分为以下5篇: [翻译]Flume 1.8.0 User Guide(用户指南) [翻译]Flum ...

  4. apt-get update 问题

    W: 仓库 “cdrom://Ubuntu 16.04.1 LTS _Xenial Xerus_ - Release amd64 (20160719) xenial Release” 没有 Relea ...

  5. Visual Studio学习记录

    1,一些快捷键记录 1,折叠 ctrl+M+A: 折叠所有代码[官方名:折叠所有大纲提示] ctrl + M + O:折叠全部代码[官方:折叠到定义],但是这个貌似只能折叠代码,xml之类的无效.m+ ...

  6. How to setup Visual Studio without pain

    Visual Studio (VS) can be very hard to install. If you are lucky, one whole day may be enough to ins ...

  7. Nginx 代理配置

    1.反向代理 修改conf\nginx.conf文件, 添加proxy_pass属性 server { listen 7080; #nginx 端口 server_name localhost; #n ...

  8. oracle远程连接服务器数据库

    oracle远程连接数据库,需要配置本地服务,具体步骤如下: 1. 2.添加新的服务 3.输入服务名(例如:orcl3即服务器数据库名) 4.选择TCP协议 5.输入服务器IP(192.268.10. ...

  9. IntelliJ IDEA 和谐地址及快捷键

    转载:http://my.oschina.NET/dyyweb/blog/494504 http://blog.csdn.net/tanlon_0308/article/details/5085473 ...

  10. display:inline-block; 在css中是什么意思?

    inline-block主要的用处是用来处理行内非替换元素的高宽问题的!行内非替换元素,比如span.a等标签,正常情况下士不能设置宽高的,加上该属性之后,就可以触发让这类标签表现得如块级元素一样,可 ...