Python爬虫保存案例如何保存爬取数据

wen python案例 27

本文目录导读:

Python爬虫保存案例如何保存爬取数据

  1. 基础文件保存方式
  2. 数据库保存方式
  3. 使用Pandas保存数据
  4. 综合案例:完整的爬虫数据保存
  5. 最佳实践建议

我来详细介绍Python爬虫保存数据的多种方式及完整案例:

基础文件保存方式

1 保存为JSON文件

import json
import requests
def save_to_json():
    # 爬取数据
    url = "https://api.example.com/data"
    response = requests.get(url)
    data = response.json()
    # 保存为JSON
    with open('data.json', 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=4)
    print("数据已保存为JSON文件")
# 完整案例
def crawl_and_save_json():
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    }
    # 假设爬取一些文章数据
    articles = [
        {'title': '文章1', 'content': '内容1', 'date': '2024-01-01'},
        {'title': '文章2', 'content': '内容2', 'date': '2024-01-02'}
    ]
    # 保存到JSON文件
    with open('articles.json', 'w', encoding='utf-8') as f:
        json.dump(articles, f, ensure_ascii=False, indent=2)
    print(f"成功保存 {len(articles)} 篇文章到 articles.json")
crawl_and_save_json()

2 保存为CSV文件

import csv
import requests
from bs4 import BeautifulSoup
def save_to_csv():
    # 示例数据
    data = [
        ['标题', '作者', '日期', '链接'],
        ['Python教程', '张三', '2024-01-01', 'http://example.com/1'],
        ['数据科学入门', '李四', '2024-01-02', 'http://example.com/2']
    ]
    # 保存为CSV
    with open('data.csv', 'w', newline='', encoding='utf-8-sig') as f:
        writer = csv.writer(f)
        writer.writerows(data)
    print("数据已保存为CSV文件")
# 完整爬取并保存案例
def crawl_and_save_csv():
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    }
    # 模拟爬取的新闻数据
    news_data = []
    for i in range(10):
        news_data.append([
            f'新闻标题{i+1}',
            f'作者{i+1}',
            f'2024-01-{i+1:02d}',
            f'http://example.com/news/{i+1}'
        ])
    # 写入CSV
    with open('news.csv', 'w', newline='', encoding='utf-8-sig') as f:
        writer = csv.writer(f)
        writer.writerow(['标题', '作者', '日期', '链接'])  # 写入表头
        writer.writerows(news_data)  # 写入数据
    print(f"成功保存 {len(news_data)} 条新闻到 news.csv")
crawl_and_save_csv()

数据库保存方式

1 SQLite数据库

import sqlite3
import requests
from datetime import datetime
class DataSaver:
    def __init__(self, db_name='crawl_data.db'):
        self.conn = sqlite3.connect(db_name)
        self.cursor = self.conn.cursor()
        self.create_tables()
    def create_tables(self):
        # 创建文章表
        self.cursor.execute('''
            CREATE TABLE IF NOT EXISTS articles (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                title TEXT NOT NULL,
                content TEXT,
                author TEXT,
                publish_date TEXT,
                source_url TEXT UNIQUE,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ''')
        self.conn.commit()
    def save_article(self, article):
        try:
            self.cursor.execute('''
                INSERT INTO articles 
                (title, content, author, publish_date, source_url)
                VALUES (?, ?, ?, ?, ?)
            ''', (
                article['title'],
                article.get('content', ''),
                article.get('author', ''),
                article.get('publish_date', ''),
                article['source_url']
            ))
            self.conn.commit()
            print(f"保存文章: {article['title']}")
        except sqlite3.IntegrityError:
            print(f"文章已存在: {article['title']}")
    def save_batch(self, articles):
        for article in articles:
            self.save_article(article)
    def close(self):
        self.conn.close()
# 使用示例
def crawl_and_save_to_db():
    # 模拟爬取数据
    articles = [
        {
            'title': 'Python爬虫入门',
            'content': '这是一个完整的爬虫教程...',
            'author': '张三',
            'publish_date': '2024-01-15',
            'source_url': 'http://example.com/1'
        },
        {
            'title': '数据分析基础',
            'content': '学习数据处理的技巧...',
            'author': '李四',
            'publish_date': '2024-01-16',
            'source_url': 'http://example.com/2'
        }
    ]
    # 保存到数据库
    saver = DataSaver()
    saver.save_batch(articles)
    saver.close()
    print("数据已保存到数据库")
crawl_and_save_to_db()

2 MySQL数据库

import pymysql
import requests
from typing import List, Dict
class MySQLDataSaver:
    def __init__(self, host='localhost', port=3306, user='root', 
                 password='password', database='crawl_data'):
        self.connection = pymysql.connect(
            host=host,
            port=port,
            user=user,
            password=password,
            database=database,
            charset='utf8mb4'
        )
        self.cursor = self.connection.cursor()
        self.create_table()
    def create_table(self):
        sql = '''
            CREATE TABLE IF NOT EXISTS products (
                id INT AUTO_INCREMENT PRIMARY KEY,
                name VARCHAR(255) NOT NULL,
                price DECIMAL(10, 2),
                description TEXT,
                category VARCHAR(100),
                source_url VARCHAR(500) UNIQUE,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        '''
        self.cursor.execute(sql)
        self.connection.commit()
    def save_product(self, product: Dict):
        sql = '''
            INSERT INTO products (name, price, description, category, source_url)
            VALUES (%s, %s, %s, %s, %s)
            ON DUPLICATE KEY UPDATE
            price = VALUES(price),
            description = VALUES(description)
        '''
        try:
            self.cursor.execute(sql, (
                product['name'],
                product['price'],
                product['description'],
                product['category'],
                product['source_url']
            ))
            self.connection.commit()
        except Exception as e:
            print(f"保存出错: {e}")
            self.connection.rollback()
    def close(self):
        self.cursor.close()
        self.connection.close()
# 使用示例
def save_products_example():
    products = [
        {
            'name': '笔记本电脑',
            'price': 5999.00,
            'description': '高性能轻薄本',
            'category': '电子产品',
            'source_url': 'http://example.com/product/1'
        }
    ]
    saver = MySQLDataSaver()
    for product in products:
        saver.save_product(product)
    saver.close()
# save_products_example()  # 需要MySQL环境才能运行

使用Pandas保存数据

import pandas as pd
import requests
def save_with_pandas():
    # 爬取数据并转换为DataFrame
    data = {
        'title': ['文章1', '文章2', '文章3'],
        'author': ['张三', '李四', '王五'],
        'views': [100, 200, 150],
        'date': ['2024-01-01', '2024-01-02', '2024-01-03']
    }
    df = pd.DataFrame(data)
    # 保存为多种格式
    # CSV格式
    df.to_csv('data_pandas.csv', index=False, encoding='utf-8-sig')
    # Excel格式(需要安装openpyxl)
    df.to_excel('data_pandas.xlsx', index=False)
    # JSON格式
    df.to_json('data_pandas.json', orient='records', force_ascii=False)
    # HTML表格
    df.to_html('data_pandas.html', index=False)
    print("使用Pandas保存数据完成")
save_with_pandas()

综合案例:完整的爬虫数据保存

import requests
from bs4 import BeautifulSoup
import json
import csv
import sqlite3
from datetime import datetime
import os
class CrawlerDataSaver:
    """完整的爬虫数据保存器"""
    def __init__(self, name='crawler'):
        self.name = name
        self.data = []
        self.setup_directories()
    def setup_directories(self):
        """创建必要的目录"""
        for dir_name in ['json', 'csv', 'db', 'excel']:
            os.makedirs(dir_name, exist_ok=True)
    def add_data(self, item):
        """添加数据"""
        self.data.append(item)
    def save_to_json(self, filename=None):
        """保存为JSON"""
        if not filename:
            filename = f"json/{self.name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(self.data, f, ensure_ascii=False, indent=2)
        print(f"保存JSON: {filename}")
        return filename
    def save_to_csv(self, filename=None):
        """保存为CSV"""
        if not filename:
            filename = f"csv/{self.name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
        if not self.data:
            print("没有数据可保存")
            return
        # 获取字段名
        fields = self.data[0].keys()
        with open(filename, 'w', newline='', encoding='utf-8-sig') as f:
            writer = csv.DictWriter(f, fieldnames=fields)
            writer.writeheader()
            writer.writerows(self.data)
        print(f"保存CSV: {filename}")
        return filename
    def save_to_sqlite(self, table_name=None, db_name=None):
        """保存到SQLite"""
        if not db_name:
            db_name = f"db/{self.name}_{datetime.now().strftime('%Y%m%d')}.db"
        if not table_name:
            table_name = self.name
        conn = sqlite3.connect(db_name)
        cursor = conn.cursor()
        # 动态创建表
        if self.data:
            fields = self.data[0].keys()
            field_types = ', '.join([f"{field} TEXT" for field in fields])
            cursor.execute(f'''
                CREATE TABLE IF NOT EXISTS {table_name} (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    {field_types}
                )
            ''')
            # 插入数据
            placeholders = ', '.join(['?' for _ in fields])
            columns = ', '.join(fields)
            for item in self.data:
                values = [str(item.get(field, '')) for field in fields]
                cursor.execute(f'''
                    INSERT INTO {table_name} ({columns})
                    VALUES ({placeholders})
                ''', values)
            conn.commit()
        conn.close()
        print(f"保存到SQLite: {db_name}")
        return db_name
    def save_all_formats(self):
        """保存所有格式"""
        results = {}
        results['json'] = self.save_to_json()
        results['csv'] = self.save_to_csv()
        results['sqlite'] = self.save_to_sqlite()
        return results
# 使用示例
def complete_crawler_example():
    # 创建爬虫数据保存器
    saver = CrawlerDataSaver('news_articles')
    # 模拟爬取数据
    for i in range(5):
        saver.add_data({
            'title': f'新闻标题{i+1}',
            'content': f'这是第{i+1}条新闻的详细内容...',
            'author': f'作者{i+1}',
            'date': datetime.now().strftime('%Y-%m-%d'),
            'url': f'http://example.com/news/{i+1}'
        })
    # 保存所有格式
    saver.save_all_formats()
    print("\n爬虫数据保存完成!")
complete_crawler_example()

最佳实践建议

1 数据保存配置

import configparser
def save_config_example():
    config = configparser.ConfigParser()
    # 创建配置文件
    config['Database'] = {
        'type': 'sqlite',
        'path': './data',
        'backup': 'True'
    }
    config['Export'] = {
        'formats': 'json,csv,excel',
        'encoding': 'utf-8'
    }
    config['Crawler'] = {
        'delay': '1',
        'user_agent': 'Mozilla/5.0'
    }
    # 保存配置
    with open('config.ini', 'w') as f:
        config.write(f)
# save_config_example()

2 错误处理和重试机制

import time
from functools import wraps
def retry_on_failure(max_retries=3, delay=1):
    """重试装饰器"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_retries - 1:
                        raise e
                    print(f"保存失败,重试中... (尝试 {attempt + 1}/{max_retries})")
                    time.sleep(delay)
            return None
        return wrapper
    return decorator
class SafeDataSaver:
    def __init__(self):
        self.failed_items = []
    @retry_on_failure(max_retries=3)
    def save_item(self, item):
        # 模拟保存操作
        if not item.get('title'):
            raise ValueError("缺少标题")
        # 实际保存代码...
        print(f"保存成功: {item['title']}")
    def save_batch(self, items):
        for item in items:
            try:
                self.save_item(item)
            except Exception as e:
                print(f"保存失败: {e}")
                self.failed_items.append(item)
        # 处理失败的项
        if self.failed_items:
            print(f"有 {len(self.failed_items)} 项保存失败")
            # 保存失败项到单独的文件
            with open('failed_items.json', 'w', encoding='utf-8') as f:
                json.dump(self.failed_items, f, ensure_ascii=False)
# 使用示例
def safe_save_example():
    saver = SafeDataSaver()
    items = [
        {'title': '文章1', 'content': '内容1'},
        {'title': '', 'content': '内容2'},  # 会失败
        {'title': '文章3', 'content': '内容3'}
    ]
    saver.save_batch(items)
safe_save_example()

选择合适的保存方式取决于:

  • 数据量大小
  • 是否需要持久化
  • 后期如何处理数据
  • 是否需要支持复杂查询

推荐方案:

  1. 小数据量:JSON或CSV文件
  2. 中等数据量:SQLite数据库
  3. 大数据量:MySQL/PostgreSQL
  4. 需要分析:Pandas + 多种导出格式

记得在处理中文时使用 utf-8utf-8-sig 编码,并添加合适的错误处理机制。

抱歉,评论功能暂时关闭!