Spl*_*urk 33 python django django-models scrapy
我是Python和Django的新手.我目前正在探索使用Scrapy来抓取网站并将数据保存到Django数据库中.我的目标是根据用户提供的域运行蜘蛛.
我写了一个蜘蛛,它提取我需要的数据,并在调用时将其正确存储在json文件中
scrapy crawl spider -o items.json -t json
Run Code Online (Sandbox Code Playgroud)
我的目标是让蜘蛛成功地将数据保存到Django数据库,然后根据用户输入让蜘蛛运行.
我知道这个主题上存在各种帖子,例如: 链接1 链接2 链接3
但是我花了超过8个小时试图让它发挥作用,我假设我不是唯一仍然面临这个问题的人.我将尝试收集到目前为止我在这篇文章中获得的所有知识,以及希望稍后发布一个有效的解决方案.因此,这篇文章相当长.
在我看来,有两种不同的解决方案可以从Scrapy将数据保存到Django数据库.一种是使用DjangoItem,另一种是直接导入模型(如做在这里).
我并不完全了解这两者的优点和缺点,但似乎区别在于使用DjangoItem只是更方便和更短.
我做了什么:
我已经添加:
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/')
Run Code Online (Sandbox Code Playgroud)
我得到的错误是:
ImportError: No module named settings
Run Code Online (Sandbox Code Playgroud)
我在想我是以错误的方式定义了我的Django项目的路径?
我也尝试过以下方法:
setup_django_env('../../')
Run Code Online (Sandbox Code Playgroud)
如何正确定义Django项目的路径?(如果那是问题)
Rol*_*Max 68
我认为主要的误解是包路径与设置模块路径.要从外部脚本使用django的模型,您需要设置DJANGO_SETTINGS_MODULE
.然后,这个模块必须是可导入的(即如果设置路径是myproject.settings
,那么该语句from myproject import settings
应该在python shell中工作).
由于django中的大多数项目都是在默认路径之外的路径中创建的PYTHONPATH
,因此必须将项目的路径添加到PYTHONPATH
环境变量中.
以下是创建一个完全工作(和最小)Django模型集成到Scrapy项目的分步指南:
注意:此说明适用于上次编辑的日期.如果它不适合您,请添加评论并描述您的问题和scrapy/django版本.
项目将在/home/rolando/projects
目录中创建.
启动django项目.
$ cd ~/projects
$ django-admin startproject myweb
$ cd myweb
$ ./manage.py startapp myapp
Run Code Online (Sandbox Code Playgroud)在中创建模型myapp/models.py
.
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=32)
Run Code Online (Sandbox Code Playgroud)添加myapp
到INSTALLED_APPS
在myweb/settings.py
.
# at the end of settings.py
INSTALLED_APPS += ('myapp',)
Run Code Online (Sandbox Code Playgroud)设置我的数据库设置myweb/settings.py
.
# at the end of settings.py
DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite3'
DATABASES['default']['NAME'] = '/tmp/myweb.db'
Run Code Online (Sandbox Code Playgroud)创建数据库.
$ ./manage.py syncdb --noinput
Creating tables ...
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
Run Code Online (Sandbox Code Playgroud)创建scrapy项目.
$ cd ~/projects
$ scrapy startproject mybot
$ cd mybot
Run Code Online (Sandbox Code Playgroud)在中创建一个项目mybot/items.py
.
注意:在较新版本的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
Run Code Online (Sandbox Code Playgroud)
最终的目录结构是这样的:
/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
Run Code Online (Sandbox Code Playgroud)
从这里开始,基本上我们完成了在scrapy项目中使用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>
Run Code Online (Sandbox Code Playgroud)
因此,它按预期工作.
最后,您可能不希望每次运行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()
Run Code Online (Sandbox Code Playgroud)
注意:更好的路径入侵方法是在项目和运行中都有setuptools
基于setup.py
文件的文件,python setup.py develop
这会将你的项目路径链接到python的路径(我假设你使用virtualenv
).
足够了.为了完整性,这里是一个基本的蜘蛛和管道,用于完全工作的项目:
创造蜘蛛.
$ cd ~/projects/mybot
$ scrapy genspider -t basic example example.com
Run Code Online (Sandbox Code Playgroud)
蜘蛛代码:
# 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')
Run Code Online (Sandbox Code Playgroud)创建管道mybot/pipelines.py
以保存项目.
class MybotPipeline(object):
def process_item(self, item, spider):
item.save()
return item
Run Code Online (Sandbox Code Playgroud)
在这里,您既可以使用item.save()
,如果你使用的是DjangoItem
类或直接导入Django的模型和手动创建的对象.在两种方式中,主要问题是定义环境变量,以便您可以使用django模型.
将管道设置添加到您的mybot/settings.py
文件中.
ITEM_PIPELINES = {
'mybot.pipelines.MybotPipeline': 1000,
}
Run Code Online (Sandbox Code Playgroud)跑蜘蛛.
$ scrapy crawl example
Run Code Online (Sandbox Code Playgroud)虽然Rho的答案看起来非常好,但我想我会分享如何使用Django模型(也就是Django ORM)进行 scrapy, 而没有完整的Django项目,因为这个问题只说明了"Django数据库"的使用.我也不使用DjangoItem.
以下适用于Scrapy 0.18.2和Django 1.5.2.我的scrapy项目在下面称为报废.
将以下内容添加到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',
)
)
Run Code Online (Sandbox Code Playgroud)manage.py
在与您相同的文件夹中创建一个文件scrapy.cfg
:运行蜘蛛本身时不需要此文件,但对于设置数据库非常方便.所以我们走了:
#!/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)
Run Code Online (Sandbox Code Playgroud)
这是完整的内容,manage.py
并且几乎就是manage.py
您在运行后获得的库存文件,django-admin startproject myweb
但第4行指向您的scrapy设置文件.不可否认,使用DJANGO_SETTINGS_MODULE
并且settings.configure
看起来有点奇怪,但它适用于manage.py
我需要的一个命令:$ python ./manage.py syncdb
.
你models.py
的models.py应该放在你的scrapy项目文件夹中(即scrapping.models´).
After creating that file you should be able to run you
$ python ./manage.py syncdb`.它可能如下所示:
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)
Run Code Online (Sandbox Code Playgroud)你曾经items.py
和pipeline.py
我曾经使用DjangoItem作为Rho的回答,但是当我与scrapyd并行使用Postgresql进行多次爬行时,我遇到了麻烦.唯一的例外max_locks_per_transaction
是在某些时候打破所有正在运行的爬网抛出.此外,我没有弄清楚如何正确回滚item.save()
管道中的失败.长话短说,我最终没有使用DjangoItem解决了我所有的问题.以下是
items.py
:
from scrapy.item import Item, Field
class MyItem(Item):
title = Field()
description = Field()
url = Field()
Run Code Online (Sandbox Code Playgroud)
请注意,如果要像下一步那样方便地解压缩,则字段需要与模型中的名称相同!
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
Run Code Online (Sandbox Code Playgroud)
如上所述,如果您像在models.py
文件中一样命名了所有项目字段,则可以**item
在创建MyModel对象时用于解压缩所有字段.
而已!
归档时间: |
|
查看次数: |
9905 次 |
最近记录: |