常用模块的使用
Xml模块
什么XML:全称 可扩展标记语言
标记指的是代表某种含义的字符 XML<>
为什么需要XML
为能够在不同的平台间继续数据的交换
为了使交换的数据能让对方看懂 就需要按照一定的语法规范来书写
XML语法格式:
一、任何的起始标签都必须有一个结束标签。 <tagname></tagname> <tagname></tagname> <tagname/> 简化写法 二、可以采用另一种简化语法,可以在一个标签中同时表示起始和结束标签。这种语法是在大于符号之前紧跟一个斜线(/),例如<百度百科词条/>。XML解析器会将其翻译成<百度百科词条></百度百科词条>。 三、标签必须按合适的顺序进行嵌套,所以结束标签必须按镜像顺序匹配起始标签,例如这是一串百度百科中的样例字符串。这好比是将起始和结束标签看作是数学中的左右括号:在没有关闭所有的内部括号之前,是不能关闭外面的括号的。 <tag1> <tag2> <tag3> </tag3> </tag2> </tag1> 关闭标签应该从内往外 一层一层关闭 顺序不能乱 四、所有的特性都必须有值。 特性指的是属性 <person name=""> </person> 五、所有的特性都必须在值的周围加上双引号。 注意:最外层有且只有一个标签 这个标签称之为根标签 第一行应该有文档声明 用于高速计算机怎么理解 例如:<?xml version="1.0" encoding="utf-8"?> 当标签嵌套的时候会出现层级关系 如果一个标签不被任何别的标签包裹 那他就是根标签(最外层)
使用场景:
1.配置文件
2.常规的数据交换 例如从服务器获取一段新闻
与json的区别: 作用是一样的 都是一种数据格式 xml比json先诞生 json的数据比xml小 目前json是主流 python中的xml处理 使用到的模块 ElmentTree 表示整个文件的元素树 Elment 表示一个节点 属性 1.text 开始标签和结束标签中间的文本 2.attrib 所有的属性 字典类型 3.tag 标签的名字 方法 get 获取某个属性的值 1.解析XML 查找标签 find 在子标签中获取名字匹配第一个 findall 在子标签中获取名字匹配的所有标签 iter(tagname) 在全文中查找[匹配的所有标签 返回一个迭代器 2.生成XML 用ElmentTree parse() 解析一个文件 getroot() 获取根标签 write() 写入到文件 3.修改xml set 一个属性 remove 一个标签 append 一个标签 import xml.etree.ElementTree as et # 读取xml文档到内存中 得到一个包含所有数据的节点树 # 每一个标签就称之为一个节点 或 元素 # tree = et.parse("text.xml") # # 获取根标签 # root = tree.getroot() # # 获取所有的country 找的是第一个 # print(root.find("country")) # # 找的是所有 # print(root.findall("country")) # # # 获取year # print(root.iter("country")) # for i in root.iter("country"): # print(i) # # # # 遍历整个xml # for country in root: # print(country.tag,country.attrib,country.text) # for t in country: # print(t.tag, t.attrib, t.text) # # # # print(root.find("country").get("name")) # =============================================修改 第所有的country的year文本 改成加1 # 读取到内存 tree = et.parse("text.xml") for country in tree.findall("country"): # yeartag = country.find("year") # yeartag.text = str(int(yeartag.text) + 1) 修改标签文本 # country.remove(country.find("year")) 删除标签 # 添加子标签 newtag = et.Element("newTag") # 文本 newtag.text = "123" #属性 newtag.attrib["name"] = "DSB" #添加 country.append(newtag) # 写回到内存 tree.write("text.xml",encoding="utf-8",xml_declaration=False)
用代码生成一个xml文档
import xml.etree.ElementTree as et # 创建根标签 root = et.Element("root") # 创建节点树 t1 = et.ElementTree(root) # 加一个peron标签 persson = et.Element("person") persson.attrib["name"] = "yyh" persson.attrib["sex"] = "man" persson.attrib["age"] = "20" persson.text = "这是一个person标签" root.append(persson) # 写入文件 t1.write("newXML.xml",encoding="utf-8",xml_declaration=True)
Shelve模块
什么是shelve模块
也是种序列化方式
使用方法
1.opne
2.读写
3.close
特点: 使用方法比较简单 提供一个文件名字就可以开始读写
读写的方法和字典一致
你可以把它当成带有自动序列化功能的字典
原理: 内部使用的就是pickle 所以 也存在跨平台性差的问题 你自己存的只有你自己知道怎么取
什么时候用:写一个单机程序时可以考虑
import shelve # 序列化 # sl = shelve.open("shelvetest.txt") # sl["date"] = "8-13" # sl["list1"] = ["123","456"] # sl.close() # 反序列化 s2 = shelve.open("shelvetest.txt") print(s2.get("list1")) s2.close()
configParser模块
configparser 是什么? 配置文件解析模块
什么是配置文件?
用于提供程序运行所需要的一些信息的文件 后缀 ini cfg
有什么用?
方便用户修改 例如超时时间
配置文件内容格式
只包括两种元素
section 分区
option 选项
一个文件可以有多个section
一个section可以有多个选项
核心功能
1.sections 获取所有分区
2.options 获取所有选项
3.get 获取一个值 传入 section option
注意:大小写不敏感
# 假装做一个下载功能 最大链接速度可以由用户来控制 用户不会看代码 所以提供一个配置文件
import configparser # 得到配置文件对象 cfg = configparser.ConfigParser() # 读取一个配置文件 cfg.read("download.ini") print(cfg.sections()) print(cfg.options("section1")) print(type(cfg.get("section1","maxspeed"))) print(type(cfg.getint("section1","maxspeed"))) print(cfg.getint("section2","minspeed")) # 修改最大速度为2048 cfg.set("section1","maxspeed","2048") cfg.write(open("download.ini","w",encoding="utf-8"))
Hashlib模块
hashlib
hash是什么?
是一种算法
用于将任意长度的数据,压缩映射到一段固定长度的字符 (提取特征)
hash的特点:
1.输入数据不同,得到的hash值有可能相同
2.不能通过hash值来得到输入的值
3.如果算法相同,无论输入的数据长度是多少,得到的hash值长度相同
因为以上特点常将hash算法用于加密和文件校验
输入用户名和密码 在代码中与数据库中的判断是否相同
思考当你的数据需要在网络中传递时 就可能会受到网络攻击
黑客通过抓包工具就能截获你发送和接收的数据
所以你的数据 如果涉及到隐私 就应该先加密在发送
加密的方式有很多
常用的MD5就是一种hash算法
常用的提升安全性的手段 就是加盐
就是把你加密前的数据做一些改动 例如 把顺序反过来
import hashlib md = hashlib.md5() md.update("hello你这么牛逼吗 你破解我试试? DSB".encode("utf-8")) print(md.hexdigest())
# 破解MD5可以尝试撞库 原理: 有一个数据库 里面存放了常见的明文和密文的对应关系 ,
# 所以我可以拿着一个密文取数据库中查找 有没有已经存在的明文 如果有撞库成功 能不能破解凭运气
# 假设我已经拿到了一个众多账号中的一个密码 我可以那这个密码 挨个测试你的所有账号 可能不能碰到运气
pwd_dic = {"123456":"e10adc3949ba59abbe56e057f20f883e","hello":"5d41402abc4b2a76b9719d911017c592"} for i in pwd_dic: if pwd_dic[i] == "5d41402abc4b2a76b9719d911017c592": print(i)
# 今后我们在写一些需要网络传输的程序时 如果要进行加密 最好把加密的算法搞得更复杂
# 密码长度为6位
# abcdef
# 在前面加一个 abc 在后面加一个 cba 完事以后在加密
pwd = "abcdef" # pwd = "abc"+pwd+"cba" md2 = hashlib.md5() md2.update("121".encode("utf-8")) md2.update(pwd.encode("utf-8")) md2.update("akjasjkasa".encode("utf-8")) print(md2.hexdigest()) # 加密实际上能做的就是让黑客的的破解成本大于他的利润 # sha = hashlib.sha512() # sha.update("abcd".encode("utf-8")) # print(len(sha.hexdigest())) # import hmac h = hmac.new("121212".encode("utf-8")) h.update("abcd".encode("utf-8")) print(h.hexdigest())
Re 模块
一:什么是正则?
正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
RE是什么
正则 表达 式子
就是一些带有特殊含义的符号或者符号的组合
它的作用是对字符串进行过滤
在一堆字符串中找到你所关心的内容
你就需要告诉计算机你的过滤规则是什么样 通过什么方式来告诉计算机 就通过正则表达式
第一步 学习正则表达式 各种符号所表示的含义
re模块的内部实现 不是python 而是调用了c库
二:常用匹配模式(元字符)
http://blog.csdn.net/yufenghyc/article/details/51078107
补充
import re # 待处理字符串 src = "abcdef \t 12121gaa1a _ - a * / \n a" # 在字符串中查找所有满足条件的 # print(re.findall("ab",src)) # \w字母数字下划线 \W非字母数字下划线 与前面相反 # print(re.findall("\w",src)) # print(re.findall("\W",src)) # \s 所有不可见字符 \S 可见字符 # print(re.findall("\s",src)) # print(re.findall("\S",src)) # \d 所有数字 \D所有非数字 # print(re.findall("\d",src)) # print(re.findall("\d",src)) # 特殊字符直接匹配 # print(re.findall("\n",src)) # print(re.findall("\t",src)) # . 除了\n以外任意字符 # print(re.findall(".",src)) # print(re.findall("\d","abcdef \t 12121gaa1a _ - a * / \n a")) # \s \w \d . 都是匹配单个字符 # 匹配重复字符 * + ? {} # * 前面的表达式出现任意次 # print(re.findall("\w\d*","1 12 aa")) # +重复1次或多次 # print(re.findall("\d+","1 12121272163871asas6378232678a aa")) # ?表示重复0次或1次 # print(re.findall("\d?","aa bb a1c 1c1 123")) # {m,n} 最少m次 最多n次 # print(re.findall("\d{1,3}","1 12 123 1234 ")) # {m} 必须是m次 print(re.findall("[a-z]{2}","a aa aaa ssss")) # {,m} 最大m次 0-m print(re.findall("[a-z]{,3}","a aa aaa a1aa")) # 从字符串1982asasa中找到所有0 1 2 # 匹配范围 # | 0|1|2 或 # print(re.findall("0|1|2","1982asasa")) # [] 字符集合 括号内的符号不是整体 # print(re.findall("[012]","1982asasa")) # ============================================ 在范围匹配时使用脱字符表示取反 # 在这里表示除了0-9之外的任意字符 # print(re.findall("[^012]","1982asasa")) # 请找出 所有的数字0-9和字母a-z A-Z 注意 减号只有在两个字符中间才有范围的意思 在两边都是普通字符 # print(re.findall("[0-9a-zA-Z]","1982asa+sa")) # ^ 匹配行首 # print(re.findall("^h","hellohello")) # # # $ 匹配行未 注意写在表达式后面 # print(re.findall("[a-z]oh$","lohhel9ohelloh")) # 单词边界 指的是单词的末尾 print(re.findall("h\\b","helloh hih")) print(re.findall("h\\B","hellhoh hih")) # 双斜杠?? print(re.findall("a\\\\c","aakakja\c")) # 贪婪匹配 * + 不是固定的特殊符号 只是一种现象 # 会一直匹配到不满足条件为止 用问号来阻止贪婪匹配(匹配最少满足条件的字符数) print(re.findall("\w+?","ajshsjkdsd")) print(re.findall("\w*?","ajshsjkdsd")) # 说明时候需要阻止贪婪 src = "<img src='www.baidupic.shuaiqi1.jpg'><img src='www.baidupic.shuaiqi2.jpg'><img src='www.baidupic.shuaiqi3.jpg'>" # () 用于给正则表达式分组(group) 不会改变原来的表达式逻辑意义 # 效果 优先取出括号内的内容 # 请用正则表达式取图片地址 print(re.findall("src='(.+?)'",src)) # 了解 加上?: 可以取消括号中的优先级 print(re.findall("src='(?:.+?)'",src)) print(re.findall("src='(?:www).(?:baidupic)",src))
re模块常用方法
findall 从左往右查找所有满足条件的字符 返回一个列表
search 返回第一个匹配的字符串 结果封装为对象 span=(0, 5) 匹配的位置 match匹配的值
match 匹配行首 返回值与search相同
对于search match 匹配的结果通过group来获取
compile 将正则表达式 封装为一个正则对象 好处是可以重复使用这个表达式
import re print(re.search("hello"," world hello python")) print(re.match("hello"," world hello python")) print(re.split("hello","world hello python",maxsplit=0)) # pattern = re.compile("hello") # print(pattern.search("world hello python",3)) # print(re.sub("hello","gun","world hello Java")) # 现有字符串如下 src = "c++|java|python|shell" # 用正则表达式将c 和shell换位置 # print(re.sub("([a-zA-Z]+)|","",src)) # 先用分组将 内容 分为三个 1.c++ 2.|java|python| 3.shell print(re.findall("(.+?)(\|.+\|)(.+)",src)) print(re.sub("(.+?)(\|.+\|)(.+)",r"\3\2\1",src)) # print(re.search("(.+?)(\|.+)\|(.+)",src).group(3)) # print(re.sub("(.+)(\|.+\|)(.+)",r"\3\2\1",src)) # print(re.search("(.+?)\|",src))
subprocess
什么是进程
正在进行中的程序 每当打开一个程序就会开启一个进程
每个进程包含运行程序所需的所有资源
正常情况下 不可以跨进程访问数据
但是有些情况写就需要访问别的进程数据 提供一个叫做管道的对象 专门用于跨进程通讯
作用:用于执行系统命令
常用方法
run 返回一个表示执行结果的对象
call 返回的执行的状态码
总结 subprocess的好处是可以获取指令的执行结果
subprocess执行指令时 可以在子进程中 这样避免造成主进程卡死