11

我希望能够在 Django 中运行Scrapy 网络爬虫框架。Scrapy 本身只提供了一个命令行工具scrapy来执行它的命令,也就是说,该工具不是故意编写为从外部程序调用的。

用户Mikhail Korobov提出了一个不错的解决方案,即从 Django 自定义管理命令调用 Scrapy。为方便起见,我在这里重复他的解决方案:

# -*- coding: utf-8 -*-
# myapp/management/commands/scrapy.py 

from __future__ import absolute_import
from django.core.management.base import BaseCommand

class Command(BaseCommand):

    def run_from_argv(self, argv):
        self._argv = argv
        return super(Command, self).run_from_argv(argv)

    def handle(self, *args, **options):
        from scrapy.cmdline import execute
        execute(self._argv[1:])

scrapy crawl domain.com我现在可以python manage.py scrapy crawl domain.com在 Django 项目中进行,而不是调用 eg 。但是,Scrapy 命令的选项根本不被解析。如果我这样做python manage.py scrapy crawl domain.com -o scraped_data.json -t json,我只会得到以下响应:

Usage: manage.py scrapy [options] 

manage.py: error: no such option: -o

所以我的问题是,如何扩展自定义管理命令以采用 Scrapy 的命令行选项?

不幸的是,Django这部分的文档不是很丰富。我还阅读了 Python 的optparse 模块的文档,但之后对我来说并不清楚。任何人都可以在这方面帮助我吗?提前非常感谢!

4

2 回答 2

5

好的,我找到了解决问题的方法。这有点难看,但它有效。由于 Django 项目的manage.py命令不接受 Scrapy 的命令行选项,因此我将选项字符串拆分为两个由manage.py. 成功解析后,我重新加入这两个参数并将它们传递给 Scrapy。

也就是说,而不是写

python manage.py scrapy crawl domain.com -o scraped_data.json -t json

我在这样的选项之间放置空格

python manage.py scrapy crawl domain.com - o scraped_data.json - t json

我的句柄函数如下所示:

def handle(self, *args, **options):
    arguments = self._argv[1:]
    for arg in arguments:
        if arg in ('-', '--'):
            i = arguments.index(arg)
            new_arg = ''.join((arguments[i], arguments[i+1]))
            del arguments[i:i+2]
            arguments.insert(i, new_arg)

    from scrapy.cmdline import execute
    execute(arguments)

同时,Mikhail Korobov 提供了最佳解决方案。看这里:

# -*- coding: utf-8 -*- 
# myapp/management/commands/scrapy.py 

from __future__ import absolute_import
from django.core.management.base import BaseCommand

class Command(BaseCommand):

    def run_from_argv(self, argv):
        self._argv = argv
        self.execute()

    def handle(self, *args, **options):
        from scrapy.cmdline import execute
        execute(self._argv[1:])
于 2012-05-13T12:47:27.657 回答
3

我认为您真的在寻找POSIX 参数语法约定准则 10

参数 -- 应该被接受为指示选项结束的分隔符。任何以下参数都应被视为操作数,即使它们以“-”字符开头。-- 参数不应用作选项或操作数。

Python 的optparse模块以这种方式运行,即使在 Windows 下也是如此。

我将scrapy项目设置模块放在参数列表中,这样我就可以在独立的应用程序中创建单独的scrapy项目:

# <app>/management/commands/scrapy.py
from __future__ import absolute_import
import os

from django.core.management.base import BaseCommand

class Command(BaseCommand):
    def handle(self, *args, **options):
        os.environ['SCRAPY_SETTINGS_MODULE'] = args[0]
        from scrapy.cmdline import execute
        # scrapy ignores args[0], requires a mutable seq
        execute(list(args))

调用如下:

python manage.py scrapy myapp.scrapyproj.settings crawl domain.com -- -o scraped_data.json -t json

用scrapy 0.12和django 1.3.1测试

于 2012-10-23T21:19:48.670 回答