运行Scrapy的Django自定义管理命令:如何包含Scrapy的选项?

pem*_*ahl 11 python django scrapy

我希望能够从Django中运行Scrapy web爬行框架.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:])
Run Code Online (Sandbox Code Playgroud)

而不是调用例如scrapy crawl domain.com我现在可以python manage.py scrapy crawl domain.com在Django项目中做.但是,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
Run Code Online (Sandbox Code Playgroud)

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

不幸的是,Django 对这部分文档并不是很广泛.我还阅读了Python的optparse模块的文档,但之后对我来说并不清楚.谁能在这方面帮助我?非常感谢提前!

pem*_*ahl 5

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

也就是说,而不是写作

python manage.py scrapy crawl domain.com -o scraped_data.json -t json
Run Code Online (Sandbox Code Playgroud)

我在这些选项之间放置了空格

python manage.py scrapy crawl domain.com - o scraped_data.json - t json
Run Code Online (Sandbox Code Playgroud)

我的句柄函数如下所示:

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)
Run Code Online (Sandbox Code Playgroud)

同时,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:])
Run Code Online (Sandbox Code Playgroud)