文件存储
- 内容概括
- 11.1 write_file 写入文件
- 11.2 read_write_lines文件读写行
- 11.3 fileput_demo另一种文件操作方法
- 11.4 read_search_xml读取XML文件
- 11.5 dict to xml 字典转xml文件方法
- 11.6 xml to dict xml文件转字典类型
- 11.7 json to dict JSON字符串转字典
- 11.8 json to class JSON字符串转换成CLASS类
- 11.9 class to json CLASS类转JSON字符串
- 11.10 classlist to json 对象列表和JSON字符串转换
- 11.11 json to xml JSON字符串转XML文件
- 11.12 write_csv 写入CSV文件
- 11.13 read_csv 读取CSV文件
- 11.14 实战案例:抓取豆瓣音乐排行榜写入CSV文件
内容概括
保存文件有多种形式,主要包括XML文件、CSV文件、JSON文件
主要内容:
1、操作文件的基础方式
2、使用Fileput对象读取文件
3、读写XML文件
4、读写JSON文件
5、XML数据、JSON数据和Python对象之间的相互转换
6、读写CSV文件
11.1 write_file 写入文件
open函数和使用方法
open函数用于打开文件,第1个参数指明文件路径(绝对相对都可以),第2个参数指明文件操作模式
文件模式 描述
r 读模式(默认)
w 写模式
x 排他的写模式(只能用户自己写)
a 追加模式
b 二进制模式(可添加到其他模式中使用)
t 文本模式(默认值,可添加到其他模式中使用)
+ 读写模式(必须与其他文件模式一起使用)
# wirte(string):向文件写入内容,该方法返回写入文件的字节数
# read[n]:读取文件的内容,n是一个整数,表示从文件指针指定位置读取n个字节,如不指定,该方法会读取从当前往后的所有字节
# seek(n):重新设置指针,也就是改变文件的当前位置(偏移量)
# close():关闭文件
实操案例:
# 一些模式打开test1.txt文件
f = open('./files/test1.txt','w')
# 向test1.txt写入"i love",运行结果:7
print(f.write('I love '))
# 向test1.txt写入"python",运行结果:6
print(f.write('python'))
f.close()
# 以读的模式打开test1.txt
f = open('./files/test1.txt','r')
# 从test1.txt文件中读取7个字节的数据,运行结果I love
print(f.read(7))
# 从当前位置开始读取6个字节的数据,运行结果python
print(f.read(6))
f.close()
try:
# 如果test2.txt文件不存在,会抛出异常
f = open('./files/test2.txt','r+')
except Exception as e:
print(e)
# 用追加可读写模式打开test2.txt文件
f = open('./files/test2.txt','a+')
# 向test2.txt文件写入hello
print(f.write('hello'))
f.close()
f = open('./files/test2.txt','a+')
# 读取test2.txt文件,由于目前文件指针已经在文件的结尾,所以什么都不会读出来
print(f.read())
# 将文件指针设置到指针开始的位置
f.seek(0)
# 读取全部文件内容,hello
print(f.read())
f.close()
try:
# 用可读写的方式打开test2.txt文件,将文件内容会清空
f = open('./files/test2.txt','w+')
# 读取文件的全部内容,什么都没读出来
print(f.read())
# 向文件写入“How are you?”
f.write('How are you?')
# 重置文件指针到文件的开始位置
f.seek(0)
# 读取文件的全部内容,运行结果How are you?
print(f.read())
finally:
f.close()
11.2 read_write_lines文件读写行
操作方法:
通过readline方法、readlines方法、writelines方法对urls.txt文件进行读写操作
- readline读取文件中一行的数据
- readlines读取文件中所有行的数据
- writelines写入文件多行数据
实操案例:
import os
f = open('./files/urls.txt','r+')
url = ''
while True:
# 从urls.txt读一行文本
url = f.readline()
# 将最后的行结束符去掉
url = url.rstrip()
# 当读上来的是空串就结束循环
if url == '':
break
else:
print(url)
print('_____________________________________')
f.seek(0)
# 读urls中所有的行
print(f.readlines())
# 向urls.txt文件中添加一个新行
f.write('https://jiketiku.com' + os.linesep)
f.close()
# 使用'a+'模式再次打开urls.txt文件
f = open('./files/urls.txt','a+')
# 定义一个要写入的urls.txt列表
urlList = ['https://geekori.com' + os.linesep, 'https://www.google.com' + os.linesep]
# 将urlList写入urls.txt文件
f.writelines(urlList)
# 关闭urls.txt文件
f.close()
11.3 fileput_demo另一种文件操作方法
操作方法:
- 使用fileinput.input方法读取urls.txt文件,通过for循环获取每一行值
- 同时调用fileinpout.filename方法
- fileinput.lineno方法分别获取正在读取的文件名和当前的行号
实操案例:
import fileinput
# 使用input方法打开urls.txt文件
fileobj = fileinput.input('./files/urls.txt')
# 输出fileobj类型
print(type(fileobj))
# 读取urls.txt文件第1行
print(fileobj.readline().rstrip())
# 通过for循环输出urls.txt文件的其他行
for line in fileobj:
line = line.rstrip()
# 如果file不等于空串,输出当前行号和内容
if line != '':
print(fileobj.lineno(),':',line)
else:
print(fileobj.filename())
11.4 read_search_xml读取XML文件
操作方法:
读取XMl文件需要导入xml.etree.ElementTree,并通过该模块的parse函数读取XML文件
实操案例:
products.xml文件
<!-- products.xml -->
<root>
<products>
<product uuid='1234'>
<id>10000</id>
<name>iPhone9</name>
<price>9999</price>
</product>
<product uuid='4321'>
<id>20000</id>
<name>特斯拉</name>
<price>800000</price>
</product>
<product uuid='5678'>
<id>30000</id>
<name>Mac Pro</name>
<price>40000</price>
</product>
</products>
</root>
from xml.etree.ElementTree import parse
# 开始分析products.xml文件,files/products.xml是要读取的XML文件的名字
doc = parse('files/products.xml')
# 通过Xpath搜索子节点集合,然后对这个子节点集合进行迭代
for item in doc.iterfind('products/product'):
# 读取product节点的id子节点的值
id = item.findtext('id')
# 读取product节点的name子节点的值
name = item.findtext('name')
# 读取product节点的price子节点的值
price = item.findtext('price')
# 读取product节点的uuid子节点的值
print('uuid=',item.get('uuid'))
print('id=',id)
print('name=',name)
print('price=',price)
print('__________________________________________________')
11.5 dict to xml 字典转xml文件方法
操作方法:
- 将一个字典类型的变量转换为XMl字符串
- 然后使用parseString函数解析整个XML字符串
- 并用带缩进格式的形式将XMl字符串写入persons.xml文件
实操案例;
import dicttoxml
from xml.dom.minidom import parseString
import os
# 定义一个字典
d = [20,'names',
{'name':'Bill','age':30,'salary':2000},
{'name':'王军','age':34,'salary':3000},
{'name':'John','age':25,'salary':2500}]
# 将字典转换为XML格式(bytes形式)
bxml = dicttoxml.dicttoxml(d, custom_root = 'persons')
# 将bytes形式的XML数据按utf-8编码格式解码成XMl字符串
xml = bxml.decode('utf-8')
print(xml)
# 解析XML字符串
dom = parseString(xml)
# 生成带缩进格式的XML字符串
prettyxml = dom.toprettyxml(indent=' ')
# 创建files目录
os.makedirs('files',exist_ok=True)
# 以只写和utf-8编码格式的方式打开persons.xml文件
f = open('./files/persons.xml','w',encoding='utf-8')
# 将格式化的XML字符写入persons.xml文件
f.write(prettyxml)
f.close()
生产的persons.xml文件:
<?xml version="1.0" ?>
<persons>
<item type="int">20</item>
<item type="str">names</item>
<item type="dict">
<name type="str">Bill</name>
<age type="int">30</age>
<salary type="int">2000</salary>
</item>
<item type="dict">
<name type="str">王军</name>
<age type="int">34</age>
<salary type="int">3000</salary>
</item>
<item type="dict">
<name type="str">John</name>
<age type="int">25</age>
<salary type="int">2500</salary>
</item>
</persons>
11.6 xml to dict xml文件转字典类型
操作方法:
- 从products.xml文件中读取一个XMl字符串
- 并使用xmltodict模块的parse模块来解析XML字符串
- 如果格式正确,parse函数可以返回字典对象
实操案例:
import xmltodict
# 打开products.xml
f = open('files/products.xml','rt',encoding="utf-8")
xml = f.read()
# 分析XMl字符串,并转化为字典
d = xmltodict.parse(xml)
print(d)
print('_________________________________________________')
f.close()
# 使用pprint模块可读性更好
import pprint
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(d)
11.7 json to dict JSON字符串转字典
操作方法:
- 将data的字典转换为JSON字符串
- 然后将JSON字符串s通过eval函数转换为字典
- 最后从products.json文件中读取SJON字符串,并使用loads函数和eval函数两种方法将JSON字符串转换为字典
实操案例:
products.json文件内容:
[
{
"name":"iPhone9",
"price":9999,
"count":3000},
{"name":"特斯拉",
"price":800000,
"count":122}
]
import json
data = {
'name':'Bill',
'company':'Microsoft',
'age':34
}
# 将字典转换为JSON字符串
jsonStr = json.dumps(data)
print(type(jsonStr))
print(jsonStr)
# 将JSON字符串转换为字典
data = json.loads(jsonStr)
print(type(data))
print(data)
# 定义一个JSON字符串
s = '''
{
'name' : 'Bill',
'company' : 'Microsoft',
'age' : 34
}
'''
# 使用eval函数将JSON字符串转换为字典
data = eval(s)
print(type(data))
print(data)
# 输出字典中key为company的值
print(data['company'])
# 打开products.json文件中的所有内容
f = open('./files/products.json','r',encoding='utf-8')
jsonStr = f.read()
# 使用eval函数将JSON字符串转换为字典
json1 = eval(jsonStr)
# 使用loads函数将JSON字符串转换为字典
json2 = json.loads(jsonStr)
print(json1)
print(json2)
print(json2[0]['name'])
f.close()
11.8 json to class JSON字符串转换成CLASS类
操作使用:
- 指定类:loads函数会自动创建指定类的实例,并将由JSON字符串转换成的字典通过类的构造方法传入类实例
- 指定回调函数:loads函数会调用回调函数返回类实例,并将有JSON字符串转换成的字典传入回调函数,必须有一个参数可以接收字典
实操案例:
从product.json文件读取JSON字符串,然后分别通过指定类(Product)和指定回调函数(json2Product)的方式将JSON字符串转换为Product对象
- product.json文件内容:
{"name":"iPhone9",
"price":9999,
"count":3000}
- json2class.PY文件内容:
import json
class Product:
# d参数式要传入的字典
def __init__(self, d):
self.__dict__ = d
# 打开product.json文件
f = open('files/product.json','r')
# 从product.json文件中读取JSON字符串
jsonStr = f.read()
my1 = json.loads(jsonStr, object_hook=Product)
# 下面3行代码输出Product对象中相应属性的值
print(type(my1))
print('name=',my1.name)
print('price=',my1.price)
print('count',my1.count)
print('________________________________________________________________')
# 定义用于将字典转换为Product对象的函数
def json2Product(d):
return Product(d)
# 通过指定类回调函数的方式将JSON字符串转换为Product对象
my2 = json.loads(jsonStr, object_hook=json2Product)
# 下面3行代码输出Product对象中相应属性的值
print(type(my2))
print('name=',my2.name)
print('price=',my2.price)
print('count',my2.count)
f.close()
11.9 class to json CLASS类转JSON字符串
操作方法:
- dumps函数不仅可以将字典转换为JSON字符串,还可以将类实例转换为JSON字符串
- dumps函数需要通过default关键字参数指定一个回调函数,在转换的过程中,dumps函数会向这个回调函数传入类实例
操作实例:
创建一个类和构造函数,将其实例化,再调用dumps方法将对象转换成JSON字符串
import json
class Product:
# 通过类的构造方法初始化3个属性
def __init__(self,name,price,count):
self.name = name
self.price = price
self.count = count
# 用于将Product类的实例转换为字典的函数
def product2Dict(obj):
return {
'name':obj.name,
'price':obj.price,
'count':obj.count
}
# 创建Product类的实例
product = Product('特斯拉',10000000,20)
# 将Product类的实例转换为JSON字符串
jsonStr = json.dumps(product,default=product2Dict,ensure_ascii=False)
print(type(jsonStr))
print(jsonStr)
11.10 classlist to json 对象列表和JSON字符串转换
操作方法:
- 从products.json文件读取JSON字符串
- 并通过loads函数将其转换为Product对象列表,
- 然后再通过dumps函数将Product对象列表转换为JSON字符串
实操案例:
products.json文件与前面的一样
import json
class Product:
def __init__(self,d):
self.__dict__ = d
f = open('files/products.json','r',encoding='utf-8')
jsonStr = f.read()
# 将JSON字符串转换为Product对象列表
products = json.loads(jsonStr,object_hook=Product)
# 输出Product对象列表中所有Product对象的相关属性值
for product in products:
print(type(product))
print('name=', product.name)
print('price=', product.price)
print('count=', product.count)
f.close()
# 定义将Product对象转换为字典的函数
def product2Dict(product):
return {
'name':product.name,
'price':product.price,
'count':product.count
}
# 将Product对象列表转换为JSOn字符串
jsonStr = json.dumps(products, default=product2Dict,ensure_ascii=False)
print(jsonStr)
11.11 json to xml JSON字符串转XML文件
操作方法:
- 从products.json文件中读取json字符串
- 将json字符串转换成字典类型
- 将字典类型转换成XML文件
实操案例:
import json
import dicttoxml
f = open('files/products.json','r',encoding='utf-8')
jsonStr = f.read()
# 将JSON字符串转换为字典
d = json.loads(jsonStr)
print(d)
# 将字典转换为XML字符串
xmlStr = dicttoxml.dicttoxml(d).decode('utf-8')
print(xmlStr)
f.close()
11.12 write_csv 写入CSV文件
操作方法:
读写方法和读写文件类似,使用open方法打开csv文件,操作符用 w 写模式
实操案例:
import csv
# 打开files/data.csv文件,如果不存在,会重新创建一个data.csv
with open('files/data.csv','w',encoding='utf-8') as f:
writer = csv.writer(f)
# 写入数据
writer.writerow(['产品ID','产品名称','生产企业','价格'])
writer.writerow(['0001','iPhone9','Apple',9999])
writer.writerow(['0002','特斯拉','特斯拉',12345])
writer.writerow(['0003','荣耀手机','华为',3456])
# 修改字段分隔符
with open('files/data1.csv', 'w', encoding='utf-8') as f:
writer = csv.writer(f, delimiter=';')
writer.writerow(['产品ID', '产品名称', '生产企业', '价格'])
writer.writerow(['0001', 'iPhone9', 'Apple', 9999])
writer.writerow(['0002', '特斯拉', '特斯拉', 12345])
writer.writerow(['0003', '荣耀手机', '华为', 3456])
# 一次性写入多行
with open('files/data2.csv','w',encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['产品ID','产品名称','生产企业','价格'])
writer.writerows([['0001','iPhone9','Apple',9999],
['0002', '特斯拉', '特斯拉', 12345],
['0003', '荣耀手机', '华为', 3456]])
# 写入字典形式的数据
with open('files/data3.csv','w',encoding='utf-8') as f:
fieldnames = ['产品ID','产品名称','生产企业','价格']
writer = csv.DictWriter(f,fieldnames=fieldnames)
writer.writeheader()
writer.writerow({'产品ID': '0001', '产品名称': 'iPhone9', '生产企业': 'Apple', '价格': 9999})
writer.writerow({'产品ID': '0002', '产品名称': '特斯拉', '生产企业': '特斯拉', '价格': 12345})
writer.writerow({'产品ID': '0003', '产品名称': '荣耀手机', '生产企业': '华为', '价格': 3456})
# 追加数据
with open('files/data.csv','a',encoding='utf-8') as f:
fieldnames = ['产品ID','产品名称','生产企业','价格']
writer = csv.DictWriter(f,fieldnames=fieldnames)
writer.writerow({'产品ID': '0004', '产品名称': '量子战衣', '生产企业': '斯塔克工业', '价格': 99999999999})
11.13 read_csv 读取CSV文件
操作方法:
读写方法和读写文件类似,使用open方法打开csv文件,操作符用 r 写模式
实操案例:
读取11.12案例中的data.csv文件,对其进行操作
import csv
# 打开要读取的CSV文件
with open('files/data.csv','r',encoding='utf-8') as f:
# 创建reader对象
reader = csv.reader(f)
# 获取每一行的数据
for row in reader:
print(row)
# 导入pandas模块
import pandas as pd
# 读取data.csv文件的数据
df = pd.read_csv('files/data.csv')
print(df)
11.14 实战案例:抓取豆瓣音乐排行榜写入CSV文件
操作方法:
- 使用requests网络库请求页面
- 使用Beautiful Soup解析库分析内容
- 解析出需要的内容
- 将内容写入CSV文件
实操案例:
import requests
from bs4 import BeautifulSoup
import re
import csv
import time
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36'
}
def get_url_music(url):
html = requests.get(url,headers=headers)
soup = BeautifulSoup(html.text, 'lxml')
aTags = soup.find_all("a",attrs={"class": "nbg"})
for aTag in aTags:
get_music_info(aTag['href'])
def save_csv(filename,info):
with open(filename, 'a', encoding='utf-8') as f:
fieldnames = ['name', 'author', 'style', 'time','publisher','score']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writerow(info)
def get_music_info(url):
html = requests.get(url,headers=headers)
soup = BeautifulSoup(html.text, 'lxml')
name = soup.find (attrs={'id':'wrapper'}).h1.span.text
author = soup.find(attrs={'id':'info'}).find('a').text
styles = re.findall('<span class="pl">流派:</span> (.*?)<br />', html.text, re.S)
if len(styles) == 0:
style = '未知'
else:
style = styles[0].strip()
time = re.findall('发行时间:</span> (.*?)<br />', html.text, re.S)[0].strip()
publishers = re.findall('<span class="pl">出版者:</span> (.*?)<br />', html.text, re.S)
if len(publishers) == 0:
publisher = '未知'
else:
publisher = publishers[0].strip()
score = soup.find(class_='ll rating_num').text
info = {
'name': name,
'author': author,
'style': style,
'time': time,
'publisher': publisher,
'score': score
}
print(info)
save_csv(filename,info)
if __name__ == '__main__':
urls = ['https://music.douban.com/top250?start={}'.format(str(i)) for i in range(0,250,25)]
filename = 'music.csv'
with open(filename, 'w', encoding='utf-8') as f:
fieldnames = ['name', 'author', 'style', 'time', 'publisher', 'score']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
for url in urls:
get_url_music(url)
time.sleep(1)
结果截图: