Python 文件读取
1、CSV 文件存储
1.1 写入
简单示例
import csv
with open('data.csv', 'a') as csvfile:
writer = csv.writer(csvfile) # 初始化写入对象,传入文件句柄
writer.writerow(['id', 'name', 'age']) # 调用 writerow() 方法传入每行的数据
writer.writerow(['1', 'rose', '18'])
writer.writerow(['2', 'john', '19'])
以文本方式打开,分隔符默认为逗号(,):
id,name,age
1,rose,18
2,john,19
修改默认分隔符:
writer = csv.writer(csvfile, delimiter=' ') # 以空格为分隔符
同时写入多行:
# 此时参数为二维列表
writer.writerow([['1', 'rose', '18'], ['2', 'john', '19']])
避免出现空行,可以在写入时加 newline=''
:
with open("test.csv", "a+", newline='') as csvfile:
如果数据源是字典
import csv
with open('data1.csv', 'a') as csvfile:
fieldnames = ['id', 'name', 'age'] # 定义表头
writer = csv.DictWriter(csvfile, fieldnames=fieldnames) # 初始化一个字典,将文件句柄和表头传入
writer.writeheader() # 写入表头
writer.writerow({'id': '1', 'name': 'rose', 'age': 18}) # 写入表格中具体内容
编码问题,需要指定 open()
函数编码格式:
open('data.csv', 'a', encoding='utf-8')
另外 pandas
库的 DataFrame
对象的 to_csv()
方法也可以将数据写入 csv 中。
1.2 读取
import csv
with open('data1.csv', 'r') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
print(row)
结果如下:
['id', 'name', 'age']
['1', 'rose', '18']
Tips:如果有中文需要指定文件编码
pandas 库的 read_csv() 方法
import pandas as pd
df = pd.read_csv('data.csv')
print(df)
运行结果如下:
id name age
0 1 rose 18
1 2 john 19
1.3 避免重复插入表头
#newline的作用是防止每次插入都有空行
with open("test.csv", "a+", newline='') as csvfile: # 必须使用 a+,追加方式
writer = csv.writer(csvfile)
#以读的方式打开csv 用csv.reader方式判断是否存在标题。
with open("test.csv", "r", newline="") as f:
reader = csv.reader(f)
if not [row for row in reader]:
writer.writerow(["型号", "分类"])
writer.writerows([[keyword, miaoshu]])
else:
writer.writerows([[keyword, miaoshu]])
示例
爬取一下该网站的所有评论:https://www.bestbuy.ca/en-ca/product/hp-hp-officejet-pro-6968-all-in-one-inkjet-printer-with-fax-6968/10441056/review
import requests
import time
import csv
headers = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) "
"Version/11.0 Mobile/15A372 Safari/604.1",
"Referer": "https://www.bestbuy.ca/en-ca/product/hp-hp-officejet-pro-6968-all-in-one-inkjet-printer-with-fax-"
"6968/10441056/review"
}
def get_content(url):
"""爬取数据"""
res = requests.get(url=url, headers=headers)
# print(res.status_code)
return res.json()
def parse_res(res):
"""解析数据"""
csv_data = {}
# print(res, type(res))
data = res["reviews"]
for i in data:
csv_data["title"] = i["title"]
csv_data["comment"] = i["comment"]
csv_data["publish"] = i["reviewerName"]
csv_data["publish_time"] = i["submissionTime"]
print(csv_data)
save_data(csv_data)
def save_data(csv_data):
"""存储数据"""
with open('data.csv', 'a+', newline='') as csvfile:
# 以读的方式打开 csv,判断表格是否有数据
with open('data.csv', 'r', newline='') as f:
reader = csv.reader(f)
fieldnames = ['title', 'comment', 'publish', 'publish_time']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames) # DictWriter: 字典
if not [row for row in reader]:
writer.writeheader()
writer.writerow(csv_data)
else:
writer.writerow(csv_data)
if __name__ == '__main__':
for i in range(1, 11):
url = 'https://www.bestbuy.ca/api/v2/json/reviews/10441056?source=all&lang=en-CA&pageSize=10&page=%s' \
'&sortBy=date&sortDir=desc' % i
res = get_content(url)
time.sleep(2)
parse_res(res)
参考文章:https://blog.csdn.net/qq_41817302/article/details/88680886
1.4 避免读取第一行表头
import csv
l = []
FileObj = open('t.csv')
readerObj = csv.reader(FileObj)
for row in readerObj:
if readerObj.line_num == 1: # readerObj.line_num 会返回 csv 文件的行数
continue
l.append(row)
print(l)
FileObj.close()
[['1', 'rose', '18'], ['2', 'lila', '19']]
2. JSON 文件存储
2.1 读取 JSON
import json
s = '''
[{
"name": "rose",
"gender": "female",
"age": "18"
}]
'''
data = json.loads(s)
print(data)
print(type(data))
运行结果如下:
[{'name': 'rose', 'gender': 'female', 'age': '18'}]
<class 'list'> # 因为最外层是列表
读取 JSON 文件
with open('data.json', 'r') as f:
s = f.read()
data = json.loads(s)
print(data)
2.2 输出 JSON
import json
data = [{
"name": "rose",
"gender": "female",
"age": "18"
}]
with open('data.json', 'a') as f:
f.write(json.dumps(data))
缩进 2 个字符,这样结构更清晰:
with open('data.json', 'a') as f:
f.write(json.dumps(data, indent=2))
运行结果如下:
[
{
"name": "rose",
"gender": "female",
"age": "18"
}
]
如果输出的包含中文,须臾指定参数 ensure_ascii=False
,否则默认转换为 Unicode
字符:
with open('data.json', 'a') as f:
f.write(json.dumps(data, indent=2, ensure_ascii=False))
3. configparser 模块
基本方法
- 读取配置文件
defaults()
:返回默认DEFAULT
的值,类型字典read(filename)
:读取配置文件内容sections()
:返回所有section
, 类型列表options(section)
:返回指定section
的键值对items(section)
:获取指定 section 所有的键值对get(section, option)
获取指定 section 中 option 的值getint(section, option)
获取指定 section 中option 的值,以 int 类型返回getfloat(section, option)
获取指定 section 中 option 的值,以 float 类型返回getboolean(section, option)
获取指定section 中 option 的值,以 boolean类型返回
- 写入配置文件
add_section(section)
添加指定的新的 sectionhas_section(section)
判断是否存在指定的 sectionset(section, option, value)
设置指定 section 中 option 的值remove_section(section)
删除指定 sectionremove_option(section, option)
删除指定 section 中的 optionwrite(fileobject)
将内容写入配置文件
1. 示例:读取、写入 DEFAULT
import configparser
cf = configparser.ConfigParser()
cf.read("user", encoding="utf-8")
cf["DEFAULT"] = {
"name": 'rose',
"age": 18,
"gender": "female"
}
with open("user", 'w')as f:
cf.write(f)
# 读取
result_dict = cf.defaults() # 获取默认 DEFAULT,没有就返回空的字典 OrderedDict()
print(result_dict)
运行结果:
[DEFAULT]
name = rose
age = 18
gender = female
OrderedDict([('name', 'rose'), ('age', '18'), ('gender', 'female')])
2. 示例二:逐行读取(读取单个 option)
def read_ini(section, option):
"""读取 ini 文件"""
try:
config = configparser.RawConfigParser()
config.read('ui', encoding='gbk')
content = config.get(section, option)
return content
except Exception as ex:
print(ex)
3. 读取所有key-value
1、user
[audio]
name = rose
age = 18
gender = female
[video]
width = 1980
height = 1080
2、读取所有 key-value
:
def read():
"""读取配置文件"""
results = {}
cf = configparser.ConfigParser()
cf.read('user', encoding='gbk')
# 全部读取并写入到字典中
for section in cf.sections():
temp = {section: {}}
options = cf.options(section)
for i in options:
temp[section].update({i: cf.get(section, i)})
results.update(temp)
print('results===>', results)
return results
运行结果:{'audio': {'name': 'rose', 'age': '18', 'gender': 'female'}, 'video': {'width': '1980', 'height': '1080'}}
4. 以字典形式存取
cf = configparser.ConfigParser()
cf['encode'] = {
'bitrate_type': 0,
'bitrate': 25,
'goplen': 40,
}
cf['system'] = {
'version': '1.0.2',
'hmode': 1686
}
with open("ui", "w+") as f:
cf.write(f)
5. 写入
def user_write(self, results: dict):
"""将用户信息写入配置文件
{"mac": {"mac": "1111111111"}}
"""
cf = configparser.ConfigParser()
results_dic = {k1: v1 for k1, v1 in results.items() if isinstance(v1, dict)}
for k2, v2 in results_dic.items():
if not .cf.has_section(k2):
cf.add_section(k2)
for k3, v3 in v2.items():
if not cf.has_option(k2, k3):
cf.set(k2, k3, v3)
with open('user', 'w+') as f:
cf.write(f)
参考
configparser
模块的基本方法:https://www.cnblogs.com/gexbooks/p/12103709.html
- python:利用
configparser
模块读写配置文件:https://www.cnblogs.com/imyalost/p/8857896.html
4. shutil 模块
复制、改名和删除文件、文件夹
4.1 复制文件和文件夹
copy(source, dest)
:拷贝文件,返回被拷贝文件后的路径(字符串)copytree(source, dest)
:拷贝文件夹/目录,返回被拷贝文件夹后的路径(字符串)
a、b 两个文件夹在同级目录,a 中有一个文件 s1.py
,b 中为空:
>>> import shutil
>>> shutil.copy('a/s1.py', 'b') # 使用默认名称
'b\\s1.py'
>>> shutil.copy('a/s1.py', 'b/s2.py') # 重新命名
'b/s2.py'
>>> shutil.copytree('a', 'b\\a')
'b\\a'
4.2 文件和文件夹的移动和重命名
- 移动文件,原有文件将会被删除,返回新位置的绝对路径
- 若目标路径是一个文件夹,那么文件将被移动到文件夹中
- 若目标路径不存在,那么将重命名为那个路径
- 若目标路径中存在同名文件,则会被覆盖
>>> shutil.move('a\\s1.py', 'b')
'b\\s1.py'
# c 文件夹不存在,s1.py 重命名为 c
>>> shutil.move('b\\s1.py', 'c')
'c'
# 重命名
>>> shutil.move('b\\s1.py', 'a\\s2.py')
'a\\s2.py'
4.3 删除文件和文件夹
os.unlink(path)
:删除path
处的文件os.rmdir(path)
:删除path
处的文件夹,该文件夹必须为空shutil.rmtree(path)
:删除path
处所有文件及文件夹
4.4 安全删除文件
send2transh
模块不会永久删除文件,而是将其移动到回收站,以便恢复,而 os.unlink()、shutil.rmtree()
是永久删除:
pip install send2trash
send2trash.send2trash('a.py')
4.5 遍历目录树
os.walk(path)
返回:
- 当前文件夹
- 当前文件夹中的子文件夹字符串列表
- 当前文件夹中的文件字符串列表
目录结构:
a
- b
- s1.py
s1.py
b
示例:
# -*- coding: utf-8 -*-
import os
for folderName, subfolders, filenames in os.walk('a'):
print('当前文件夹:', folderName)
for subfolder in subfolders:
print('子文件夹:', subfolder)
for filename in filenames:
print('文件:', filename)
# >>> for folderName, subfolders, filename in os.walk('a'):
# ... print('当前文件夹:{},当前文件夹中子文件的字符串列表:{},当前文件夹中文件字符串列表:{}'.format(folderName, subfolders, filename))
# ...
# 当前文件夹:a,当前文件夹中子文件的字符串列表:['b'],当前文件夹中文件字符串列表:['s1.py']
# 当前文件夹:a\b,当前文件夹中子文件的字符串列表:[],当前文件夹中文件字符串列表:[]
运行结果:
当前文件夹: a
子文件夹: b
文件: s1.py
当前文件夹: a\b