我对Python和Django非常陌生.我目前正在探索使用Scrapy来抓取站点并将数据保存到Django数据库.我的目标是根据用户指定的域运行蜘蛛.

我已经编写了一个爬行器,它可以提取我需要的数据,并在调用时将其正确地存储在json文件中.

scrapy crawl spider -o items.json -t json

正如scrapy tutorial中所描述的那样.

我现在的目标是让spider成功地将数据保存到Django数据库,然后根据用户输入让spider运行.

我知道有很多关于这个话题的帖子,比如: link 1link 2 link 3

但是,我花了8个多小时试图让它工作,我想我不是唯一一个仍然面临这个问题的人.因此,我将try 收集我在这篇文章中获得的所有知识,并希望在以后发布一个有效的解决方案.因此,这篇文章相当长.

在我看来,将数据从Scrapy保存到Django数据库有两种不同的解决方案.一种是使用DjangoItem,另一种是直接导入模型(如here所做).

我并不完全了解这两种方法的优缺点,但似乎不同之处仅仅在于使用DjangoItem更方便、更短.

What i've done:

我补充说:

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/')

Error i'm getting is:

ImportError: No module named settings

我在想我用错误的方式定义了Django项目的路径?

我还try 了以下几种方法:

setup_django_env('../../') 

如何正确定义Django项目的路径?(如果这就是问题所在)

推荐答案

我认为主要的误解是软件包路径与设置模块路径.为了从外部脚本使用Django的模型,您需要设置DJANGO_SETTINGS_MODULE.那么,这个模块必须是importable(即,如果设置路径是myproject.settings,那么语句from myproject import settings应该可以在python shell中工作).

由于django中的大多数项目都是在默认PYTHONPATH之外的路径中创建的,因此必须将项目的路径添加到PYTHONPATH环境变量中.

下面是一个逐步的指南,可以创建一个完整的(且最小的)Django模型集成到一个Scrapy项目中:

Note:本说明自上次编辑之日起生效.如果对您不起作用,请添加 comments ,并描述您的问题和scrapy/django版本.

  1. 这些项目将在/home/rolando/projects目录内创建.

  2. django project开始.

    $ cd ~/projects
    $ django-admin startproject myweb
    $ cd myweb
    $ ./manage.py startapp myapp
    
  3. myapp/models.py中创建一个模型.

    from django.db import models
    
    
    class Person(models.Model):
        name = models.CharField(max_length=32)
    
  4. myweb/settings.py中将myapp加到INSTALLED_APPS.

    # at the end of settings.py
    INSTALLED_APPS += ('myapp',)
    
  5. 将我的数据库设置设为myweb/settings.py.

    # at the end of settings.py
    DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite3'
    DATABASES['default']['NAME'] = '/tmp/myweb.db'
    
  6. 创建数据库.

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

    $ cd ~/projects
    $ scrapy startproject mybot
    $ cd mybot
    
  8. mybot/items.py中创建一个项目.

Note:在较新版本的Scrapy中,您需要安装scrapy_djangoitem并使用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

最终的目录 struct 如下:

/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

从这里开始,我们基本上完成了在一个粗糙的项目中使用django模型所需的代码.我们可以立即使用scrapy shell命令进行测试,但要注意所需的环境变量:

$ 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>

因此,它正在按预期工作.

最后,您可能不想在每次运行bot时都设置环境变量.有许多替代方案可以解决这个问题,尽管最好的方法是将项目的包实际安装在设置为PYTHONPATH的路径中.

这是最简单的解决方案之一:将以下行添加到您的mybot/settings.py文件中以设置环境变量.

# 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()

Note:破解路径的一种更好的方法是在两个项目中都有基于setuptoolssetup.py个文件,并运行python setup.py develop,这将把您的项目路径链接到python的路径(我假设您使用virtualenv).

我吃饱了.为了完整起见,下面是一个完全正常工作的项目的基本爬行器和管道:

  1. 创建蜘蛛.

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

    蜘蛛代码:

    # 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. mybot/pipelines.py中创建管道以保存项目.

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

    在这里,如果使用DjangoItem类,可以使用item.save(),也可以直接导入django模型并手动创建对象.在这两种方式中,主要的问题是定义环境变量,以便可以使用django模型.

  3. 将管道设置添加到mybot/settings.py文件.

    ITEM_PIPELINES = {
        'mybot.pipelines.MybotPipeline': 1000,
    }
    
  4. 跑开蜘蛛.

    $ scrapy crawl example
    

Django相关问答推荐

Django Signals:从实例访问ManyToManyRel值

Django显示交叉表格

使用自定义模型注册后,Django无法登录

在 Trunc 的 kind 属性中使用字段

无法使用 django-filters 进行过滤

如何在视图中的 Django 重定向末尾附加字符串?

如何在 createsuperuser 中实例化表

使用 Python/Django 上传大文件

Django 模型命名约定

Django 相当于 COUNT 和 GROUP BY

InvalidBasesError:无法解析 [] 的基础

Python / Django 中的 Unicode 与 UTF-8 混淆?

Django 从字段开始

Django error:不能分配必须是实例

使用 Django 1.5 实现多种用户类型

Django 和 VirtualEnv 开发/部署最佳实践

Django manage.py:在其依赖之前应用迁移

如何使 Django QuerySet 批量删除()更高效

如何在字段集中显示 Django 管理内联模型?

Django REST 框架中的每个字段权限