Python爬虫技术 第18节 数据存储

news2024/11/27 19:48:24

Python 爬虫技术常用于从网页上抓取数据,并将这些数据存储起来以供进一步分析或使用。数据的存储方式多种多样,常见的包括文件存储和数据库存储。下面我将通过一个简单的示例来介绍如何使用 Python 爬取数据,并将其存储为 CSV 和 JSON 文件格式,以及如何将数据存储到 SQL 和 NoSQL 数据库中。

在这里插入图片描述stars

示例场景:

假设我们要爬取一个网站上的产品信息,每个产品包含以下字段:product_name, price, rating, description

步骤 1: 安装所需库

首先需要安装一些必要的 Python 库:

  • requests 用于发起 HTTP 请求
  • BeautifulSoup 用于解析 HTML 文档
  • pandas 用于数据处理
  • sqlite3pymysql (MySQL) 用于 SQL 数据库操作
  • pymongo 用于 MongoDB (NoSQL)

可以通过 pip 安装:

pip install requests beautifulsoup4 pandas sqlite3 pymysql pymongo

步骤 2: 编写爬虫代码

2.1 爬取数据
import requests
from bs4 import BeautifulSoup

def fetch_data(url):
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')
    
    products = []
    for product in soup.find_all('div', class_='product'):
        name = product.find('h2').text.strip()
        price = product.find('span', class_='price').text.strip()
        rating = product.find('span', class_='rating').text.strip()
        description = product.find('p', class_='description').text.strip()

        products.append({
            'product_name': name,
            'price': price,
            'rating': rating,
            'description': description
        })
    return products

url = 'http://example.com/products'
products = fetch_data(url)
print(products)
2.2 存储数据到 CSV 文件
import pandas as pd

def save_to_csv(data, filename):
    df = pd.DataFrame(data)
    df.to_csv(filename, index=False)

save_to_csv(products, 'products.csv')
2.3 存储数据到 JSON 文件
import json

def save_to_json(data, filename):
    with open(filename, 'w') as f:
        json.dump(data, f, indent=4)

save_to_json(products, 'products.json')

步骤 3: 存储数据到数据库

3.1 存储数据到 SQL 数据库 (SQLite)
import sqlite3

def save_to_sqlite(data):
    conn = sqlite3.connect('products.db')
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS products
                 (product_name TEXT, price TEXT, rating TEXT, description TEXT)''')

    placeholders = ', '.join(['?'] * len(data[0]))
    columns = ', '.join(data[0].keys())
    sql = f'INSERT INTO products ({columns}) VALUES ({placeholders})'

    c.executemany(sql, [list(item.values()) for item in data])
    conn.commit()
    conn.close()

save_to_sqlite(products)
3.2 存储数据到 NoSQL 数据库 (MongoDB)
from pymongo import MongoClient

def save_to_mongodb(data):
    client = MongoClient('mongodb://localhost:27017/')
    db = client['products_db']
    collection = db['products']

    collection.insert_many(data)
    client.close()

save_to_mongodb(products)

以上示例展示了如何使用 Python 抓取数据并将其存储到不同的数据存储方式中。你可以根据具体的需求选择合适的存储方式。如果需要在生产环境中使用,请确保遵守相关法律法规和网站的服务条款。

当然可以!我们可以进一步完善上面的代码,使其更加完整和实用。接下来,我们将添加异常处理、日志记录等功能,并提供完整的代码示例。

完整的代码示例

1. 导入必要的库
import requests
from bs4 import BeautifulSoup
import pandas as pd
import json
import sqlite3
from pymongo import MongoClient
import logging
2. 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
3. 网页数据抓取函数
def fetch_data(url):
    try:
        response = requests.get(url)
        response.raise_for_status()  # 检查响应状态码是否正常
        soup = BeautifulSoup(response.text, 'html.parser')

        products = []
        for product in soup.find_all('div', class_='product'):
            name = product.find('h2').text.strip()
            price = product.find('span', class_='price').text.strip()
            rating = product.find('span', class_='rating').text.strip()
            description = product.find('p', class_='description').text.strip()

            products.append({
                'product_name': name,
                'price': price,
                'rating': rating,
                'description': description
            })

        logging.info(f"Fetched {len(products)} products.")
        return products
    except Exception as e:
        logging.error(f"Error fetching data: {e}")
        return []

url = 'http://example.com/products'
products = fetch_data(url)
4. CSV 文件存储
def save_to_csv(data, filename):
    try:
        df = pd.DataFrame(data)
        df.to_csv(filename, index=False)
        logging.info(f"Data saved to {filename}.")
    except Exception as e:
        logging.error(f"Error saving to CSV: {e}")

save_to_csv(products, 'products.csv')
5. JSON 文件存储
def save_to_json(data, filename):
    try:
        with open(filename, 'w') as f:
            json.dump(data, f, indent=4)
        logging.info(f"Data saved to {filename}.")
    except Exception as e:
        logging.error(f"Error saving to JSON: {e}")

save_to_json(products, 'products.json')
6. SQLite 数据库存储
def save_to_sqlite(data):
    try:
        conn = sqlite3.connect('products.db')
        c = conn.cursor()
        c.execute('''CREATE TABLE IF NOT EXISTS products
                     (product_name TEXT, price TEXT, rating TEXT, description TEXT)''')

        placeholders = ', '.join(['?'] * len(data[0]))
        columns = ', '.join(data[0].keys())
        sql = f'INSERT INTO products ({columns}) VALUES ({placeholders})'

        c.executemany(sql, [list(item.values()) for item in data])
        conn.commit()
        conn.close()
        logging.info("Data saved to SQLite database.")
    except Exception as e:
        logging.error(f"Error saving to SQLite: {e}")

save_to_sqlite(products)
7. MongoDB 数据库存储
def save_to_mongodb(data):
    try:
        client = MongoClient('mongodb://localhost:27017/')
        db = client['products_db']
        collection = db['products']

        collection.insert_many(data)
        client.close()
        logging.info("Data saved to MongoDB database.")
    except Exception as e:
        logging.error(f"Error saving to MongoDB: {e}")

save_to_mongodb(products)

完整的脚本

将上述所有部分组合成一个完整的脚本如下所示:

import requests
from bs4 import BeautifulSoup
import pandas as pd
import json
import sqlite3
from pymongo import MongoClient
import logging

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def fetch_data(url):
    try:
        response = requests.get(url)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, 'html.parser')

        products = []
        for product in soup.find_all('div', class_='product'):
            name = product.find('h2').text.strip()
            price = product.find('span', class_='price').text.strip()
            rating = product.find('span', class_='rating').text.strip()
            description = product.find('p', class_='description').text.strip()

            products.append({
                'product_name': name,
                'price': price,
                'rating': rating,
                'description': description
            })

        logging.info(f"Fetched {len(products)} products.")
        return products
    except Exception as e:
        logging.error(f"Error fetching data: {e}")
        return []

def save_to_csv(data, filename):
    try:
        df = pd.DataFrame(data)
        df.to_csv(filename, index=False)
        logging.info(f"Data saved to {filename}.")
    except Exception as e:
        logging.error(f"Error saving to CSV: {e}")

def save_to_json(data, filename):
    try:
        with open(filename, 'w') as f:
            json.dump(data, f, indent=4)
        logging.info(f"Data saved to {filename}.")
    except Exception as e:
        logging.error(f"Error saving to JSON: {e}")

def save_to_sqlite(data):
    try:
        conn = sqlite3.connect('products.db')
        c = conn.cursor()
        c.execute('''CREATE TABLE IF NOT EXISTS products
                     (product_name TEXT, price TEXT, rating TEXT, description TEXT)''')

        placeholders = ', '.join(['?'] * len(data[0]))
        columns = ', '.join(data[0].keys())
        sql = f'INSERT INTO products ({columns}) VALUES ({placeholders})'

        c.executemany(sql, [list(item.values()) for item in data])
        conn.commit()
        conn.close()
        logging.info("Data saved to SQLite database.")
    except Exception as e:
        logging.error(f"Error saving to SQLite: {e}")

def save_to_mongodb(data):
    try:
        client = MongoClient('mongodb://localhost:27017/')
        db = client['products_db']
        collection = db['products']

        collection.insert_many(data)
        client.close()
        logging.info("Data saved to MongoDB database.")
    except Exception as e:
        logging.error(f"Error saving to MongoDB: {e}")

if __name__ == '__main__':
    url = 'http://example.com/products'
    products = fetch_data(url)
    save_to_csv(products, 'products.csv')
    save_to_json(products, 'products.json')
    save_to_sqlite(products)
    save_to_mongodb(products)

这个脚本包含了基本的数据抓取、存储到文件和数据库的功能,并且具有错误处理和日志记录机制,可以作为实际项目的基础。请注意,在实际部署时还需要考虑更详细的错误处理、性能优化等细节问题。

好的,我们可以在现有的基础上进一步完善代码,增加更多的功能和健壮性。以下是针对现有代码的一些改进点:

  1. 参数化 URL: 允许用户指定要抓取的 URL。
  2. 异常处理: 增加更详细的异常处理。
  3. 日志文件: 将日志输出到文件而不是控制台。
  4. 命令行参数: 使用命令行参数来控制程序行为。
  5. 数据验证: 对抓取的数据进行简单的验证。
  6. 数据库连接池: 使用连接池提高数据库操作效率。

下面是根据以上改进点修改后的代码:

import requests
from bs4 import BeautifulSoup
import pandas as pd
import json
import sqlite3
from pymongo import MongoClient
import logging
from argparse import ArgumentParser
from contextlib import closing
from urllib.parse import urlparse

# 设置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# 创建命令行参数解析器
parser = ArgumentParser(description="Web scraper and data storage tool.")
parser.add_argument("url", help="The URL of the web page to scrape.")
parser.add_argument("--output-csv", help="Save data to a CSV file.", default=None)
parser.add_argument("--output-json", help="Save data to a JSON file.", default=None)
parser.add_argument("--output-sqlite", help="Save data to an SQLite database.", action="store_true")
parser.add_argument("--output-mongodb", help="Save data to a MongoDB database.", action="store_true")

# 网页数据抓取函数
def fetch_data(url):
    try:
        response = requests.get(url)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, 'html.parser')

        products = []
        for product in soup.find_all('div', class_='product'):
            name = product.find('h2').text.strip()
            price = product.find('span', class_='price').text.strip()
            rating = product.find('span', class_='rating').text.strip()
            description = product.find('p', class_='description').text.strip()

            products.append({
                'product_name': name,
                'price': price,
                'rating': rating,
                'description': description
            })

        logger.info(f"Fetched {len(products)} products.")
        return products
    except requests.exceptions.HTTPError as errh:
        logger.error(f"HTTP Error: {errh}")
    except requests.exceptions.ConnectionError as errc:
        logger.error(f"Error Connecting: {errc}")
    except requests.exceptions.Timeout as errt:
        logger.error(f"Timeout Error: {errt}")
    except requests.exceptions.RequestException as err:
        logger.error(f"OOps: Something Else: {err}")
    except Exception as e:
        logger.error(f"Error fetching data: {e}")
    return []

# CSV 文件存储
def save_to_csv(data, filename):
    try:
        df = pd.DataFrame(data)
        df.to_csv(filename, index=False)
        logger.info(f"Data saved to {filename}.")
    except Exception as e:
        logger.error(f"Error saving to CSV: {e}")

# JSON 文件存储
def save_to_json(data, filename):
    try:
        with open(filename, 'w') as f:
            json.dump(data, f, indent=4)
        logger.info(f"Data saved to {filename}.")
    except Exception as e:
        logger.error(f"Error saving to JSON: {e}")

# SQLite 数据库存储
def save_to_sqlite(data):
    try:
        with closing(sqlite3.connect('products.db')) as conn:
            c = conn.cursor()
            c.execute('''CREATE TABLE IF NOT EXISTS products
                         (product_name TEXT, price TEXT, rating TEXT, description TEXT)''')

            placeholders = ', '.join(['?'] * len(data[0]))
            columns = ', '.join(data[0].keys())
            sql = f'INSERT INTO products ({columns}) VALUES ({placeholders})'

            c.executemany(sql, [list(item.values()) for item in data])
            conn.commit()
            logger.info("Data saved to SQLite database.")
    except Exception as e:
        logger.error(f"Error saving to SQLite: {e}")

# MongoDB 数据库存储
def save_to_mongodb(data):
    try:
        client = MongoClient('mongodb://localhost:27017/')
        db = client['products_db']
        collection = db['products']

        collection.insert_many(data)
        client.close()
        logger.info("Data saved to MongoDB database.")
    except Exception as e:
        logger.error(f"Error saving to MongoDB: {e}")

# 主程序入口
if __name__ == '__main__':
    args = parser.parse_args()

    url = args.url
    if not url.startswith(('http://', 'https://')):
        logger.error("Invalid URL format. Please ensure it starts with http:// or https://.")
        exit(1)

    products = fetch_data(url)

    if args.output_csv:
        save_to_csv(products, args.output_csv)

    if args.output_json:
        save_to_json(products, args.output_json)

    if args.output_sqlite:
        save_to_sqlite(products)

    if args.output_mongodb:
        save_to_mongodb(products)

代码解释

  • 命令行参数: 使用 argparse 解析命令行参数,允许用户指定 URL 以及输出文件名或数据库。
  • 日志: 使用标准的日志配置,可以方便地修改日志级别或输出位置。
  • 异常处理: 添加了针对网络请求的异常处理,包括常见的 HTTP 错误、连接错误等。
  • 数据验证: 在实际应用中,可能还需要对数据进行更严格的验证,例如检查数据是否符合预期格式。
  • 数据库连接: 使用 with closing() 语句管理 SQLite 连接,确保连接正确关闭。
  • URL 校验: 确保提供的 URL 是有效的 HTTP/HTTPS URL。

这个版本的代码提供了更多的灵活性和健壮性,可以根据具体需求进一步调整和完善。如果需要在生产环境中使用,还应考虑其他因素,如并发处理、更高级的错误恢复机制等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1952056.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】二叉树链式结构——感受递归的暴力美学

前言: 在上篇文章【数据结构】二叉树——顺序结构——堆及其实现中,实现了二叉树的顺序结构,使用堆来实现了二叉树这样一个数据结构;现在就来实现而二叉树的链式结构。 一、链式结构 链式结构,使用链表来表示一颗二叉树…

【机器学习】解开反向传播算法的奥秘

🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 ​💫个人格言: "如无必要,勿增实体" 文章目录 解开反向传播算法的奥秘反向传播算法的概述反向传播算法的数学推导1. 前向传播2…

3.k8s:服务发布:service,ingress;配置管理:configMap,secret,热更新;持久化存储:volumes,nfs,pv,pvc

目录​​​​​​​ 一、服务发布 1.service (1)service和pod之间的关系 (2) service内部服务创建访问 (3)service访问外部服务 (4)基于域名访问外部 (5&#xff…

Prometheus各类监控及监控指标和告警规则

目录 linux docker监控 linux 系统进程监控 linux 系统os监控 windows 系统os监控 配置文件&告警规则 Prometheus配置文件 node_alert.rules docker_container.rules mysql_alert.rules vmware.rules Alertmanager告警规则 consoul注册服务 Dashboard JSON…

并发编程--volatile

1.什么是volatile volatile是 轻 量 级 的 synchronized,它在多 处 理器开 发 中保 证 了共享 变 量的 “ 可 见 性 ” 。可 见 性的意思是当一个 线 程 修改一个共享变 量 时 ,另外一个 线 程能 读 到 这 个修改的 值 。如果 volatile 变 量修 饰 符使用…

车载录像机:移动安全领域的科技新星

随着科技的飞速发展,人类社会的各个领域都在不断经历技术革新。其中,车载录像机作为安防行业与汽车技术结合的产物,日益受到人们的关注。它不仅体现了人类科技发展的成果,更在安防领域发挥了重要作用。本文将详细介绍车载录像机的…

Spring Boot集成canal快速入门demo

1.什么是canal? canal 是阿里开源的一款 MySQL 数据库增量日志解析工具,提供增量数据订阅和消费。 工作原理 MySQL主备复制原理 MySQL master 将数据变更写入二进制日志(binary log), 日志中的记录叫做二进制日志事件&#xff…

【QT】UDP

目录 核心API 示例:回显服务器 服务器端编写: 第一步:创建出socket对象 第二步: 连接信号槽 第三步:绑定端口号 第四步:编写信号槽所绑定方法 第五步:编写第四步中处理请求的方法 客户端…

Simulink代码生成: 基本模块的使用

文章目录 1 引言2 模块使用实例2.1 In/Out模块2.2 Constant模块2.3 Scope/Display模块2.4 Ground/Terminator模块 3 总结 1 引言 本文中博主介绍Simulink中最简单最基础的模块,包括In/Out模块(输入输出),Constant模块&#xff08…

Postman测试工具详细解读

目录 一、Postman的基本概念二、Postman的主要功能1. 请求构建2. 响应查看3. 断言与自动化测试4. 环境与变量5. 集合与文档化6. 与团队实时协作 三、Postman在API测试中的重要性1. 提高测试效率2. 保障API的稳定性3. 促进团队协作4. 生成文档与交流工具 四、Postman的使用技巧1…

CAS算法

CAS算法 1. CAS简介 CAS叫做CompareAndSwap,比较并交换,主要是通过处理器的指令来保证操作的原子性。 CAS基本概念 内存位置 (V):需要进行CAS操作的内存地址。预期原值 (A):期望该内存位置上的旧值。新值 (B):如果旧…

VSCode python autopep8 格式化 长度设置

ctrl, 打开设置 > 搜索autopep8 > 找到Autopep8:Args > 添加项--max-line-length150

Java泛型的介绍和基本使用

什么是泛型 ​ 泛型就是将类型参数化,比如定义了一个栈,你必须在定义之前声明这个栈中存放的数据的类型,是int也好是double或者其他的引用数据类型也好,定义好了之后这个栈就无法用来存放其他类型的数据。如果这时候我们想要使用这…

谷粒商城实战笔记-71-商品服务-API-属性分组-前端组件抽取父子组件交互

文章目录 一,一次性创建所有的菜单二,开发属性分组界面1,左侧三级分类树形组件2,右侧分组列表3,左右两部分通信3.1 子组件发送数据3.2,父组件接收数据 Vue的父子组件通信父组件向子组件传递数据子组件向父组…

SpringBoot添加密码安全配置以及Jwt配置

Maven仓库(依赖查找) 1、SpringBoot安全访问配置 首先添加依赖 spring-boot-starter-security 然后之后每次启动项目之后,访问任何的请求都会要求输入密码才能请求。(如下) 在没有配置的情况下,默认用户…

LLM agentic模式之工具使用: Gorilla

Gorilla Gorilla出自2023年5月的论文《Gorilla: Large Language Model Connected with Massive APIs》,针对LLM无法准确地生成API调用时的参数,构建API使用数据集后基于Llama微调了一个模型。 数据集构建 API数据集APIBench的构建过程如下&#xff1…

《Programming from the Ground Up》阅读笔记:p75-p87

《Programming from the Ground Up》学习第4天,p75-p87总结,总计13页。 一、技术总结 1.persistent data p75, Data which is stored in files is called persistent data, because it persists in files that remain on disk even when the program …

C语言程序设计15

程序设计15 问题15_1代码15_1结果15_1 问题15_2代码15_2结果15_2 问题15_3代码15_3结果15_3 问题15_1 在 m a i n main main 函数中将多次调用 f u n fun fun 函数,每调用一次,输出链表尾部结点中的数据,并释放该结点,使链表缩短…

【SQL 新手教程 3/20】关系模型 -- 外键

💗 关系数据库建立在关系模型上⭐ 关系模型本质上就是若干个存储数据的二维表 记录 (Record): 表的每一行称为记录(Record),记录是一个逻辑意义上的数据 字段 (Column):表的每一列称为字段(Colu…

Buildroot 构建 Linux 系统

Buildroot 是一个工具,以简化和自动化为嵌入式系统构建完整 Linux 系统的过程。使用交叉编译技术,Buildroot 能够生成交叉编译工具链、根文件系统、Linux 内核映像和针对目标设备的引导加载程序。可以独立地使用这些选项的任何组合,例如&…