影刀RPA进阶教程:MySQL数据库读写与Pandas数据互通全流程

SQLite适合单机、小规模数据存储,但一旦你的RPA项目需要多人共享数据、远程访问、高并发写入,SQLite就不够用了。这时候需要切换到MySQL——真正的“客户端-服务器”数据库,支持多用户同时读写、支持远程连接、支持千万级数据量。

我之前帮一个团队做“多店铺销售数据汇总”项目,一开始用的SQLite,数据文件存在共享文件夹里。两个采集流程同时跑的时候频繁报错“数据库被锁定”,后来换成MySQL,问题直接消失,写入速度还快了两倍

picture.image

这篇文章不讲MySQL的理论知识,就讲影刀RPA里怎么连接MySQL、怎么读写数据、怎么用Pandas和MySQL互通。读完你可以把“本地SQLite”升级成“云端MySQL”,让数据在不同流程和不同机器之间共享。


什么时候该用MySQL

场景用SQLite用MySQL
单机单流程✅ 合适杀鸡用牛刀

picture.image | 多流程同时读写 | ❌ 会锁库 | ✅ 支持并发 | | 多台电脑共享数据 | ❌ 文件共享不稳定 | ✅ 服务器集中存储 | | 数据量 > 100万行 | ⚠️ 开始变慢 | ✅ 流畅 | | 需要远程访问 | ❌ 不支持 | ✅ 原生支持 | | 需要用户权限管理 | ❌ 弱 | ✅ 完善的权限体系 |

picture.image

picture.image 核心判断标准:如果你的数据需要在“多台电脑”或“多个流程”之间共享,就应该用MySQL。


picture.image

第一步:安装MySQL和Python驱动

安装MySQL数据库(服务器端)

picture.image 如果公司已有MySQL服务器,直接用。如果没有,在电脑上安装一个:

  1. 去MySQL官网下载MySQL Community Server(社区版,免费)
  2. 安装时设置root密码(务必记好)
  3. 安装完成后,用命令行或Navicat测试连接

picture.image

云数据库方案(推荐,省心):

如果不想自己维护MySQL服务器,用云服务:

  • 阿里云RDS MySQL

picture.image

  • 腾讯云MySQL
  • 华为云GaussDB

按月付费,不用管运维,适合项目型场景。

在影刀里安装Python驱动

影刀的Python环境默认没有安装MySQL驱动,需要手动安装。

在“执行Python代码”指令里运行:

import subprocess
import sys

# 安装pymysql(轻量级MySQL驱动)
subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'pymysql', '-i', 'https://pypi.tuna.tsinghua.edu.cn/simple'])
print("✅ pymysql 安装完成")

# 如果要用Pandas读写MySQL,还需要安装
subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'pandas', 'sqlalchemy', '-i', 'https://pypi.tuna.tsinghua.edu.cn/simple'])
print("✅ pandas + sqlalchemy 安装完成")

注意: 第一次运行时,需要在影刀顶部的Python图标点亮状态下执行这段代码。安装成功后,后续流程就可以直接import pymysql了。

picture.image

第二步:创建数据库和表(首次运行)

# ============================================
# 执行Python代码:创建MySQL数据库和商品表
# 输入:
#   - host(文本):数据库地址,如 "localhost" 或 "192.168.1.100"
#   - user(文本):用户名,如 "root"
#   - password(文本):密码
#   - database(文本):数据库名,如 "rpa_data"
# 输出:无
# ============================================

import pymysql

def init_mysql(host, user, password, database):
    # 先连接到MySQL(不指定数据库)
    conn = pymysql.connect(
        host=host,
        user=user,
        password=password,
        charset='utf8mb4'
    )
    cursor = conn.cursor()
    
    # 创建数据库(如果不存在)
    cursor.execute(f"CREATE DATABASE IF NOT EXISTS {database} DEFAULT CHARSET utf8mb4")
    print(f"✅ 数据库 {database} 已创建")
    
    
![picture.image](https://p6-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/67ed637ede3b4ddeafddef28bd632147~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1783907304&x-signature=qWSf0p1eNx566dJFMWDX2s%2B0mlE%3D)
    # 切换到目标数据库
    conn.select_db(database)
    
    # 创建商品数据表(如果不存在)
    create_table_sql = """
    CREATE TABLE IF NOT EXISTS products (
        id INT AUTO_INCREMENT PRIMARY KEY,
        platform VARCHAR(20) NOT NULL COMMENT '平台名称',
        title VARCHAR(500) NOT NULL COMMENT '商品标题',
        price DECIMAL(10,2) DEFAULT 0.00 COMMENT '价格',
        sales INT DEFAULT 0 COMMENT '销量',
        shop_name VARCHAR(200) COMMENT '店铺名称',
        product_url VARCHAR(500) COMMENT '商品链接',
        collect_date DATE COMMENT '采集日期',
        collect_time TIME COMMENT '采集时间',
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY unique_product (platform, product_url(255))
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
    """
    cursor.execute(create_table_sql)
    print("✅ 数据表 products 已创建")
    
    # 创建索引(提高查询速度)
    cursor.execute("CREATE INDEX idx_date ON products(collect_date)")
    cursor.execute("CREATE INDEX idx_platform ON products(platform)")
    cursor.execute("CREATE INDEX idx_price ON products(price)")
    print("✅ 索引创建完成")
    
    conn.commit()
    cursor.close()
    conn.close()
    
    print("✅ MySQL初始化完成")

# 调用
init_mysql(
    host="localhost",
    user="root",
    password="your_password",
    database="rpa_data"
)

表结构说明:

字段类型说明
idINT自增主键
platformVARCHAR(20)平台名称(拼多多/淘宝/小红书)
titleVARCHAR(500)商品标题(最长500字符)
priceDECIMAL(10,2)价格(10位数字,2位小数)
salesINT销量(整数)
shop_nameVARCHAR(200)店铺名称
product_urlVARCHAR(500)商品链接
collect_dateDATE采集日期
collect_timeTIME采集时间
created_atTIMESTAMP记录创建时间(自动)
updated_atTIMESTAMP记录更新时间(自动)
UNIQUE key(platform, product_url)同一平台同一商品不重复

和SQLite表的区别:

  • MySQL支持TIMESTAMP自动记录时间
  • MySQL支持更精细的DECIMAL浮点数精度
  • MySQL的UNIQUE KEY写法略有不同
  • product_url在UNIQUE里加了长度限制(255字符),因为索引字段不能太长

第三步:批量写入数据到MySQL

# ============================================
# 执行Python代码:批量插入数据到MySQL
# 输入:
#   - data_list(二维列表):每条数据格式:
#     [platform, title, price, sales, shop_name, product_url, collect_date, collect_time]
#   - mysql_config(字典):{host, user, password, database}
# 输出:insert_count(数字)
# ============================================

import pymysql

def batch_insert_mysql(data_list, mysql_config):
    if not data_list:
        return 0
    
    conn = pymysql.connect(
        host=mysql_config['host'],
        user=mysql_config['user'],
        password=mysql_config['password'],
        database=mysql_config['database'],
        charset='utf8mb4'
    )
    cursor = conn.cursor()
    
    # 插入或忽略重复
    insert_sql = """
    INSERT IGNORE INTO products 
    (platform, title, price, sales, shop_name, product_url, collect_date, collect_time)
    VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
    """
    
    success_count = 0
    fail_count = 0
    
    for row in data_list:
        try:
            cursor.execute(insert_sql, (
                row[0],  # platform
                row[1],  # title
                row[2],  # price
                row[3],  # sales
                row[4],  # shop_name
                row[5],  # product_url
                row[6],  # collect_date
                row[7]   # collect_time
            ))
            success_count += 1
        except Exception as e:
            fail_count += 1
            print(f"插入失败:{row[1]},错误:{e}")
    
    conn.commit()
    cursor.close()
    conn.close()
    
    print(f"✅ 批量插入完成:成功{success_count}条,失败{fail_count}条")
    return success_count

关键写法:

INSERT IGNORE INTO 表示如果触发了UNIQUE KEY约束(同一平台同一商品已存在),这条数据会被忽略,不报错。这是实现“增量写入、不重复”的核心。


第四步:从MySQL查询数据到影刀

# ============================================
# 执行Python代码:从MySQL查询数据
# 输入:
#   - query_date(文本):查询日期,格式 YYYY-MM-DD
#   - mysql_config(字典):数据库连接配置
# 输出:result_data(二维列表),第一行是表头
# ============================================

import pymysql

def query_mysql(query_date, mysql_config):
    conn = pymysql.connect(
        host=mysql_config['host'],
        user=mysql_config['user'],
        password=mysql_config['password'],
        database=mysql_config['database'],
        charset='utf8mb4'
    )
    cursor = conn.cursor()
    
    # 查询指定日期的数据,按价格从高到低排序
    sql = """
    SELECT platform, title, price, sales, shop_name, collect_time
    FROM products
    WHERE collect_date = %s
    ORDER BY price DESC
    """
    cursor.execute(sql, (query_date,))
    
    # 获取所有行
    rows = cursor.fetchall()
    
    # 加上表头
    columns = ["平台", "标题", "价格", "销量", "店铺", "采集时间"]
    result = [columns] + [list(row) for row in rows]
    
    cursor.close()
    conn.close()
    
    print(f"✅ 查询到 {len(rows)} 条记录")
    return result

# 调用
result_data = query_mysql("2026-07-06", mysql_config)

在影刀里的用法: 查询结果可以直接用“写入表格数据”写入Excel,或者作为流程下一步的数据源。


第五步:Pandas + MySQL 数据互通(高级)

Pandas可以直接读写MySQL,省去手动拼接SQL的麻烦。

# ============================================
# 执行Python代码:Pandas读写MySQL
# 输入:
#   - mysql_config(字典)
#   - collect_date(文本)
# 输出:
#   - df_json(JSON字符串),Pandas DataFrame的JSON格式
# ============================================

import pandas as pd
from sqlalchemy import create_engine
import json

def pandas_mysql_demo(mysql_config, collect_date):
    # 创建数据库连接(SQLAlchemy)
    db_url = f"mysql+pymysql://{mysql_config['user']}:{mysql_config['password']}@{mysql_config['host']}/{mysql_config['database']}?charset=utf8mb4"
    engine = create_engine(db_url)
    
    # ===== 读取:MySQL → Pandas =====
    df = pd.read_sql(
        f"SELECT * FROM products WHERE collect_date = '{collect_date}' ORDER BY price DESC",
        engine
    )
    print(f"✅ 从MySQL读取 {len(df)} 条数据到Pandas")
    
    # ===== 用Pandas做数据分析 =====
    # 各平台平均价格
    avg_price_by_platform = df.groupby('platform')['price'].mean()
    print("各平台平均价格:")
    print(avg_price_by_platform)
    
    # 销量TOP10
    top10 = df.nlargest(10, 'sales')[['title', 'sales', 'price']]
    print("销量TOP10:")
    print(top10)
    
    # ===== 写入:Pandas → MySQL(新表) =====
    # 把分析结果写入一个新表
    top10.to_sql('top10_products', engine, if_exists='replace', index=False)
    print("✅ TOP10数据已写入MySQL表 top10_products")
    
    # ===== 返回DataFrame的JSON(给影刀用) =====
    return df.to_json(orient='records', force_ascii=False)

# 调用
df_json = pandas_mysql_demo(mysql_config, "2026-07-06")

这个写法的价值:

  • 用Pandas做数据透视、分组、排序、去重,一行代码顶影刀十行循环
  • 分析结果可以直接写回MySQL,也可以传给影刀做后续处理
  • 适合“采集→分析→存储”一体化流程

第六步:MySQL连接池配置(多流程共享)

如果多个流程同时访问MySQL,每次都新建连接、断开连接,效率很低。

推荐:在MySQL连接配置中开启连接池。

# 用SQLAlchemy的连接池
from sqlalchemy import create_engine

# 连接池配置
engine = create_engine(
    db_url,
    pool_size=5,           # 连接池大小
    max_overflow=10,       # 最大额外连接数
    pool_recycle=3600,     # 连接回收时间(秒)
    pool_pre_ping=True     # 使用前检查连接是否有效
)

# 所有读写操作都用这个engine,不要反复创建

在影刀里的实践:

  • engine创建在“执行Python代码”的外部(比如做成全局变量),不要让每次调用都重新创建连接
  • 或者在主流程里创建一次连接,传递给多个子流程使用

MySQL常用SQL速查表

操作SQL语句说明
插入(忽略重复)INSERT IGNORE INTO 表名 VALUES (...)已存在则跳过
插入(更新重复)INSERT ... ON DUPLICATE KEY UPDATE 价格=VALUES(价格)已存在则更新价格
查询全部SELECT * FROM 表名返回所有数据
条件查询SELECT * FROM 表名 WHERE 价格 > 50按条件筛选
排序查询SELECT * FROM 表名 ORDER BY 销量 DESC LIMIT 20销量TOP20
分组统计SELECT 平台, COUNT(*) FROM 表名 GROUP BY 平台按平台统计数量
日期范围SELECT * FROM 表名 WHERE 采集日期 BETWEEN '2026-07-01' AND '2026-07-07'按日期区间筛选
模糊匹配SELECT * FROM 表名 WHERE 标题 LIKE '%耳机%'标题包含“耳机”
删除旧数据DELETE FROM 表名 WHERE 采集日期 < '2026-06-01'删除指定日期前数据
清空表TRUNCATE TABLE 表名删除所有数据(比DELETE快)

容易踩的坑速查表

现象排查方向修复方法
连接报错“Access denied”用户名或密码错了检查user和password是否正确
连接报错“Can't connect”MySQL服务没启动或地址错了检查host是否正确,MySQL是否运行中
连接报错“Unknown database”数据库名写错了先用SQLite风格创建数据库,或检查database名
插入中文报错乱码字符集没设好连接时指定charset='utf8mb4'
插入报错“Data too long”字段长度不够检查表结构,加长VARCHAR长度
查询返回空列表日期格式不匹配确保传入的日期和数据库里存的格式一致(YYYY-MM-DD)
多流程同时写入卡死连接池满了增大pool_size或减少并发数
数据在MySQL里能看到,但影刀读不到SQL语句的条件写错了在Navicat里验证SQL语句是否正确

MySQL vs SQLite 选择指南

场景用SQLite用MySQL
单个流程、本地数据
多个流程、同一台电脑⚠️ 可能锁库
多台电脑、数据共享❌ 无法共享✅ 远程访问
数据量 < 10万行
数据量 > 100万行⚠️
需要数据备份/恢复⚠️ 手动备份✅ 原生支持
需要图形化管理工具SQLiteStudioNavicat/DBeaver
部署和运维成本零(一个文件)需要安装配置

一条核心建议

迁移到MySQL的时机:当你开始出现“数据库被锁定”报错,或者需要在多台电脑之间共享数据时,就该迁移了。

迁移的路径建议:

  1. 第一步:先搭一个本地MySQL,把现有SQLite数据导入进去(用INSERT ... SELECT或导出CSV再导入)
  2. 第二步:把流程里的数据库连接地址从products.db改成localhost:3306
  3. 第三步:确认流程能正常读写MySQL
  4. 第四步:把MySQL迁移到云服务器,让所有电脑共享

迁移过程中最容易踩的坑是“字符集”——中文显示为乱码。解决办法:所有地方统一用utf8mb4(MySQL的UTF-8完整版),连接时指定charset='utf8mb4',表的字符集也设成utf8mb4

另外,永远不要在流程里硬编码数据库密码。用流程参数或环境变量存储敏感信息,避免密码泄露。


推荐资源

  • MySQL官方文档:安装指南
  • Navicat / DBeaver(MySQL图形化管理工具,比命令行直观)
  • 影刀社区示例:“MySQL数据存储模板”(搜索“MySQL”)

#影刀RPA #RPA自动化 #MySQL #数据库 #Pandas

作者:林焱

本文为《影刀RPA学习手册》系列文章之一,内容源于实操经验的整理与分享。

0
0
0
0
评论
未登录
暂无评论