爬虫-文件存储-txt\json\csv

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 文件,其内容如所示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zt0kGvL3-1618743572163)(res/5-1.jpg)]
这里 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 开发网络爬虫》整理

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值