Python之旅的第2^4天(shelvexml模块和re模块部分)
Posted 崆峒山肖大侠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python之旅的第2^4天(shelvexml模块和re模块部分)相关的知识,希望对你有一定的参考价值。
实在是没想到今天的内容会这么精彩,特别是re模块,我激动了,这不就是数据抓取的基础吗?哈哈哈
一、shelve模块
import shelve # shelve模块,功能上类似于json和pickle,但是操作起来比较简单,是将传入数据转化为一个字典 # 但是在写入过程中我们看不到字典的存在,同时不能跨语言进行传输 # f = shelve.open(r‘shelve_test1‘) #此时会生成3个文件,但是你完全不用理会,因为你看不懂 # f[‘stu1_info1‘] = {‘name‘:‘alex‘,‘age‘:18} #将传入的字典{‘name‘:‘alex‘,‘age‘:18} 变成一个v值, # # 与我们写入的‘stu1_info1‘行程一个键值对,就是转换成为字典 # f[‘stu1_info2‘] = {‘name‘:‘zhoujielun‘,‘age‘:28} # f[‘shelve_test‘] = {‘k1‘:‘v1‘} # f.close() # print(f.get(‘stu1_info1‘)[‘name‘]) #用f.get(k值)获取你要找到的字典,然后用字典内的k值得到对应的v #输出结果为:‘alex‘
二、xml模块
# 关于xml模块的引入 import xml.etree.ElementTree as ET #部分调用的模块由于名称太长,我们可以定义缩写 #as后面跟随的内容就是缩写 # xml当然就是用来解析xml文件的 # 首先引入xml的文件内容,这里要明白xml中标签(tag)、属性(attrib)、标签数值(text) # 下面是xml文件内的内容,请对照进行操作 # <data> # <country name="Liechtenstein"> # <rank updated="yes">2</rank> # <year updated="yes">2010</year> # <gdppc>141100</gdppc> # <neighbor direction="E" name="Austria" /> # <neighbor direction="W" name="Switzerland" /> # </country> # <country name="Singapore"> # <rank updated="yes">5</rank> # <year updated="yes">2013</year> # <gdppc>59900</gdppc> # <neighbor direction="N" name="Malaysia" /> # </country> # <country name="Panama"> # <rank updated="yes">69</rank> # <year updated="yes">2013</year> # <gdppc>13600</gdppc> # <neighbor direction="W" name="Costa Rica" /> # <neighbor direction="E" name="Colombia" /> # </country> # </data> # 以文件内容的第三行为例<rank updated="yes">2</rank> # 其中<rank></rank> ‘rank‘就是xml文件中的标签值 # updated = "yes" 就是rank的属性 # 两个括号中间的‘2‘就是他们的数值 #ET.parse 打开一个xml文件,这里的parse的意思是解析,即为解析一个文件 # tree = ET.parse(‘xml_lesson‘) #这时我们就将打开文件的句柄复制给了tree,这里用tree命名非常合适 #xml文件机构非常像一棵树,树根<data> 第一次分叉<country> # <country>下面还会分出很多分支标签、对应的数值和属性 # tree.getroot() 就是获得根节点的意思 # root = tree.getroot() # print(root) #输出的结果:<Element ‘data‘ at 0x0000028F1BB4A318> #得到这样的结果就表示,root是一个对象,是可以被遍历的 #我们可以尝试去打印root下一级的子标签 # for i in root: # print(i.tag) #输出了data下面包含的三个country #我们再向下便利一层 # for a in i: # print(a.tag) #输出rank、year、gdppc、neighbor、neighbor三次 # #表示三个country下面的所有对应标签内容 #.attrib 就是刚才介绍在第一个尖括号里面出现的等号两边的连起来的东西 #<rank updated="yes">2</rank> 里面的updated="yes"就是属性 # for i in root: # print(i.attrib) #输出{‘name‘: ‘Liechtenstein‘}、{‘name‘: ‘Singapore‘}、{‘name‘: ‘Panama‘} # #分别是<data>下面三个country中对应的属性 name="Liechtenstein" 等 # #最终表现形式是以字典的形式输出的 # print(root.attrib) #root 即<data>没有属性值,所以输出一个空的字典 # .text 获取其中的值,<rank updated="yes">2</rank>当中的2 # for child in root: # print(child.tag, child.attrib) # for i in child: # print(i.tag, i.attrib, i.text) # # 输出结果是: # country {‘name‘: ‘Liechtenstein‘} # rank {‘updated‘: ‘yes‘} 2 # year {‘updated‘: ‘yes‘} 2010 # gdppc {} 141100 # neighbor {‘direction‘: ‘E‘, ‘name‘: ‘Austria‘} None # neighbor {‘direction‘: ‘W‘, ‘name‘: ‘Switzerland‘} None # country {‘name‘: ‘Singapore‘} # rank {‘updated‘: ‘yes‘} 5 # year {‘updated‘: ‘yes‘} 2013 # gdppc {} 59900 # neighbor {‘direction‘: ‘N‘, ‘name‘: ‘Malaysia‘} None # country {‘name‘: ‘Panama‘} # rank {‘updated‘: ‘yes‘} 69 # year {‘updated‘: ‘yes‘} 2013 # gdppc {} 13600 # neighbor {‘direction‘: ‘W‘, ‘name‘: ‘Costa Rica‘} None # neighbor {‘direction‘: ‘E‘, ‘name‘: ‘Colombia‘} None #可以看出,没有返回值的时候返回None #.iter 指定遍历其中的某一个节点,比如‘year‘ # 请记住iter方法是放在了root根目录下进行执行的 # for node in root.iter(‘year‘): # print(node.tag, node.attrib, node.text) #输出结果: # year {‘updated‘: ‘yes‘} 2010 # year {‘updated‘: ‘yes‘} 2013 # year {‘updated‘: ‘yes‘} 2013 # 对其中year的值进行修改 # tree = ET.parse(‘xml_lesson‘) # root = tree.getroot() # for node in root.iter(‘year‘): # new_year = int(node.text) + 1 # node.text = str(new_year) # node.set(‘update‘,‘yes‘) # tree.write(‘xml_lesson‘) #此时对应的<year>部分的数值已经增加了1 #.remove 删除某一节点的内容 #.findall 感觉有点类似于iter,但是感觉只是用来找寻下一层的 #.find 感觉有点类似于iter, # 要求是删除掉<rank>值大于50的<country>所有信息 # for country in root.findall(‘country‘): # rank = int(country.find(‘rank‘).text) # if rank > 50: # root.remove(country) # tree.write(‘new_xml_lesson‘) #最终生成新文件,并删除了最后一个<country> #生成一个新的xml文件 # new_xml = ET.Element(‘new_xml_test.xml‘) # name = ET.SubElement(new_xml , ‘name‘ , attrib = {‘xiaowang‘: ‘alex‘}) # age = ET.SubElement(name , ‘age‘ ,attrib = {‘zhoujielun‘:‘18‘}) # sex = ET.SubElement(name, "sex") # sex.text = ‘33‘ #数值的写入方式很特别 # name2 = ET.SubElement(new_xml, "name", attrib={"enrolled": "no"}) # age = ET.SubElement(name2, "age") # age.text = ‘19‘ # # et = ET.ElementTree(new_xml) #表示生成文档对象 # et.write(‘test.xml‘,encoding = ‘utf-8‘,xml_declaration = True) #写入文件 # # ET.dump(new_xml) #打印生成的格式 #以上是xml的全部内容
三、re模块的元字符部分
import re # re模块,即正则表达式,主要针对字符串进行相关处理,由c语言编制而成,运行效率很高 # 是一个小型的高度专业的语言,主要用作模糊匹配 # re模块包含的元字符有 . ^ $ * + ? {} [] | () # 先引入一个re模块的方法re.findall(‘查找规则‘,‘查找内容‘) # 输出一个列表,表示找到的内容 # . 表示通配符,可以表示任何字符,一以对应 # print(re.findall(‘a..x‘,‘adasalexdasdaayex‘)) #输出:[‘alex‘, ‘ayex‘] # ^ 表示必须以尖角号后面的字符为开头 # print(re.findall(‘^a..x‘,‘alexdadsaalex‘)) #输出:[‘alex‘] 此时只能显示在最开始出现的‘alex‘ # $ 美元符,表示必须以美元符前面的字符为结尾 # print(re.findall(‘a..x$‘,‘alexdadsaalex‘)) #输出:[‘alex‘] 此时输出的‘alex‘是字符串最末尾的alex # * 和 + 分表表示该字符串出现次数为: # * 表示(0,正无穷大) # + 表示(1,正无穷大) #同时他们都是贪婪匹配,以匹配到最多为结果 # print(re.findall(‘alex*‘,‘aledsasfafa‘)) #[‘ale‘] # print(re.findall(‘alex*‘,‘alexxxxxsadada‘)) #[‘alexxxxx‘] # # print(re.findall(‘alex+‘,‘aledsasfafa‘)) #[] # print(re.findall(‘alex+‘,‘alexxxxxsadada‘)) #[‘alexxxxx‘] # ? 表示该字符匹配0或者1次 # print(re.findall(‘alex?‘,‘aledsasfafa‘)) #[‘ale‘] # print(re.findall(‘alex?‘,‘alexxxxxsadada‘)) #[‘alex‘] # {} 大括号,可以设定出现次数的范围,如果只填写一个数字,则表示指定了出现次数 # {0,正无穷} == * # {1,正无穷} == + # {0,1} == ? # [] 中括号是一个非常关键的符号,他表示其中任意一个与外面的匹配符合 # 在[]中,除了- ^ 三个特殊符号外,里面的任何符号都是没有意义的 # [] 中他们三个的意思分别是 # - 表示范围 # print(re.findall(‘x[a-z]‘,‘xdasdsaxdas‘)) #[‘xd‘, ‘xd‘] # print(re.findall(‘x[a-z]*‘,‘xdasdsaxdas‘)) #[‘xdasdsaxdas‘] 之所以这样是因为*是贪婪匹配,有多少拿多少 # print(re.findall(‘[a-z]*x‘,‘xdasdsaxdas‘)) #[‘xdasdsax‘] # print(re.findall(‘^[a-z]x‘,‘xdasdsaxdas‘)) #[] # ^ 表示非这些字符 # print(re.findall(‘[^a-z]x‘,‘9xdasdsa0xdas‘)) #[‘9x‘, ‘0x‘] # 转义符,好像括号内外都一样 # 首先是能让没意义的有意义 # d 匹配任何十进制数;它相当于类 [0-9]。 # D 匹配任何非数字字符;它相当于类 [^0-9]。 # s 匹配任何空白字符;它相当于类 [ fv]。 # S 匹配任何非空白字符;它相当于类 [^ fv]。 # w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。 # W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_] # 匹配一个特殊字符边界,比如空格 ,&,#等 # 能让有意义的没有意义 # 给了一个5+(9*8-5*(3-1)) # 取出3-1部分的内容 # a = ‘5+(9*8-5*(3-1))‘ # b = re.findall(‘([^()]*)‘,a) # print(b) #此时可得到[‘(3-1)‘] # * 和 + 后面增加上? # 会由原来的贪婪匹配,转换成为惰性匹配 # print(re.findall(‘alex*‘,‘alexxxxxsadada‘)) #[‘alexxxxx‘] # print(re.findall(‘alex*?‘,‘alexxxxxsadada‘)) #[‘ale‘] # # print(re.findall(‘alex+‘,‘alexxxxxsadada‘)) #[‘alexxxxx‘] # print(re.findall(‘alex+?‘,‘alexxxxxsadada‘)) #[‘alex‘] #关于re模块真非常神奇 #比如可以以身份证号为参考,获取以612开头的,并且是1990年之后出生的人的身份证号码 # 使用正则表达式 ^612...1990+* # 比如获取‘das12dadsa123asd45‘当中所有的数字d+即可实现
就是这些了,没想到今天的三个小时这么精彩,非常的激动,期待明天re的新发现哦
以上是关于Python之旅的第2^4天(shelvexml模块和re模块部分)的主要内容,如果未能解决你的问题,请参考以下文章