在scrapy中使用pipeline可以将抓取到的数据存储于数据库或者文件中,但在实际操作过程中,如果不采用第三方orm库,需要自己构造sql语句,进行数据库操作,如果操作数据库的字段较多时,容易出现错误,并且为重复的体力劳动。于是,考虑使用python比较成熟的第三方orm库,将便于数据入库的操作。由于笔者之前使用过django来搭建web站点,对django的model印象深刻,只需要将数据存储于对象中,而该对象对应了数据库中表,只需要调用简单命令save等,就可以将数据入库。因此,考虑使用django中的model来存储数据。
目前,我还没有找到将model模块直接从django中剥离的办法,只能采取比较笨重的方法(参考:http://doc.scrapy.org/en/0.24/topics/djangoitem.html),即新建一个django项目,然后用scrapy去调用其中已经设置好的model模块,实现数据的存储。若有更好的方法,希望告知。
首先就是安装scrapy和django,由于涉及到很多第三方库,此处可以参考官网文档,此处的版本为scrapy:0.24.5,django:1.7.7
安装完毕后,分别新建django项目和scrapy项目,并且在django新项目下创建app silo分别命名如下,
$ scrapy startproject demo
$ django-admin.py startproject demosite
$ cd demosite/
$ python manage.py startapp silo
$ cd ../..
$ tree
.
└── django-scrapy
├── demo
│ ├── demo
│ │ ├── __init__.py
│ │ ├── items.py
│ │ ├── pipelines.py
│ │ ├── settings.py
│ │ └── spiders
│ │ └── __init__.py
│ └── scrapy.cfg
└── demosite
├── demosite
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── settings.py
│ ├── settings.pyc
│ ├── urls.py
│ └── wsgi.py
├── manage.py
└── silo
├── admin.py
├── __init__.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
.
└── django-scrapy
├── demo
│ ├── demo
│ │ ├── __init__.py
│ │ ├── items.py
│ │ ├── pipelines.py
│ │ ├── settings.py
│ │ └── spiders
│ │ └── __init__.py
│ └── scrapy.cfg
└── demosite
├── demosite
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── settings.py
│ ├── settings.pyc
│ ├── urls.py
│ └── wsgi.py
├── manage.py
└── silo
├── admin.py
├── __init__.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
首先,需要在django项目demosite的目录下配置model,在创建好的silo app中添加与数据库相互映射的类,
./django-scrapy/demosite/silo/models.py
from django.db import models
class Demo_data(models.Model):
class Demo_data(models.Model):
iAutoId = models.AutoField(primary_key=True, default=None)
title = models.CharField(max_length=256, default=None)
title = models.CharField(max_length=256, default=None)
...
然后在demotie的setting文件中配置数据库以及app信息,
./django-scrapy/demosite/demosite
# 数据库信息
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 使用mysql进行数据存储
'NAME': 'demo_db',
'USER': 'admin',
'PASSWORD': 'admin',
'HOST': '192168.0.100',
'PORT': '3306'
}
}
'default': {
'ENGINE': 'django.db.backends.mysql', # 使用mysql进行数据存储
'NAME': 'demo_db',
'USER': 'admin',
'PASSWORD': 'admin',
'HOST': '192168.0.100',
'PORT': '3306'
}
}
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'silo', # 加入使用的app
)
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'silo', # 加入使用的app
)
然后返回demosite的根目录 ./django-scrapy/demosite/,运行命令创建model以及数据库映射
$ python manage.py makemigrations
$ python manage.py migrate
注:如果需要重新创建表,在数据中直接删除表,会造成django项目的出错,可以按照下面步骤操作(http://stackoverflow.com/questions/27583744/django-table-doesnt-exist)
1. 删除数据库中表
2. 在models.py中注释对应的class
3. 在django项目根目录下运行命令
$ python manage.py makemigrations
$ python manage.py migrate --fake
4. 将models.py中的类取消注释
5. 在django项目根目录下运行命令
$ python manage.py makemigrations
$ python manage.py migrate
此时,可以看到,数据库中将会创建一张全新的表
紧接着,需要在scrapy项目中进行配置,并且将django中创建的model导入其中。在./django-scrapy/demo/demo中的settings.py中进行下面配置
./django-scrapy/demo/demo/settings.py
import sys
sys.path.append('../../demosite')
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'demosite.settings'
sys.path.append('../../demosite')
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'demosite.settings'
然后在./django-scrapy/demo/demo/items.py中定义item,
./django-scrapy/demo/demo/items.py
from scrapy.contrib.djangoitem import DjangoItem
from silo.models import Demo_data
from silo.models import Demo_data
class DemoItem(DjangoItem):
django_model =Demo_data
django_model =Demo_data
最后就可以在pipeline中进行数据的存储,大功告成,比起之前繁琐的sql语句,此处只需要一句save就解决问题。
./django-scrapy/demo/demo/pipelines.py
class DemoPipeline(object):
def process_item(self, item, spider):
item.save()
return item
def process_item(self, item, spider):
item.save()
return item
当然,该处还可以进行更深的挖掘,希望大家拍砖。