用解析器解析出数据之后,接下来就是存储数据了。保存的形式有很多,最简单的形式是直接保存为文本文件,如TXT、JSON、csv等。另外,还可以将这些数据保存到数据库中。

文本存储

文件打开模式

python中所有open()打开一个文件,文件的打开有很多模式:

  • r:以只读方式打开文件,文件的指针将会放在文件的开头,这是默认模式。
  • rb:以二进制只读方式打开一个文件,文件指针将会放在文件的开头。
  • r+:以读写方式打开一个文件,文件指针将会放在文件的开头。
    -** rb+**: 以二进制读写方式打开一个文件,文件指针将会放在文件的开头。
  • w:以写入方式打开一个文件。如果该文件已存在,则将其瞿盖;如果该文件不存在,则创建新文件。
  • wb:以二进制写入方式打开一个文件。如果该文件已存在,则将其覆盖;如果该文件不存在,则创建新文件。
  • w+:以读写方式打开一个文件。如果该文件已存在,则将其覆盖;如果该文件不存在,则创建新文件。
  • wb+:以二进制读写格式打开一个文件。如果该文件已存在,则将其覆盖;如果该文件不存在, 则创建新文件。
  • a:以追加方式打开一个文件。如果该文件已存在,文件指针将会放在文件结尾。也就是说,新的内容将会被写入到已有内容之后;如果该文件不存在, 则创建新文件来写入。
  • ab:以二进制追加方式打开一个文件。如果该文件已存在,则文件指针将会放在文件结尾。也就是说,新的内容将会被写入到己有内容之后;如果该文件不存在,则创建新文件来写入。
  • a+:以读写方式打开一个文件。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式;如果眩文件不存在,则创建新文件来读写。
  • ab+:以二进制追加方式打开一个文件。如果该文件已存在,则文件指针将会放在文件结尾;如果该文件不存在,则创建新文件用于读写。

以TXT文本形式存储

TXT 文本的操作非常简单,且其几乎兼容任何平台,但是它有个缺点,那就是不利于检索。

import requests
from pyquery import PyQuery as pq

url = 'https://www.zhihu.com/explore'
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 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()
    # 将question,author和answer的内容保存在文件explore.txt中
    file = open('explore.txt', 'a', encoding='utf-8')
    file.write('\n'.join([question, author, answer]))
    file.write('\n' + '=' * 50 + '\n')
    file.close()

  事实上,一般来讲,文件写入这个动作还有一种简化写法,就是使用with as语法,在with 控制块结束时,文件会自动关闭,所以就不需要再调用close()方法了。

with  open('explore.txt', 'a', encoding='utf-8') as file:
    file.write('\n'.join([question, author, answer]))
    file.write('\n' + '=' * 50 + '\n')

以JSON数据形式存储

读取json数据

  Python为我们提供了简单易用的JSON库来实现JSON文件的读写操作,我们可以调用JSON库的loads()方法将JSON文本字符串转为JSON对象,也可以通过dumps()方法将JSON对象转为文本字符串。

json内的数据需要使用双引号包围,不能使用单引号。

import json

str = '''
[{
    "name": "Bob",
    "gender": "male",
    "birthday": "1992-10-18"
}, {
    "name": "Selina",
    "gender": "female",
    "birthday": "1995-10-18"
}]
'''

print(type(str))
# 使用loads()方法将字符串转换为json对象
data = json.loads(str)
print(data)
print(type(data))
# 可以使用以下两种方法取得列表类型内的json数据
print(data[0]['name'])
print(data[0].get('name'))
# 如果用中括号取值[][],但想取得的值不存在,则以下这种方式会报错
# print(data[0]['age'])
# 如果使用get()函数取值的话,就算值不存在也只是会输出None,get()的第二个参数表示值不存在时要输出的默认值
print(data[0].get('age', 25))

# /******---- 输出: -----******\
# <class 'str'>
# [{'gender': 'male', 'birthday': '1992-10-18', 'name': 'Bob'}, {'gender': 'female', 'birthday': '1995-10-18', 'name': 'Selina'}]
# <class 'list'>
# Bob
# Bob
# 25

当然,也可以从文件读取json字符串信息:

with open('data.json', 'r') as file:
    str = file.read()
    data = json.loads(str)
    print(data)

输出json数据

import json

data = [{
    "name": "Bob",
    "gender": "男",
    "birthday": "1992-10-18"
}]

with open('data.json', 'w') as file:
    file.write(json.dumps(data, indent=2, ensure_ascii=False)) 
    # indent表示缩进字符个数,ensure_ascii为False表示不使用ASCII字符集,这样可以正确输出中文

data.json文件中的内容如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tr2PR6Kl-1640339861361)(https://note.youdao.com/yws/public/resource/f8e5908c0721dddb3fd530cf29cb1b8e/xmlnote/WEBRESOURCE5c55acb5ef08952f68989ff660a19fed/42821 “”)]

以CSV文本格式存储

  Csv(Comma-Separated Values,逗号分隔值或字符分隔值),其文件以纯文
本形式存储表格数据。该文件是一个字符序列,可以由任意数目的记录组成,记录间以某种换行符分隔。每条记录由字段组成,字段间的分隔符是其他字符或字符串,最常见的是逗号或制表符。不过所有记录都有完全相同的字段序列,相当于一个结构化表的纯文本形式。它比Excel文件更加简介,XLS是电子表格,它包含了文本、数值、公式和格式等内容,而csv 中不包含这些内容,就是字符分隔的纯文本,保存最基本的表格数据信息,结构简单清晰。

写入CSV数据

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])

此时data.csv文件的内容如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sdSkBwIx-1640339861362)(https://note.youdao.com/yws/public/resource/f8e5908c0721dddb3fd530cf29cb1b8e/xmlnote/WEBRESOURCE726e279bee28d8071543b7a812f60258/42835 “”)]

  上面的程序中没有指明CSV的分隔符,所以使用的是默认的逗号,如果想修改CSV文件中列与列之间的分隔符:

import csv

with open('data.csv', 'w') as csvfile:
    writer = csv.writer(csvfile, delimiter=' ')
    writer.writerow(['id', 'name', 'age'])
    writer.writerow(['10001', 'Mike', 20])
    writer.writerow(['10002', 'Bob', 22])
    writer.writerow(['10003', 'Jordan', 21])

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dgtzpeK8-1640339861364)(https://note.youdao.com/yws/public/resource/f8e5908c0721dddb3fd530cf29cb1b8e/xmlnote/WEBRESOURCEf445bd3566bf3f3c9a461ed4bc816fb0/42837 “”)]

也可以使用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]])

  但是一般情况下,爬虫爬取的都是结构化数据,我们一般会用字典来表示,所以尽量使用csv库提供的DictWriter()向CSV文件中写字典入数据。

import csv

with open('data.csv', 'w') as csvfile:
    fieldnames = ['id', 'name', 'age']  # 定义CSV头部信息
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    writer.writeheader()    # 写入CSV头部信息
    # 下面的writerow()传入的是字典数据
    writer.writerow({'id': '10001', 'name': 'Mike', 'age': 20})
    writer.writerow({'id': '10002', 'name': 'Bob', 'age': 22})
    writer.writerow({'id': '10003', 'name': 'Jordan', 'age': 21})

读取CSV数据

import csv

with open('data.csv', 'r') as csvfile:
    # reader()每次读取CSV文件中的一行
    reader = csv.reader(csvfile)
    for row in reader:
        print(row)
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐