variable template tag get_template dirs python django django-models scrapy

python - tag - templates dirs django



Acceda a los modelos Django con scrapy: definiendo el camino al proyecto Django (2)

Soy nuevo en Python y Django. Actualmente estoy explorando el uso de Scrapy para raspar sitios y guardar datos en la base de datos de Django. Mi objetivo es ejecutar una araña basada en el dominio dado por un usuario.

He escrito una araña que extrae los datos que necesito y los almacena correctamente en un archivo json al llamar

scrapy crawl spider -o items.json -t json

Como se describe en el tutorial de scrapy .

Mi objetivo ahora es lograr que la araña guarde con éxito los datos en la base de datos de Django, y luego trabajar para que la araña se ejecute en función de las entradas del usuario.

Soy consciente de que existen varias publicaciones sobre este tema, como estas: link 1 link 2 link 3

Pero después de haber gastado más de 8 horas tratando de hacer que esto funcione, supongo que no soy el único que todavía tiene problemas con esto. Por lo tanto, intentaré y reuniré todo el conocimiento que he obtenido hasta ahora en esta publicación, así como una posible publicación de una solución de trabajo en un momento posterior. Debido a esto, esta publicación es bastante larga.

Me parece que hay dos soluciones diferentes para guardar datos en la base de datos de Django desde Scrapy. Una es usar DjangoItem , otra es importar los modelos directamente (como se hace aquí ).

No estoy completamente consciente de las ventajas y desventajas de estos dos, pero parece que la diferencia es simplemente que el uso de DjangoItem es más conveniente y más corto.

Qué he hecho:

He añadido:

def setup_django_env(path): import imp, os from django.core.management import setup_environ f, filename, desc = imp.find_module(''settings'', [path]) project = imp.load_module(''settings'', f, filename, desc) setup_environ(project) setup_django_env(''/Users/Anders/DjangoTraining/wsgi/'')

El error que obtengo es:

ImportError: No module named settings

Estoy pensando que estoy definiendo el camino a mi proyecto Django de una manera incorrecta?

También intenté lo siguiente:

setup_django_env(''../../'')

¿Cómo puedo definir la ruta a mi proyecto Django correctamente? (si ese es el problema)


A pesar de que la respuesta de Rho parece muy buena, pensé que compartiría cómo obtuve el tratamiento con Django Models (también conocido como Django ORM) sin un proyecto completo de Django ya que la pregunta solo indica el uso de una "base de datos Django". Además, no uso DjangoItem.

Lo siguiente funciona con Scrapy 0.18.2 y Django 1.5.2. Mi proyecto de scrapy se llama desguace en lo siguiente.

  1. Agregue lo siguiente a su archivo scrapy settings.py

    from django.conf import settings as d_settings d_settings.configure( DATABASES={ ''default'': { ''ENGINE'': ''django.db.backends.postgresql_psycopg2'', ''NAME'': ''db_name'', ''USER'': ''db_user'', ''PASSWORD'': ''my_password'', ''HOST'': ''localhost'', ''PORT'': '''', }}, INSTALLED_APPS=( ''scrapping'', ) )

  2. Cree un archivo manage.py en la misma carpeta que su scrapy.cfg : este archivo no es necesario cuando ejecuta la araña en sí, pero es muy conveniente para configurar la base de datos. Así que, aquí vamos:

    #!/usr/bin/env python import os import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "scrapping.settings") from django.core.management import execute_from_command_line execute_from_command_line(sys.argv)

    Ese es todo el contenido de manage.py y es manage.py archivo stock manage.py que obtienes después de ejecutar django-admin startproject myweb pero la cuarta línea apunta a tu archivo de configuración de scrapy. Es cierto que usar DJANGO_SETTINGS_MODULE y settings.configure parece un poco extraño, pero funciona para los comandos de uno manage.py que necesito: $ python ./manage.py syncdb .

  3. Su models.py Your models.py se debe colocar en la carpeta de proyecto de scrapy (es decir, scrapping.models´). After creating that file you should be able to run you scrapping.models´). After creating that file you should be able to run you $ python ./manage.py syncdb`. Puede verse así:

    from django.db import models class MyModel(models.Model): title = models.CharField(max_length=255) description = models.TextField() url = models.URLField(max_length=255, unique=True)

  4. Your items.py y pipeline.py : Yo solía usar DjangoItem como se describe en la respuesta de Rho, pero me encontré con problemas al ejecutar muchos rastreos en paralelo con scrapyd y el uso de Postgresql. La excepción max_locks_per_transaction fue lanzada en algún punto rompiendo todos los rastreos en ejecución. Además, no me di cuenta de cómo deshacer correctamente un item.save() fallido item.save() en la tubería. Para resumir, terminé sin usar DjangoItem, lo que resolvió todos mis problemas. Aquí es cómo: items.py :

    from scrapy.item import Item, Field class MyItem(Item): title = Field() description = Field() url = Field()

    Tenga en cuenta que los campos deben tener el mismo nombre que en el modelo si desea descomprimirlos cómodamente en el siguiente paso. pipelines.py :

    from django.db import transaction from models import MyModel class Django_pipeline(object): def process_item(self, item, spider): with transaction.commit_on_success(): scraps = MyModel(**item) scraps.save() return item

    Como se mencionó anteriormente, si usted nombró todos los campos de sus artículos como lo hizo en su archivo models.py , puede usar el **item para descomprimir todos los campos al crear su objeto MyModel.

¡Eso es!


Creo que el error principal es la ruta del paquete frente a la ruta del módulo de configuración. Para usar los modelos de django a partir de un script externo, debe configurar el DJANGO_SETTINGS_MODULE . Entonces, este módulo tiene que ser importable (es decir, si la ruta de configuración es myproject.settings , entonces la declaración from myproject import settings debería funcionar en un shell de python).

Como la mayoría de los proyectos en django se crean en una ruta fuera de la PYTHONPATH predeterminada, debe agregar la ruta del proyecto a la variable de entorno PYTHONPATH .

Aquí hay una guía paso a paso para crear una integración de modelos Django completamente funcional (y mínima) en un proyecto de Scrapy:

Nota: Estas instrucciones funcionan en la fecha de la última edición. Si no funciona para usted, agregue un comentario y describa su problema y las versiones de scrapy / django.

  1. Los proyectos se crearán en el directorio /home/rolando/projects .

  2. Comience el proyecto django .

    $ cd ~/projects $ django-admin startproject myweb $ cd myweb $ ./manage.py startapp myapp

  3. Crea un modelo en myapp/models.py .

    from django.db import models class Person(models.Model): name = models.CharField(max_length=32)

  4. Agregue myapp a INSTALLED_APPS en myweb/settings.py .

    # at the end of settings.py INSTALLED_APPS += (''myapp'',)

  5. Establecer mi configuración de db en myweb/settings.py

    # at the end of settings.py DATABASES[''default''][''ENGINE''] = ''django.db.backends.sqlite3'' DATABASES[''default''][''NAME''] = ''/tmp/myweb.db''

  6. Crea la base de datos.

    $ ./manage.py syncdb --noinput Creating tables ... Installing custom SQL ... Installing indexes ... Installed 0 object(s) from 0 fixture(s)

  7. Crea el proyecto de scrapy .

    $ cd ~/projects $ scrapy startproject mybot $ cd mybot

  8. Crea un artículo en mybot/items.py .

Nota: en las versiones más nuevas de Scrapy, debe instalar scrapy_djangoitem y usar from scrapy_djangoitem import DjangoItem .

from scrapy.contrib.djangoitem import DjangoItem from scrapy.item import Field from myapp.models import Person class PersonItem(DjangoItem): # fields for this item are automatically created from the django model django_model = Person

La estructura de directorio final es esta:

/home/rolando/projects ├── mybot │   ├── mybot │   │   ├── __init__.py │   │   ├── items.py │   │   ├── pipelines.py │   │   ├── settings.py │   │   └── spiders │   │   └── __init__.py │   └── scrapy.cfg └── myweb ├── manage.py ├── myapp │   ├── __init__.py │   ├── models.py │   ├── tests.py │   └── views.py └── myweb ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py

A partir de aquí, básicamente hemos terminado con el código requerido para usar los modelos django en un proyecto de scrapy. Podemos probarlo de inmediato usando el comando scrapy shell pero tenga en cuenta las variables de entorno requeridas:

$ cd ~/projects/mybot $ PYTHONPATH=~/projects/myweb DJANGO_SETTINGS_MODULE=myweb.settings scrapy shell # ... scrapy banner, debug messages, python banner, etc. In [1]: from mybot.items import PersonItem In [2]: i = PersonItem(name=''rolando'') In [3]: i.save() Out[3]: <Person: Person object> In [4]: PersonItem.django_model.objects.get(name=''rolando'') Out[4]: <Person: Person object>

Por lo tanto, está funcionando según lo previsto.

Finalmente, es posible que no desee tener que establecer las variables de entorno cada vez que ejecute su bot. Hay muchas alternativas para abordar este problema, aunque lo mejor es que los paquetes de los proyectos se instalan realmente en una ruta establecida en PYTHONPATH .

Esta es una de las soluciones más simples: agregue estas líneas a su archivo mybot/settings.py para configurar las variables de entorno.

# Setting up django''s project full path. import sys sys.path.insert(0, ''/home/rolando/projects/myweb'') # Setting up django''s settings module name. # This module is located at /home/rolando/projects/myweb/myweb/settings.py. import os os.environ[''DJANGO_SETTINGS_MODULE''] = ''myweb.settings'' # Since Django 1.7, setup() call is required to populate the apps registry. import django; django.setup()

Nota: Un mejor enfoque para el pirateo de rutas es tener archivos setuptools basados ​​en setup.py en ambos proyectos y ejecutar python setup.py develop que enlazará su ruta de proyecto en la ruta del python (supongo que usa virtualenv ).

Es suficiente. Para completar, aquí hay una araña básica y una tubería para un proyecto completamente funcional:

  1. Crea la araña.

    $ cd ~/projects/mybot $ scrapy genspider -t basic example example.com

    El código araña:

    # file: mybot/spiders/example.py from scrapy.spider import BaseSpider from mybot.items import PersonItem class ExampleSpider(BaseSpider): name = "example" allowed_domains = ["example.com"] start_urls = [''http://www.example.com/''] def parse(self, response): # do stuff return PersonItem(name=''rolando'')

  2. Cree una tubería en mybot/pipelines.py para guardar el artículo.

    class MybotPipeline(object): def process_item(self, item, spider): item.save() return item

    Aquí puede usar item.save() si está usando la clase DjangoItem o importa el modelo django directamente y crea el objeto manualmente. En ambos sentidos, el problema principal es definir las variables de entorno para que pueda usar los modelos django.

  3. Agregue la configuración de la tubería a su archivo mybot/settings.py .

    ITEM_PIPELINES = { ''mybot.pipelines.MybotPipeline'': 1000, }

  4. Ejecuta la araña.

    $ scrapy crawl example