前言
Scrapy爬取到的数据可以使用MySql持久化存储,通常Scrapy通过在pipiline.py里面连接数据库获取游标,然后写原生SQL语句来插入数据到Mysql里面,所以一旦数据字段较多时,pipiline里面会出现大段SQL语句,十分难受,那么有没办法跟Django一样,有一个模型然后直接model.save就可以存储数据呢?事实上SQLAlchemy就是Python里面最有名的ORM框架,使用它来写一个model类,然后就可以给Scrapy使用。
创建Model模块
由于我们项目下可能会有多个爬虫,因此我们建立一个Model包,然后在下面对应每个爬虫新增一个model的模块,我项目下已有四个爬虫,因此对应四个model模块:
由于是model包,因此必须有init.py文件,为了方便后面使用,我们将数据库连接方式和返回数据库连接会话的函数都放到init.py里面:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
#创建对象基类
Base = declarative_base()
#初始化数据库连接
engine = create_engine('mysql+pymysql://root:12345678@localhost:3306/get_ais?charset=utf8',pool_size=100)
#返回数据库会话
def loadSession():
Session = sessionmaker(bind=engine)
session = Session()
return session
在model包里面创建爬虫对应的model模块,其中的字段跟item里面的对应,例如get_ais_xs这个爬虫,对应的item类如下:
class GetAisItem_JQXS(scrapy.Item):
# define the fields for your item here like:
xs_name = scrapy.Field()
xs_xq_url = scrapy.Field()
xs_type = scrapy.Field()
xs_pf = scrapy.Field()
xs_createdate = scrapy.Field()
xs_text = scrapy.Field()
根据以上item在model包里面创建ais_xs.py模块和存储表对应的类,内容如下:
from sqlalchemy import String,Column,DateTime,Text,Integer
from . import Base
#必须继承基类
class XS(Base):
#类对应的数据库表名
__tablename__ = 'ais_xs'
#设置主建,不能重复
xs_xq_url = Column(String(100),primary_key = True,nullable = False)
xs_name = Column(String(100),nullable = True)
xs_type = Column(String(20),nullable = True)
xs_pf = Column(String(10),nullable = True)
xs_createdate = Column(DateTime,nullable = True)
xs_text = Column(Text,nullable = True)
在pipiline里面使用model类
上面已经创建了model,那么scrapy里面怎么使用呢?如下述代码,直接在pipiline里面引入即可,具体详见代码:
#引入model里面的基类、数据库连接、数据库连接会话函数
from .model import Base,engine,loadSession
#引入model里面对应爬虫的model模块
from .model import ais_xs
import logging
class GetAisPipeline:
#搜索Base的所有子类,并在数据库中生成表
Base.metadata.create_all(engine)
def process_item(self, item, spider):
try:
#直接将爬虫yield的item赋值成一个model的对象
a = ais_xs.XS(
xs_xq_url = item['xs_xq_url'],
xs_name = item['xs_name'][0],
xs_type = item['xs_type'][0],
xs_pf = item['xs_pf'][0],
xs_createdate = item['xs_createdate'][0],
xs_text = item['xs_text'][0]
)
#获取数据库连接
session = loadSession()
#将item变成的对象保存进数据库
session.add(a)
#提交事务
session.commit()
except Exception as e:
logging.info(e)
如此及以达成了不使用SQL语句而持久化保存爬取到的数据到mysql的目标。