Scrapy多爬虫项目抽离数据处理与数据库操作的最佳实践咨询
Scrapy 多站点爬虫项目重构最佳实践
数据处理逻辑解耦方案
针对多站点规则差异大、处理函数零散的问题,采用按站点拆分独立ItemLoader的方案,完全避免所有逻辑堆积在items.py的情况:
- 公共逻辑抽离复用
把全项目通用的清洗规则(比如去HTML标签、去掉特殊空白符、统一日期格式化这类所有站点都会用到的逻辑)单独放到processors/common.py公共模块,所有站点都可以直接引用,无需重复开发。 - 站点专属逻辑独立存放
新增loaders目录,每个站点对应一个独立的Loader文件,站点专属的处理函数、字段输入输出处理器都放在对应Loader文件中,和其他站点完全隔离,修改单个站点规则不会影响其他业务。
参考目录结构:
your_project/ ├── items.py # 仅存放统一的Item字段定义,不写任何处理逻辑 ├── loaders/ │ ├── __init__.py │ ├── common.py # 通用清洗函数 │ ├── taobao_loader.py # 淘宝站点专属Loader和处理函数 │ └── jd_loader.py # 京东站点专属Loader和处理函数 └── spiders/
站点专属Loader示例代码:
from scrapy.loader import ItemLoader from itemloaders.processors import TakeFirst, MapCompose from your_project.items import ProductItem from your_project.loaders.common import remove_tags, trim_space # 仅淘宝站点用到的价格处理函数,不会和其他站点逻辑混淆 def parse_taobao_price(value): return int(float(value.replace('¥', '').strip()) * 100) class TaobaoProductLoader(ItemLoader): default_item_class = ProductItem default_output_processor = TakeFirst() title_in = MapCompose(remove_tags, trim_space) price_in = MapCompose(remove_tags, parse_taobao_price)
重构后爬虫代码和原有写法差异极小,只需替换对应Loader即可:
import scrapy from your_project.loaders.taobao_loader import TaobaoProductLoader class TaobaoSpider(scrapy.Spider): name = "taobao" start_urls = ["xxx"] def parse(self, response): loader = TaobaoProductLoader(selector=response) loader.add_xpath('title', "//title/text()") loader.add_xpath('price', "//div[@class='price']/text()") yield loader.load_item()
数据库操作解耦方案
直接使用Scrapy原生的Pipeline机制处理所有持久化逻辑,完全移除爬虫文件中的数据库操作:
- 所有数据库增删改查逻辑都写到Pipeline中,爬虫只负责yield Item,不需要关心数据存储的任何细节,后续更换数据库、修改存储规则都只需要改Pipeline代码,无需调整爬虫逻辑。
Pipeline示例代码:
import pymysql from your_project.items import ProductItem class MySQLPipeline: def open_spider(self, spider): # 爬虫启动时初始化数据库连接 self.conn = pymysql.connect( host='127.0.0.1', user='root', password='your_password', database='crawler', charset='utf8mb4' ) self.cursor = self.conn.cursor() def process_item(self, item, spider): if isinstance(item, ProductItem): sql = "INSERT INTO product (title, price) VALUES (%s, %s)" self.cursor.execute(sql, (item['title'], item['price'])) self.conn.commit() return item def close_spider(self, spider): # 爬虫关闭时释放连接 self.cursor.close() self.conn.close()
写完后只需要在settings.py中开启该Pipeline即可生效,如需区分站点做不同的存储逻辑,只需在process_item方法中通过spider.name判断当前运行的爬虫即可。
重构后核心优势
- 各层逻辑完全解耦:爬虫只负责页面解析取原始数据、Loader只负责数据清洗、Pipeline只负责持久化,哪部分出问题修改对应模块即可,互不影响
- 维护成本大幅降低:站点专属逻辑独立存放,通用逻辑复用,不会出现大量零散函数堆积在同个文件的问题
- 扩展效率高:新增站点只需要新增对应爬虫文件、专属Loader即可,公共逻辑直接复用,无需重复开发
内容的提问来源于stack exchange,提问作者Xus
相关产品推荐
相关产品推荐

