2018-11-07 Scrapy 实战(4)--存储到数据库

文章由本人博客首发: http://qinfei.glrsmart.com/2018/11/07/scrapy-shi-zhan-4-cun-chu-dao-shu-ju-ku/

前面说了,顺顺利利地爬到了数据,我们可不是为了只是 print 出来炫技的,分析,自己建立关系,存库, 数据就易主了有木有?

我们这里使用 ORM 神器 sqlalchemy 听说过吗? 我在flask, twisted 里面经常用哦.

安装什么的都不说了,直接上代码,毕竟很多童鞋等着看代码,不想听我废话.

再说一句, 就一句. 在 ORM 里面 我就喜欢 models controllers 建一大堆,分层才好维护,虽然文件显得多了一些.什么? 这些文件建在哪一层目录? 别急, 我在最后一节(杂谈)附上我的工程目录结构.

先建 model:

init.py

from sqlalchemy.ext.declarative import declarative_base

# declarative_base()类工厂函数,会根据不同的数据库引擎创建基类, 通过继承基类来创建与数据库表对应的类
Base = declarative_base()
# 在这里 import models 中的对象如果mysql 表不存在会自动创建表
from .body_seg import BodySeg
from ..controllers import engine

Base.metadata.create_all(engine)

body_seg.py

# -*- coding: utf-8 -*-
from . import Base
from sqlalchemy import Column, String, Integer
# from sqlalchemy.orm import relationship


class BodySeg(Base):
    __tablename__ = 'body_seg'

    id = Column(Integer, nullable=False, primary_key=True, autoincrement=True)
    seg_name = Column(String(32), nullable=True)

models 就完成啦.

下面 controllers:

init.py

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from sqlalchemy.pool import NullPool


SQLALCHEMY_DATABASE_URI = 'mysql+mysqldb://username:passwd@ip:port/dbname?charset=utf8'
engine = create_engine(SQLALCHEMY_DATABASE_URI, poolclass=NullPool)
Session = sessionmaker(bind=engine)

body_seg.py

from . import Session
from ..models.body_seg import BodySeg
from sqlalchemy.exc import IntegrityError


def add(seg_name):
    '''
    添加seg
    
    :param seg_name: 
    :return: 
    '''
    session = Session()
    record = session.query(BodySeg).filter_by(seg_name=seg_name).first()
    if not record:
        record = BodySeg(seg_name=seg_name)
        session.add(record)
    try:
        result = True
        session.commit()
    except IntegrityError:
        session.rollback()
        result = False
    session.close()
    return result


def get_all_segs():
    '''
    查询所有seg,只返回seg 名字
    
    :return: seg名字列表,格式: [("name",), ("name",)]
    '''
    session = Session()
    segs = session.query(BodySeg.seg_name).all()
    session.close()
    return segs

然后 controllers 也建好啦!

下面就是见证奇迹的时刻,我们再贴一遍 pipeline 里面的代码:

from .items import BodySegItem
from .controllers import body_seg


class BodySegPipeline:
    def process_item(self, item, spider):
        """
        处理大类数据

        这个方法必须实现,每个item pipeline组件都需要调用该方法,
        这个方法必须返回一个 Item 对象
        被丢弃的item将不会被之后的pipeline组件所处理。

        :param item: item (Item 对象) – 被爬取的item
        :param spider: (Spider 对象) – 爬取该item的spider
        :return:
        """
        if isinstance(item, BodySegItem):
            body_seg.add(seg_name=item["seg"])
        return item

看到了吗? 直接使用 body_seg.add(seg_name=item["seg"])就可以写入数据库啦, 也不用管数据库里面表有没有建好, sqlalchemy 会自动帮你处理的.

启动爬虫, 数据就会源源不断地流入到我们的数据库啦

你可能感兴趣的:(2018-11-07 Scrapy 实战(4)--存储到数据库)