Python中的io模块是用来处理各种类型的I/O操作流。主要有三种类型的I/O类型:文本I/O(Text I/O),二进制I/O(Binary I/O)和原始I/O。它们都是通用类别,每一种都有不同的后备存储。属于这些类别中的任何一个的具体对象称为文件对象,其他常用的术语为流或者类文件对象。
除了它的类别,每一种具体的流对象也具有各种功能:它仅仅允许读,或者仅仅允许写,或者既能读又能写。它也允许任意随机访问,或者仅仅顺序访问。
所有的流对于提供给它们的数据的数据类型都很严格。例如,如果用一个二进制流的write()方法写一个字符类型的数据,那么将会触发一个TypeError错误。用文本流的write()方法来写字节对象数据也是一样的,会触发该错误。
文本文件IO
Text I/O期望输入和产生的是字符对象。这意味着无论何时,本地存储都是存储字节组(比如在文件中),数据的编码和解码是透明的,特定平台中换行符字符的翻译也是透明的(windows下换行翻译为:\r\n,而linux中为\n,mac中则又不同,但是这些跨平台的换行符Text I\O会自动根据操作系统平台来转换)。
最简单的创造文本流的方法就是用open()函数,指定编码格式是可选的。
f = open("myfile.txt", "r", encoding = "utf-8")
- 1
内存中的文本流也可以通过StringIO对象得到:
f = io.StringIO("some initial text data")
- 1
文本流的api细节描述在文档中的TextIOBase部分。
二进制IO
Binary I/O希望输入的是类字节对象,创造的是字节组对象。不会执行编码,解码和换行符转换操作。这种类型的流可以用于各种无文本数据,或者还需要手动控制的正在处理的文本数据时。
最简单的构造二进制流的方法就是用open(),在模式串中加上’b’
f = open("myfile.jpg", "rb")
- 1
内存中的二进制流也可以用BytesIO对象来创造:
f = io.BytesIO(b"some initial binary data: \x00\x01")
- 1
二进制流api详细的描述细节在文档中的BufferedIOBase部分。
其他库模块可能提供一些额外的方法来创造文本流或二进制流。
这里就将信息保存在xml文件中,想到得到的文件如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <orderlist> 3 <order> 4 <customer>姓名1</customer> 5 <phone>电话1</phone> 6 <address>地址1</address> 7 <count>点餐次数1</count> 8 </order> 9 <order> 10 <customer>姓名2</customer> 11 <phone>电话2</phone> 12 <address>地址2</address> 13 <count>点餐次数2</count> 14 </order> 15 </orderlist>
Python写xml比较简单,直接使用minidom即可。
思路也比较简单,因为dom文档就是一棵树,每一个标签都是一个节点,包括文本内容也是节点,因此从根节点开始,把节点一级一级的插入即可。
在上一篇中已经将抓取的信息存入了字典orderDict中,这里我们直接在类Order中添加一个方法,将orderDict里面的每一项信息插入DOM树,然后再写入本地xml文件。
由于比较简单,直接给出代码:
1 from xml.dom.minidom import Document 2 # 将self.orderDict中的信息写入本地xml文件,参数filename是xml文件名 3 def writeInfoToXml(self, filename): 4 # 创建dom文档 5 doc = Document() 6 7 # 创建根节点 8 orderlist = doc.createElement('orderlist') 9 # 根节点插入dom树 10 doc.appendChild(orderlist) 11 12 # 依次将orderDict中的每一组元素提取出来,创建对应节点并插入dom树 13 for (k, v) in self.orderDict.iteritems(): 14 # 分离出姓名,电话,地址,点餐次数 15 (name, tel, addr, cnt) = (v[0], k, v[1], v[2]) 16 17 # 每一组信息先创建节点<order>,然后插入到父节点<orderlist>下 18 order = doc.createElement('order') 19 orderlist.appendChild(order) 20 21 # 将姓名插入<order>中 22 # 创建节点<customer> 23 customer = doc.createElement('customer') 24 # 创建<customer>下的文本节点 25 customer_text = doc.createTextNode(name) 26 # 将文本节点插入到<customer>下 27 customer.appendChild(customer_text) 28 # 将<customer>插入到父节点<order>下 29 order.appendChild(customer) 30 31 # 将电话插入<order>中,处理同上 32 phone = doc.createElement('phone') 33 phone_text = doc.createTextNode(tel) 34 phone.appendChild(phone_text) 35 order.appendChild(phone) 36 37 # 将地址插入<order>中,处理同上 38 address = doc.createElement('address') 39 address_text = doc.createTextNode(addr) 40 address.appendChild(address_text) 41 order.appendChild(address) 42 43 # 将点餐次数插入<order>中,处理同上 44 count = doc.createElement('count') 45 count_text = doc.createTextNode(str(cnt)) 46 count.appendChild(count_text) 47 order.appendChild(count) 48 49 # 将dom对象写入本地xml文件 50 with open(filename, 'w') as f: 51 f.write(doc.toprettyxml(indent='\t', encoding='utf-8')) 52 53 return
在先调用getAllOrders方法之后,再调用writeInfoToXml即可将所有信息写入xml文件中。