Scrapy 数据存入 MySQL:同步与异步实现详解

陆景行
陆景行
发布时间:2026-10-13| 6人浏览过
原创

本文详细介绍 Scrapy 框架将数据持久化至 MySQL 数据库的两种核心方式:同步操作与基于 Twisted 的异步存储。文章涵盖 pipelines.py 配置、数据库连接池建立及错误处理机制,并针对中文乱码、特殊字符报错及重复数据累积问题提供具体解决方案,包括使用 pymysql.escape_string 和 scrapy-deltafetch 等插件实现增量爬取。

Scrapy 同步存储 MySQL 实现

方法一:同步操作

首先,在 pipelines.py 文件中编写处理数据的 Python 代码。


import pymysql
 
class LvyouPipeline(object):
  def __init__(self):
    # connection database
    self.connect = pymysql.connect(host='XXX', user='root', passwd='XXX', db='scrapy_test') # 后面三个依次是数据库连接名、数据库密码、数据库名称
    # get cursor
    self.cursor = self.connect.cursor()
    print("连接数据库成功")
 
  def process_item(self, item, spider):
    # sql语句
    insert_sql = """
    insert into lvyou(name1, address, grade, score, price) VALUES (%s,%s,%s,%s,%s)
    """
    # 执行插入数据到数据库操作
    self.cursor.execute(insert_sql, (item['Name'], item['Address'], item['Grade'], item['Score'],
                     item['Price']))
    # 提交,不进行提交无法保存到数据库
    self.connect.commit()
 
  def close_spider(self, spider):
    # 关闭游标和连接
    self.cursor.close()
    self.connect.close()

其次,在项目的配置文件中启用该 Pipeline。

Scrapy 异步存储 MySQL 实现

方式二:异步存储

在 pipelines.py 文件中实现异步逻辑。

利用 Twisted 模块实现数据库的异步插入,Twisted 提供了 twisted.enterprise.adbapi 接口。

第一步,导入 adbapi 模块。

第二步,生成数据库连接池。

第三步,执行数据插入数据库的操作。

第四步,打印错误信息并进行排错处理。


import pymysql
from twisted.enterprise import adbapi
# 异步更新操作
class LvyouPipeline(object):
  def __init__(self, dbpool):
    self.dbpool = dbpool
 
  @classmethod
  def from_settings(cls, settings): # 函数名固定,会被scrapy调用,直接可用settings的值
    """
    数据库建立连接
    :param settings: 配置参数
    :return: 实例化参数
    """
    adbparams = dict(
      host=settings['MYSQL_HOST'],
      db=settings['MYSQL_DBNAME'],
      user=settings['MYSQL_USER'],
      password=settings['MYSQL_PASSWORD'],
      cursorclass=pymysql.cursors.DictCursor  # 指定cursor类型
    )
 
    # 连接数据池ConnectionPool,使用pymysql或者Mysqldb连接
    dbpool = adbapi.ConnectionPool('pymysql', **adbparams)
    # 返回实例化参数
    return cls(dbpool)
 
  def process_item(self, item, spider):
    """
    使用twisted将MySQL插入变成异步执行。通过连接池执行具体的sql操作,返回一个对象
    """
    query = self.dbpool.runInteraction(self.do_insert, item) # 指定操作方法和操作数据
    # 添加异常处理
    query.addCallback(self.handle_error) # 处理异常
 
  def do_insert(self, cursor, item):
    # 对数据库进行插入操作,并不需要commit,twisted会自动commit
    insert_sql = """
    insert into lvyou(name1, address, grade, score, price) VALUES (%s,%s,%s,%s,%s)
    """
    self.cursor.execute(insert_sql, (item['Name'], item['Address'], item['Grade'], item['Score'],
                         item['Price']))
 
  def handle_error(self, failure):
    if failure:
      # 打印错误信息
      print(failure)

常见问题与增量爬取方案

注意事项:

1. Python 3.x 版本不再支持 MySQLdb,其替代方案为:import pymysql。

2. 可能遇到报错 pymysql.err.ProgrammingError: (1064, ……

原因分析:当 item['quotes'] 字段内容包含引号时,容易触发上述 SQL 语法错误。

解决办法:调用 pymysql.escape_string() 方法对数据进行转义处理。

例如:


sql = """INSERT INTO video_info(video_id, title) VALUES("%s","%s")""" % (video_info["id"],pymysql.escape_string(video_info["title"]))

3. 当数据包含中文时,数据库连接需添加 charset='utf8' 参数,否则中文显示为乱码。

4. 每次执行爬虫都会将数据追加到数据库中,多次测试会导致相同数据不断累积。如何实现增量爬取?

  • scrapy-deltafetch
  • scrapy-crawl-once(与1不同的是存储的数据库不同)
  • scrapy-redis
  • scrapy-redis-bloomfilter(3的增强版,存储更多的url,查询更快)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。