文章目录
1-文本打开方式
- r:以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
- rb:以二进制只读方式打开一个文件。文件指针将会放在文件的开头。
- r+:以读写方式打开一个文件。文件指针将会放在文件的开头。
- rb+:以二进制读写方式打开一个文件。文件指针将会放在文件的开头。
- w:⭐以写入方式打开一个文件。如果该文件已存在,则将其覆盖。如果该文件不存在,则创建新文件。
- wb:以二进制写入方式打开一个文件。如果该文件已存在,则将其覆盖。如果该文件不存在,则创建新文件。
- w+:以读写方式打开一个文件。如果该文件已存在,则将其覆盖。如果该文件不存在,则创建新文件。
- wb+:以二进制读写格式打开一个文件。如果该文件已存在,则将其覆盖。如果该文件不存在,则创建新文件。
- a:⭐以追加方式打开一个文件。如果该文件已存在,文件指针将会放在文件结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,则创建新文件来写入。
- ab:以二进制追加方式打开一个文件。如果该文件已存在,则文件指针将会放在文件结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,则创建新文件来写入。
- a+:以读写方式打开一个文件。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,则创建新文件来读写。
- ab+:以二进制追加方式打开一个文件。如果该文件已存在,则文件指针将会放在文件结尾。如果该文件不存在,则创建新文件用于读写。
2-文件写入方法
第一种
一定要记得close()
file = open('explore.txt', 'a', encoding='utf-8')
file.write('\n'.join([question, author, answer]))
file.write('\n' + '=' * 50 + '\n')
file.close()
第二种(推荐)
在 with 控制块结束时,文件会自动关闭,所以就不需要再调用 close 方法了。
with open('explore.txt', 'a', encoding='utf-8') as file:
file.write('\n'.join([question, author, answer]))
file.write('\n' + '=' * 50 + '\n')
3-TXT 文本存储
基本介绍
优点:将数据保存到 TXT 文本的操作非常简单,而且 TXT 文本几乎兼容任何平台。
缺点:不利于检索。
适用范围:如果对检索和数据结构要求不高,追求方便第一的话,可以采用 TXT 文本存储。
示例
保存知乎上 “发现” 页面的 “热门话题” 部分,将其问题和答案统一保存成文本形式。
首先,可以用 requests 将网页源代码获取下来,然后使用 pyquery 解析库解析,接下来将提取的标题、回答者、回答保存到文本,代码如下:
import requests
from pyquery import PyQuery as pq
url = 'https://www.zhihu.com/explore'
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
html = requests.get(url, headers=headers).text
doc = pq(html)
items = doc('.explore-tab .feed-item').items()
for item in items:
question = item.find('h2').text()
author = item.find('.author-link-line').text()
answer = pq(item.find('.content').html()).text()
file = open('explore.txt', 'a', encoding='utf-8')
file.write('\n'.join([question, author, answer]))
file.write('\n' + '=' * 50 + '\n')
file.close()
这里主要是为了演示文件保存的方式,因此 requests 异常处理部分在此省去。首先,用 requests 提取知乎的 “发现” 页面,然后将热门话题的问题、回答者、答案全文提取出来,然后利用 Python 提供的 open 方法打开一个文本文件,获取一个文件操作对象,这里赋值为 file,接着利用 file 对象的 write 方法将提取的内容写入文件,最后调用 close 方法将其关闭,这样抓取的内容即可成功写入文本中了。
运行程序,可以发现在本地生成了一个 explore.txt 文件,其内容如所示。
这里 open 方法的第一个参数即要保存的目标文件名称,第二个参数为 a,代表以追加方式写入到文本。另外,我们还指定了文件的编码为 utf-8。最后,写入完成后,还需要调用 close 方法来关闭文件对象。
4-JSON文件存储-import json
基本介绍
JSON,全称为 JavaScript Object Notation, 也就是 JavaScript 对象标记,它通过对象和数组的组合来表示数据,构造简洁但是结构化程度非常高,是一种轻量级的数据交换格式。
一个 JSON 对象可以写为如下形式:
[{
"name": "Bob",
"gender": "male",
"birthday": "1992-10-18"
}, {
"name": "Selina",
"gender": "female",
"birthday": "1995-10-18"
}]
由中括号包围的就相当于列表类型,列表中的每个元素可以是任意类型,这个示例中它是字典类型,由大括号包围。
JSON 可以由以上两种形式自由组合而成,可以无限次嵌套,结构清晰,是数据交换的极佳方式。
读取-json.loads()
import json
常用方法 | 描述 |
---|---|
json.loads() | 将 JSON 文本字符串转为 JSON 对象 返回的是列表,之后就可以用索引获取对应的元素 |
json.dumps() | 将 JSON 对象转为文本字符串 json.dumps(data, indent=2, ensure_ascii=False) 参数indent,代表缩进字符个数。这样得到的内容会自动带缩进,格式会更加清晰。 |
将json形式字符串转换为列表/字典
值得注意的是,JSON 的数据需要用双引号来包围,不能使用单引号。否则会出现json解析错误的提示。
例如,这里有一段 JSON 形式的字符串,它是 str 类型,我们用 Python 将其转换为可操作的数据结构,如列表或字典:
import json
str = '''
[{
"name": "Bob",
"gender": "male",
"birthday": "1992-10-18"
}, {
"name": "Selina",
"gender": "female",
"birthday": "1995-10-18"
}]
'''
print(type(str))
"""
<class'str'>
"""
data = json.loads(str) #这里使用loads 方法将字符串转为JSON对象。由于最外层是中括号,所以最终的类型是列表类型。
print(data)
print(type(data))
"""
[{'name': 'Bob', 'gender': 'male', 'birthday': '1992-10-18'}, {'name': 'Selina', 'gender': 'female', 'birthday': '1995-10-18'}]
<class 'list'>
"""
#可以用索引来获取对应的内容。
#例如,如果想取第一个元素里的 name 属性:
data[0]['name']
"""
Bob
"""
data[0].get('name')
"""
Bob
"""
获取键值时有两种方式,一种是中括号加键名,另一种是通过 get 方法传入键名。这里推荐使用 get 方法,这样如果键名不存在,则不会报错,会返回 None。另外,get 方法还可以传入第二个参数(即默认值),示例如下:
#获取年龄 age,其实在原字典中该键名不存在,此时默认会返回 None。
data[0].get('age')
"""
None
"""
#如果传入第二个参数(即默认值),那么在不存在的情况下返回该默认值。
data[0].get('age', 25)
"""
25
"""
利用json库读取json文件
有一个 data.json 文本文件,其内容是刚才定义的 JSON 字符串,我们可以先将文本文件内容读出,然后再利用 loads 方法转化:
import json
with open('data.json', 'r') as file:
str = file.read()
data = json.loads(str)
print(data)
"""
[{'name': 'Bob', 'gender': 'male', 'birthday': '1992-10-18'}, {'name': 'Selina', 'gender': 'female', 'birthday': '1995-10-18'}]
"""
利用pandas库读取json文件
可以利用pandas库的read_json读取json文件
import pandas as pd
data = pd.read_json()
保存为json文件-json.dumps()
调用 dumps 方法将 JSON 对象转化为字符串。
json.dumps(data, indent=2, ensure_ascii=False)
#参数indent,代表缩进字符个数。这样得到的内容会自动带缩进,格式会更加清晰。
#为了输出中文,还需要指定参数ensure_ascii为 False
例如,将上例中的列表重新写入文本:
import json
#利用 dumps 方法,将JSON对象转为字符串,然后再调用文件的 write 方法写入文本
data = [{
'name': 'Bob',
'gender': 'male',
'birthday': '1992-10-18'
}]
with open('data.json', 'w') as file:
file.write(json.dumps(data, indent=2, ensure_ascii=False))
5-CSV存储
CSV,全称为 Comma-Separated Values,中文可以叫作逗号分隔值或字符分隔值,其文件以纯文本形式存储表格数据。
该文件是一个字符序列,可以由任意数目的记录组成,记录间以某种换行符分隔。每条记录由字段组成,字段间的分隔符是其他字符或字符串,最常见的是逗号或制表符。
不过所有记录都有完全相同的字段序列,相当于一个结构化表的纯文本形式。
写入
利用csv库-import csv
列表形式写入
首先,导库import csv
;
其次,打开文件,以w或者a的方式写入with open('xxx.csv', 'w') as csvfile:
;
然后,调用csv库的writer方法初始化写入对象writer = csv.writer(csvfile)
;
最后,调用writerow方法传入每行的数据即可完成写入writer.writerow(['xx', 'xxx', xx])
;
import csv
with open('data.csv', 'w') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['id', 'name', 'age'])
writer.writerow(['10001', 'Mike', 20])
writer.writerow(['10002', 'Bob', 22])
writer.writerow(['10003', 'Jordan', 21])
同时写入多行
调用writerows方法同时写入多行,此时参数就需要为二维列表
import csv
with open('data.csv', 'w') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['id', 'name', 'age'])
writer.writerows([['10001', 'Mike', 20], ['10002', 'Bob', 22], ['10003', 'Jordan', 21]])
字典形式写入
首先,导库import csv
;
其次,打开文件,以w或者a的方式写入with open('xxx.csv', 'w') as csvfile
;
然后,定义表头信息,用fieldnames表示fieldnames = ['xx', 'xx', 'xx']
;
再之,调用csv库的DictWriter方法初始化一个字典写入对象,writer=csv.DictWriter(csvfile,fieldnames=fieldnames)
;
然后,调用writeheader方法写入头信息writer.writeheader()
;
最后,调用writerow方法传入传入相应的字典即可writer.writerow({'xx': 'xx', 'yy': 'yy', 'zz': zz})
;
import csv
with open('data.csv', 'w') as csvfile:
fieldnames = ['id', 'name', 'age']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({'id': '10001', 'name': 'Mike', 'age': 20})
writer.writerow({'id': '10002', 'name': 'Bob', 'age': 22})
writer.writerow({'id': '10003', 'name': 'Jordan', 'age': 21})
利用pandas库
可以调用 DataFrame 对象的 to_csv 方法来将数据写入 CSV 文件中。
读取
利用csv库读取
首先,导库import csv
;
其次,打开csv文件with open('xxx.csv', 'r', encoding='utf-8') as csvfile:
;
然后,构造reader对象reader = csv.reader(csvfile)
;
最后,通过遍历输出每行的内容for row in reader:
,每行都是列表形式
import csv
with open('data.csv', 'r', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
print(row)
利用pandas库读取
import pandas as pd
df = pd.read_csv('data.csv')
print(df)
6-将爬取的数据保存为各类文件
import json
import csv
import lxml
import requests
from bs4 import BeautifulSoup as BS
response = open('html.txt',encoding='utf-8')
bsobj = BS(response, 'lxml')
items = bsobj.find_all('div', class_='explore-feed feed-item', )
for item in items:
question = item.a.string
author = item.find(name='a', class_='author-link').get_text()
answer = item.textarea.string
info = [question,author,answer,] #将数据保存为列表
dict = { #保存为dict
'question':question,
'author':author,
'answer':answer
}
save_as_txt(info)
save_as_json(dict)
save_as_csv(info)
def save_as_txt(list):
filename = 'info.txt'
with open(filename, 'a',encoding='utf-8') as file:
file.write('\n'.join(list))
def save_as_json(dict):
filename = 'info.json'
with open(filename, 'a',encoding='utf-8') as file:
file.write(json.dumps(dict, indent=4, ensure_ascii=False)+',\n')
filename = 'info.csv'
with open(filename, 'w', encoding='utf-8') as file:
writer = csv.writer(file)
writer.writerow(['question', 'author', 'answer'])
def save_as_csv(list):
filename = 'info.csv'
with open(filename, 'a', encoding='utf-8') as file:
writer = csv.writer(file)
writer.writerow(list)
参考文献
根据崔庆才《Python 3 开发网络爬虫》整理