Python 爬虫入门(二):使用数据库储存数据 「详细介绍」
前言
- 欢迎来到"Python 爬虫入门"系列的第二篇文章。在上一篇文章中,我们学习了爬虫的基本概念、HTTP协议、网页组成以及如何使用Python编写简单的爬虫。本篇文章我们将继续深入,探讨如何使用数据库来存储爬取的数据。
- 在实际的爬虫项目中,我们通常需要处理大量的数据。将这些数据保存在内存中或者直接写入文件可能会面临诸如数据丢失、查询效率低下等问题。这时,使用数据库就成为了一个更好的选择。数据库不仅可以安全地存储大量数据,还提供了高效的查询和管理功能。
- 本文将介绍三种常用的数据库:关系型数据库MySQL,以及非关系型数据库Redis和MongoDB。我们将详细讲解如何在Python爬虫中使用这些数据库,并通过实例来展示它们各自的特点和适用场景。
1. 关系型数据库:MySQL
1.1 什么是MySQL?
MySQL是一个开源的关系型数据库管理系统,使用SQL(结构化查询语言)进行数据操作。
它以其可靠性、性能和易用性而闻名,被广泛应用于各种规模的应用程序中。
1.2 MySQL的特点
- 支持复杂查询:MySQL支持JOIN等复杂SQL查询,适合处理结构化数据。
- 事务支持:MySQL支持ACID事务,保证数据的一致性和可靠性。
- 数据完整性:通过主键、外键等约束确保数据的完整性。
- 高性能:针对高并发读写进行了优化,支持大规模数据存储。
1.3 在 Python中 使用 MySQL
1.3.1 安装 MySQL
下载 MySQL Installer:
访问 MySQL 官方网 https://dev.mysql.com/downloads/installer/ ,下载 MySQL Installer for Windows运行安装程序:
双击下载的安装文件,选择 “Custom” 安装类型 ,选择要安装的组件(至少选择 MySQL Server 和 Workbench)按照提示完成安装,设置 root 密码
验证安装:
打开命令提示符 输入 mysql -u root -p 输入设置的密码 如果成功登录,则安装成功
1.3.2 连接 MySQL 数据库
这里我们可以使用 mysql-connector-python 库连接 MySQL 数据库。
输入以下 pip 命令进行安装:
pip install mysql-connector-python
下面是一个使用MySQL存储爬取数据的示例:
import mysql.connector import requests from bs4 import BeautifulSoup # 连接到MySQL数据库 conn = mysql.connector.connect( host="localhost", user="your_username", password="your_password", database="crawler_db" ) cursor = conn.cursor() # 创建表 cursor.execute(""" CREATE TABLE IF NOT EXISTS articles ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255), content TEXT, url VARCHAR(255) ) """) # 爬取数据并存储 url = "https://example.com/articles" response = requests.get(url) soup = BeautifulSoup(response.text, 'html.parser') for article in soup.find_all('article'): title = article.find('h2').text content = article.find('div', class_='content').text article_url = article.find('a')['href'] # 插入数据 cursor.execute(""" INSERT INTO articles (title, content, url) VALUES (%s, %s, %s) """, (title, content, article_url)) # 提交事务并关闭连接 conn.commit() cursor.close() conn.close()
在这个例子中,我们首先安装并连接到MySQL数据库,然后创建一个名为articles
的表。接着,我们爬取网页内容,并将每篇文章的标题、内容和URL插入到数据库中。
1.4 MySQL的适用场景
- 需要处理复杂的关系数据时
- 对数据一致性要求较高的场景
- 需要进行复杂查询的应用
2. 非关系型数据库:Redis
2.1 什么是Redis?
Redis(Remote Dictionary Server)是一个开源的、支持网络、基于内存、可选持久性的键值对存储数据库。
它以其超高的读写速度而闻名,常被用作缓存、消息队列和实时数据存储。
2.2 Redis的特点
- 高性能:基于内存操作,读写速度极快。
- 数据结构丰富:支持字符串、哈希、列表、集合、有序集合等多种数据结构。
- 原子性操作:Redis的所有操作都是原子性的,支持事务。
- 持久化:支持数据的持久化存储。
2.3 在Python中使用Redis
2.3.1 安装 Redis
下载 Redis for Windows:
访问 https://github.com/microsoftarchive/redis/releases,下载最新的 .msi 文件安装 Redis:
双击下载的 .msi 文件 按照提示完成安装启动 Redis 服务:
打开命令提示符(以管理员身份运行) 输入 redis-server验证安装:
打开新的命令提示符 输入 redis-cli 输入 ping,如果返回 PONG,则安装成功
2.3.2 安装 Redis 库
通过以下pip命令安装:
pip install redis
下面是一个使用Redis存储爬取数据的示例:
import redis import requests from bs4 import BeautifulSoup # 连接到Redis r = redis.Redis(host='localhost', port=6379, db=0) # 爬取数据并存储 url = "https://example.com/products" response = requests.get(url) soup = BeautifulSoup(response.text, 'html.parser') for product in soup.find_all('div', class_='product'): product_id = product['id'] name = product.find('h3').text price = product.find('span', class_='price').text # 使用哈希存储产品信息 r.hset(f"product:{product_id}", mapping={ 'name': name, 'price': price }) # 设置过期时间(例如1小时) r.expire(f"product:{product_id}", 3600)
在这个例子中,我们使用Redis的哈希结构来存储每个产品的信息。我们还为每个产品设置了过期时间,这在缓存场景中很有用。
2.4 Redis的适用场景
- 需要高速缓存的应用
- 实时数据分析
- 消息队列系统
- 排行榜或计数器系统
3. 非关系型数据库:MongoDB
3.1 什么是MongoDB?
MongoDB是一个开源的文档型数据库,它以JSON格式存储数据,提供了高性能、高可用性和易扩展性。
MongoDB的设计目标是为WEB应用提供可扩展的高性能数据存储解决方案。
3.2 MongoDB的特点
- 文档型:数据以BSON(Binary JSON)格式存储,非常灵活。
- 高性能:支持索引,提供高效的数据读写。
- 易扩展:支持分片,可以轻松处理大规模数据。
- 丰富的查询语言:支持丰富的查询操作,包括聚合管道。
3.3 在Python中使用MongoDB
3.3.1 安装 MongoDB
下载 MongoDB:
访问 MongoDB 下载页面https://www.mongodb.com/try/download/community,选择 Community Server 版本并下载 .msi 安装文件安装 MongoDB:
双击下载的 .msi 文件 选择 “Complete” 安装类型 按照提示完成安装配置 MongoDB 服务:
创建数据目录,例如 C:\data\db 打开命令提示符(以管理员身份运行) 输入 mongod --dbpath C:\data\db验证安装:
打开新的命令提示符 输入 mongo 如果进入 MongoDB shell,则安装成功
3.3.2 安装 MongoDB 库
通过以下 pip 命令安装:
pip install pymongo
下面是一个使用MongoDB存储爬取数据的示例:
from pymongo import MongoClient import requests from bs4 import BeautifulSoup # 连接到MongoDB client = MongoClient('mongodb://localhost:27017/') db = client['crawler_db'] collection = db['movies'] # 爬取数据并存储 url = "https://example.com/movies" response = requests.get(url) soup = BeautifulSoup(response.text, 'html.parser') for movie in soup.find_all('div', class_='movie'): title = movie.find('h2').text director = movie.find('span', class_='director').text year = int(movie.find('span', class_='year').text) genres = [genre.text for genre in movie.find_all('span', class_='genre')] # 插入数据 collection.insert_one({ 'title': title, 'director': director, 'year': year, 'genres': genres }) # 创建索引 collection.create_index([('title', 1)]) collection.create_index([('year', -1)])
在这个例子中,我们将每部电影的信息作为一个文档存储在MongoDB中。我们还为title
和year
字段创建了索引,以提高查询性能。
3.4 MongoDB的适用场景
- 需要处理大量非结构化或半结构化数据
- 需要高度可扩展性的应用
- 快速迭代开发,数据模式经常变化的项目
- 地理空间查询应用
4. 根据实际需求选择数据库
在选择数据库时,需要考虑以下几个因素:
- 数据结构:如果数据高度结构化且关系复杂,可能更适合使用MySQL;如果数据结构灵活多变,可能更适合使用MongoDB。
- 性能需求:如果需要极高的读写速度,Redis可能是最佳选择;如果需要复杂的查询功能,MySQL或MongoDB可能更合适。
- 数据量:对于海量数据,MongoDB的可扩展性可能更有优势。
- 一致性要求:如果需要强一致性,MySQL可能是更好的选择;如果可以接受最终一致性,MongoDB可能更适合。
- 开发效率:对于快速迭代的项目,MongoDB的灵活性可能有助于提高开发效率。
5. 实战:综合使用多个数据库
在实际的爬虫项目中,我们可能需要结合使用多个数据库来满足不同的需求。
下面是一个综合使用MySQL、Redis和MongoDB的爬虫示例:
import mysql.connector import redis from pymongo import MongoClient import requests from bs4 import BeautifulSoup # 连接MySQL mysql_conn = mysql.connector.connect( host="localhost", user="your_username", password="your_password", database="crawler_db" ) mysql_cursor = mysql_conn.cursor() # 连接Redis redis_client = redis.Redis(host='localhost', port=6379, db=0) # 连接MongoDB mongo_client = MongoClient('mongodb://localhost:27017/') mongo_db = mongo_client['crawler_db'] mongo_collection = mongo_db['raw_data'] def crawl_and_store(url): # 检查Redis缓存 if redis_client.exists(url): print(f"URL {url} already crawled recently. Skipping...") return response = requests.get(url) soup = BeautifulSoup(response.text, 'html.parser') # 存储原始数据到MongoDB mongo_collection.insert_one({ 'url': url, 'html_content': response.text }) # 解析并存储结构化数据到MySQL title = soup.find('h1').text content = soup.find('div', class_='content').text mysql_cursor.execute(""" INSERT INTO articles (url, title, content) VALUES (%s, %s, %s) """, (url, title, content)) mysql_conn.commit() # 将URL标记为已爬取(1小时过期) redis_client.setex(url, 3600, 'crawled') # 爬取多个URL urls = [ "https://example.com/article1", "https://example.com/article2", "https://example.com/article3" ] for url in urls: crawl_and_store(url) # 关闭连接 mysql_cursor.close() mysql_conn.close() mongo_client.close()
在这个综合示例中:
- 我们使用Redis来记录已经爬取过的URL,避免重复爬取。
- 将爬取的原始HTML内容存储在MongoDB中,以便后续的数据分析或重新解析。
- 将解析后的结构化数据(如文章标题和内容)存储在MySQL中,便于进行复杂查询。
这种方法充分利用了各个数据库的优势:Redis的高速缓存能力、MongoDB的灵活性和MySQL的强大查询功能。
6. 注意事项
在使用数据库存储爬取的数据时,需要注意以下几点:
数据清洗:在存储数据之前,确保对数据进行适当的清洗和验证,以保证数据质量。
错误处理:在与数据库交互时,要做好错误处理,例如处理连接失败、查询超时等情况。
安全性:使用参数化查询来防止SQL注入攻击,特别是在使用MySQL时。
性能优化:合理使用索引,避免频繁的小批量插入,考虑使用批量插入来提高效率。
数据备份:定期备份重要数据,以防数据丢失。
遵守robots.txt:在爬取和存储数据时,务必遵守网站的robots.txt规则和使用条款。
数据隐私:注意保护用户隐私,不要存储敏感个人信息。
总结
在这篇文章中,我们深入探讨了如何在Python爬虫中使用MySQL、Redis和MongoDB这三种不同类型的数据库来存储爬取的数据。
每种数据库都有其独特的优势和适用场景:
- MySQL适合存储结构化数据,支持复杂查询和事务处理。
- Redis以其超高的读写速度成为缓存和实时数据处理的理想选择。
- MongoDB的灵活性和可扩展性使其成为处理大量非结构化或半结构化数据的有力工具。
通过综合使用这些数据库,我们可以构建出既高效又灵活的爬虫系统,能够处理各种复杂的数据存储需求。
如果你有任何问题或者好的想法,欢迎随时和我交流。