系列文章

  1. 网页爬虫第一课:从案例解构爬虫基本概念
  2. 填坑18年:我总结的CSS选择器
  3. 爬虫数据持久化方式的选择
  4. 爬取静态博客网页以分析本网站拓扑结构
  5. python程序的性能测试及瓶颈分析
  6. Python工程项目的规范开发指南

存储方案的选择

爬虫数据的存储目前有以下几种方式:

  1. TXT文本文件存储
  2. JSON文件存储
  3. CSV文件存储
  4. MySQL存储
  5. MongoDB文档存储
  6. Redis缓存存储
  7. Elasticsearch搜索引擎存储
  8. RabbitMQ的使用

作为个人使用, 从数据的”存储便捷性-多种工具间的兼容性-可拓展性”的角度出发, 我选择综合使用下述方案:

  1. 在本地, 当数据文件较少时, 用”JSON文件存储”;
  2. 在本地, 当数据文件较多时, 用”MongoDB文档存储”;
  3. 在云端, 用”Elasticsearch搜索引擎存储”, 同时本地的MongoDB数据的文件定期上传到云端的Elasticsearch.

上面的过程慢慢来. 在本文中今天先学会JSON文件存储.

JSON文件存储

python的json字符串形如:

1
2
3
4
5
6
json_str = [ {
"name": "hellokitty",
"age":18,
"gender":"female",
"income":20000
} ]

将python中生成的数据写入到磁盘json文件有两个函数: dumpsdump.

1
2
3
import json
with open('local.json', w, encoding='utf-8') as file:
file.write(json.dumps(json_str, ensure_ascii=False, indent=4))

Or,

1
2
import json
json.dump(json_str, open('local.json', 'w', encoding='utf-8'), indent=4, ensure_ascii=False)

类似地, 从磁盘json文件读取数据到python程序中也有两个函数: loadsload. 在此不再赘述.

MongoDB文档存储

MongoDB是有C++语言编写的非关系型数据库(NoSQL, Not Only SQL). NoSQL是基于键值对的, 而且不需要经过SQL层的解析, 所以速度快, 适合大数据量的存储. MongoDB的数据存储格式是BSON, 也就是二进制的JSON. (前文已经说过, 对于不大的数据量, 我们多以JSON实现数据持久化. 而当数据量大时, JSON可以平滑的过渡到MongoDB).

MongoDB的一些特点使它比较适合爬虫数据的存储. 对于爬虫的数据存储来说, 一条数据可能存在因某些字段提取失败而缺失的情况, 而且数据可能临时调整. 另外, 数据之间还存在嵌套关系. 如果使用关系型数据库存储这些数据, 一是需要提前建表, 二是如果数据存在嵌套关系, 还需要进行序列化操作才可以存储, 这非常不方便. 如果使用非关系型数据库, 就可以避免这些麻烦, 更简单、高效. [1]

我们选择在wsl的Linux环境中操作MongoDB数据库. 这里简要给出MongoDB的安装流程:

Step 1: 安装MongoDB [2]

1
2
3
4
5
6
7
8
9
10
11
sudo apt-get install gnupg curl

curl -fsSL https://pgp.mongodb.com/server-6.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-6.0.gpg \
--dearmor

echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-6.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list

sudo apt-get update

sudo apt-get install -y mongodb-org

Step 2: 启动MongoDB服务 [3]

1
2
3
4
sudo systemctl start mongod
sudo systemctl daemon-reload
sudo systemctl status mongod
sudo systemctl enable mongod

命令行操作MongoDB

在mongosh或MongoDB Compass中, 交互式操作. 这里我只给出最小工作流程:

  1. 了解MongoDB数据库的基本概念: MongoDB Basics
  2. 连接MongoDB后台服务程序, 并新建(或使用已有的)数据库: 数据库操作
  3. 在数据库中新建(或使用已有的)集合: 集合操作
  4. 对于数据库的日常应用, 基本都是围绕CRUD操作进行的: MongoDB CRUD

Python操作MongoDB

这里我仅给出用python将数据写入MongoDB的最小工作流程, 详细的操作可以参考本小节的下述资料.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import mitmproxy.http
from mitmproxy import ctx
import pymongo


# store the collected data into mongodb
def store_doc(document):
try:
client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["WechatDB"]
collection = db["WechatArticle"]
collection.insert_one(document)
ctx.log.info("=" * 80)
ctx.log.info("Data stored successfully")
except Exception as e:
ctx.log.info("=" * 80)
ctx.log.error("Failed to store data: %s" % e)
ctx.log.info("=" * 80)


if __name__ == "__main__":

# variable of doc could be collected from the response of the request
doc = {
"title": title,
"author": author,
"content": content,
"publish_time": publish_time,
"url": url,
"read_num": read_num,
"like_num": like_num,
"comment_num": comment_num,
"reward_num": reward_num,
"tags": tags,
"comments": comments
}

store_doc(doc)

阅读资料:

Elasticsearch搜索引擎存储

Elasticsearch的优势是可以快速的进行全文搜索, 而且支持分布式搜索. 但是Elasticsearch数据库特别耗费资源,我曾租了一年的云主机作为Elasticsearch服务器——花了不少钱,也没有搞出什么名堂。最难受的是它太重了,每次使用的时候一想到杀鸡用牛刀,瞬间失去了行动的兴趣。

而日常的爬虫应用需求,都是个性化的,所以数据库以轻便为佳。

小结与展望

用MongoDB吧,它轻便,易用;更关键的是,它是非结构化的,对于应付对象元数据不确定的情况比较灵活。

这些特点使MongoDB适合爬虫数据的存储。

参考与注释