我希望能够从Django中运行Scrapy web crawling framework。 Scrapy本身仅提供命令行工具scrapy
来执行其命令,即该工具不是故意编写的,而是从外部程序调用。
用户Mikhail Korobov提出nice solution,即从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
我现在可以在Django项目中执行python manage.py scrapy crawl domain.com
。但是,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的documentation of this part并不是很广泛。我还阅读了Python optparse module的文档,但事后对我来说并不清楚。谁能在这方面帮助我?非常感谢提前!
答案 0 :(得分: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:])
答案 1 :(得分:3)
我认为你真的在寻找POSIX argument syntax conventions的准则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进行测试