从脚本运行scrapy,不包括管道

Posted

技术标签:

【中文标题】从脚本运行scrapy,不包括管道【英文标题】:Running scrapy from script not including pipeline 【发布时间】:2014-09-29 23:54:46 【问题描述】:

我正在从脚本运行scrapy,但它所做的只是激活蜘蛛。它不会通过我的项目管道。我读过http://scrapy.readthedocs.org/en/latest/topics/practices.html,但它没有说明包括管道。

我的设置:

Scraper/
    scrapy.cfg
    ScrapyScript.py
    Scraper/
        __init__.py
        items.py
        pipelines.py
        settings.py
        spiders/
            __init__.py
            my_spider.py

我的脚本:

from twisted.internet import reactor
from scrapy.crawler import Crawler
from scrapy.settings import Settings
from scrapy import log, signals
from Scraper.spiders.my_spider import MySpiderSpider

spider = MySpiderSpider(domain='myDomain.com')
settings = get_project_settings
crawler = Crawler(Settings())
crawler.signals.connect(reactor.stop, signal=signals.spider_closed)
crawler.configure()
crawler.crawl(spider)
crawler.start()
log.start()
log.msg('Reactor activated...')
reactor.run()
log.msg('Reactor stopped.')

我的管道:

from scrapy.exceptions import DropItem
from scrapy import log
import sqlite3


class ImageCheckPipeline(object):

    def process_item(self, item, spider):
        if item['image']:
            log.msg("Item added successfully.")
            return item
        else:
            del item
            raise DropItem("Non-image thumbnail found: ")


class StoreImage(object):

    def __init__(self):
        self.db = sqlite3.connect('images')
        self.cursor = self.db.cursor()
        try:
            self.cursor.execute('''
                CREATE TABLE IMAGES(IMAGE BLOB, TITLE TEXT, URL TEXT)
            ''')
            self.db.commit()
        except sqlite3.OperationalError:
            self.cursor.execute('''
                DELETE FROM IMAGES
            ''')
            self.db.commit()

    def process_item(self, item, spider):
        title = item['title'][0]
        image = item['image'][0]
        url = item['url'][0]
        self.cursor.execute('''
            INSERT INTO IMAGES VALUES (?, ?, ?)
        ''', (image, title, url))
        self.db.commit()

脚本的输出:

[name@localhost Scraper]$ python ScrapyScript.py
2014-08-06 17:55:22-0400 [scrapy] INFO: Reactor activated...
2014-08-06 17:55:22-0400 [my_spider] INFO: Closing spider (finished)
2014-08-06 17:55:22-0400 [my_spider] INFO: Dumping Scrapy stats:
    'downloader/request_bytes': 213,
     'downloader/request_count': 1,
     'downloader/request_method_count/GET': 1,
     'downloader/response_bytes': 18852,
     'downloader/response_count': 1,
     'downloader/response_status_count/200': 1,
     'finish_reason': 'finished',
     'finish_time': datetime.datetime(2014, 8, 6, 21, 55, 22, 518492),
     'item_scraped_count': 51,
     'response_received_count': 1,
     'scheduler/dequeued': 1,
     'scheduler/dequeued/memory': 1,
     'scheduler/enqueued': 1,
     'scheduler/enqueued/memory': 1,
     'start_time': datetime.datetime(2014, 8, 6, 21, 55, 22, 363898)
2014-08-06 17:55:22-0400 [my_spider] INFO: Spider closed (finished)
2014-08-06 17:55:22-0400 [scrapy] INFO: Reactor stopped.
[name@localhost Scraper]$ 

【问题讨论】:

是否有 DEBUG 消息?它将具有以下格式:<time_stamp> [<crawler_name>] DEBUG: <error_msg>。如果有,请发布。 似乎没有 DEBUG 消息。在那里发布的输出就是我所拥有的。 在你的蜘蛛中你调用了正确的管道方法。根据上面的代码,我希望看到item = StoreImage(),以便它可以调用process_item 方法,如文档中所述。 否,但设置中提到了我的项目管道。在脚本中我有settings = get_project_settings,所以管道也应该在scrapy脚本中提及。 在我的蜘蛛中,我有一行:item = ItemCheckPipeline() 【参考方案1】:

您需要实际调用 get_project_settings,您在发布的代码中传递给爬虫的 Settings 对象将为您提供默认值,而不是您的特定项目设置。你需要这样写:

from scrapy.utils.project import get_project_settings
settings = get_project_settings()
crawler = Crawler(settings)

【讨论】:

【参考方案2】:

@Pawel 和the docs' 的解决方案对我不起作用,在查看Scrapy's source code 之后,我意识到在某些情况下它无法正确识别设置模块。我想知道为什么管道没有被使用,直到我意识到从一开始就没有从脚本中找到它们。

正如文档和 Pawel 所说,我使用的是:

from scrapy.utils.project import get_project_settings
settings = get_project_settings()
crawler = Crawler(settings)

但是,调用时:

print "these are the pipelines:"
print crawler.settings.__dict__['attributes']['ITEM_PIPELINES']

我明白了:

these are the pipelines:
<SettingsAttribute value= priority=0>

settings 未正确填充。

我意识到需要的是项目设置模块的路径,相对于包含调用 Scrapy 的脚本的模块,例如scrapy.myproject.settings。然后,我创建了Settings() 对象,如下所示:

from scrapy.settings import Settings

settings = Settings()
os.environ['SCRAPY_SETTINGS_MODULE'] = 'scraper.edx_bot.settings'
settings_module_path = os.environ['SCRAPY_SETTINGS_MODULE']
settings.setmodule(settings_module_path, priority='project')

我使用的有效导入管道的完整代码是:

from twisted.internet import reactor
from scrapy.crawler import Crawler
from scrapy import log, signals
from scrapy.settings import Settings
from scrapy.utils.project import get_project_settings
from scrapy.myproject.spiders.first_spider import FirstSpider

spider = FirstSpider()

settings = Settings()
os.environ['SCRAPY_SETTINGS_MODULE'] = 'scrapy.myproject.settings'
settings_module_path = os.environ['SCRAPY_SETTINGS_MODULE']
settings.setmodule(settings_module_path, priority='project')
crawler = Crawler(settings)

crawler.signals.connect(reactor.stop, signal=signals.spider_closed)
crawler.configure()
crawler.crawl(spider)
crawler.start()
log.start(loglevel=log.INFO)
reactor.run()

【讨论】:

虽然接受的答案是正确的,但我认为你的更好。感谢您的提示,并帮助我解决了在项目中导入设置时遇到的相同问题! @aralar 没有像您描述的那样工作,您的解决方案使我免于浪费更多时间。非常感谢这么好的答案。 所以get_project_settings从未使用过?

以上是关于从脚本运行scrapy,不包括管道的主要内容,如果未能解决你的问题,请参考以下文章

scrapy流程大致分析

Scrapy:从python脚本运行一个蜘蛛并等待它直到执行结束

如何检测我的 shell 脚本是不是通过管道运行?

Scrapy 使用 crawlerprocess 运行时抛出错误

从 Jenkins 管道运行脚本时,如何通过 ssh 在远程 AIX 机器中加载环境变量?

持久的子进程管道 - 没有读取标准输出