Conectar Scrapy con Django

Mi solución (no necesesariamente la mejor) para integrar Django con Scrapy .

Python Data

Primers Pasos

Vamos a utilizar Django para acceder, almacenar y probablemente presentar también de manera sencilla los datos que queremos extraer con Scrapy. También necesitaremos la extensión scrapy-djangoitem que conectará el modelo de datos de los dos frameworks. El proyecto de Scrapy debería estar dentro del proyecto de Django, al mismo nivel que una app.

Si estás leyendo este post, supongo que tienes un conocimiento básico de cómo funcionan Djngo y Srapy. Si no, te recomiendo que eches un vistazo a los siguientes enlaces:

# Ejemplo de cuál debería ser el árbol de directorios
...
├── requirements.txt
├── manage.py
├── django-project
│   ├── django-project
│   │   ├── settings.py
│   │   ├── urls.py
│   │   ├── views.py
│   │   └── wsgi.py
│   ├── example-app
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── migrations
│   │   ├── models.py
│   │   ├── static
│   │   │   ├── ...
│   │   ├── templates
│   │   │   ├── ...
│   │   ├── tests.py
│   │   ├── urls.py
│   │   ├── views.py
│   ├── scrapy-proyect
│   │   ├── ..  
│   │   ├── apps.py
│   │   ├── crawlproperty.py
│   │   ├── geckodriver.log
│   │   ├── items.py
│   │   ├── middlewares.py
│   │   ├── pipelines.py
│   │   ├── settings.py
│   │   ├── spiders
│   │   │   ├── spider.py
...

Configuración de Django

Asegúrate de añadir la app de Django y el proyecto de Scrapy al archivo de configuración del proyecto de Django django-project/django-project/settings.py:

INSTALLED_APPS = [
    'example-app.apps.ExampleAppConfig',
    'scrapy-proyect.apps.ScrapyProyectConfig',
    ...
]

Configuración de Scrapy

Necesitamos añadir un archivo init.py vacio en django-project/scrapy-project/__init__.py y en django-project/scrapy-project/spiders/__init__.py para que Django reconozca el proyecto de Scrapy como un paquete.

Para que Django y Scrapy sean capaces de comunicarse, también es necesario modificar el archivo de configuración de django-project/scrapy-project/settings.py:

import sys
import os
import django
# ------------ DJANGO SETTINGS ------------
sys.path.append('../dedomeno')
os.environ['DJANGO_SETTINGS_MODULE'] = 'django-project.settings'
django.setup()  # for > django 1.7

BOT_NAME = 'scrapy-project'

SPIDER_MODULES = ['scrapy-project.spiders']
NEWSPIDER_MODULE = 'scrapy-project.spiders'
...

Es necesario crear django-project/scrapy-project/apps.py para que el proyecto de Scrapy sea identificado por Django como una app:

from django.apps import AppConfig

class ScrapyPrpjectConfig(AppConfig):
    name = 'scrapy-project'

En django-project/scrapy-project/items.py se crean los Items de Scrapy, que heredan de DjangoItem y los asignamos al modelo de Django en la variable django_model:

import scrapy
from scrapy_djangoitem import DjangoItem
from example-app.models import Xxxx, Yyyy

class XxxxItem(DjangoItem):
    django_model = Xxxx

class YyyyItem(DjangoItem):
    django_model = Yyyy

Tras esto, los DjangoItems están listos para ser usados en el spider. También podemos acceder al modelo de Django a través del ORM de Django (borrar, crear, consultas…). django-project/scrapy-project/spiders/spider.py

# Scrapy Items imports
from scrapy-project.items import XxxxItem, YyyyItem
# Django model imports
from example-app.models import Xxxx, Yyyy

Generalmente se usará un Item Pipeline para limpiar, eliminar dublicados y almacener un item en la base de datos (aunque también es posible realizarlo dentro del spider, dependiendo de las necesidades) django-project/scrapy-project/spiders/pipelines.py:

from scrapy-project.items import XxxxItem, YyyyItem
from example-app.models import  Xxxx, Yyyy

class XxxxPipeline(object):
    def process_item(self, item, spider):
        # the cleaning magic starts!
        ....
        # finish!
        item.save()
        return item
...

También, es posible interactuar con los objetos DjangoItem de Scrapy o con los objetos Django con los imports que se muestran arriba..

Por último, es necesrio habilitar los pipelines en el fichero de configuración de Scrapy django-project/scrapy-project/settings.py

# Configure item pipelines
#ITEM_PIPELINES = {
    'scrapy_project.pipelines.XxxxPipeline': 200,
    ...
#}

HAPPY SCRAPING!

Intentaré realizar más entradas en el blog para explorar los siguientes puntos:

Normalmente se usa la linea de comandos para empezar un crawler. Pero si quieres realizar un scrapeo recurrente, probablemente será necesario hacer lo siguiente: