Scrapy 非常基本的例子

Posted

技术标签:

【中文标题】Scrapy 非常基本的例子【英文标题】:Scrapy Very Basic Example 【发布时间】:2013-09-21 05:18:47 【问题描述】:

嗨,我在我的 Mac 上安装了 Python Scrapy,我试图在他们的网站上关注 very first example。

他们试图运行命令:

scrapy crawl mininova.org -o scraped_data.json -t json

我不太明白这是什么意思?看起来scrapy原来是一个单独的程序。而且我认为他们没有名为 crawl 的命令。在示例中,他们有一段代码,即 MininovaSpider 类和 TorrentItem 的定义。我不知道这两个类应该去哪里,去同一个文件,这个python文件的名字是什么?

【问题讨论】:

你想做什么? 我试图在网上遵循这个例子并抓取 minonova 的项目。 今天晚上我把一些旧的scrapy脚本推送到了github,如果你想以它们为例:github.com/dreamcc/Scrapy-Spiders 签出this answer 【参考方案1】:

TL;DR:见Self-contained minimum example script to run scrapy。

首先,建议使用带有单独的.cfgsettings.pypipelines.pyitems.pyspiders 包等的普通 Scrapy 项目来保留和处理 Web 抓取逻辑。它提供了模块化、关注点分离,使事物保持有序、清晰和可测试。

如果您按照official Scrapy tutorial 创建项目,则您正在通过特殊的scrapy 命令行工具运行网络抓取:

scrapy crawl myspider

但是,Scrapy提供了一个 API 到 run crawling from a script。

有几个关键概念需要提一下:

Settings class - 基本上是一个用 default built-in values 初始化的键值对“容器” Crawler class - 主类,其作用类似于使用 Scrapy 进行网络抓取所涉及的所有不同组件的粘合剂 Twisted reactor - 因为 Scrapy 内置在 twisted 异步网络库之上 - 要启动爬虫,我们需要将它放在 Twisted Reactor 中,简单来说就是一个事件循环:

反应器是 Twisted 中事件循环的核心——该循环使用 Twisted 驱动应用程序。事件循环是一种编程结构,它等待和 在程序中调度事件或消息。它通过调用一些 内部或外部“事件提供者”,通常会阻塞,直到 事件已经到达,然后调用相关的事件处理程序 (“发送事件”)。反应堆提供基本接口 服务的数量,包括网络通信、线程和 事件调度。

这是从脚本运行 Scrapy 的一个基本且简化的过程:

创建一个Settings 实例(或使用get_project_settings() 来使用现有设置):

settings = Settings()  # or settings = get_project_settings()

用传入的settings实例实例化Crawler

crawler = Crawler(settings)

实例化一个蜘蛛(这就是最终的意义,对吧?):

spider = MySpider()

配置信号。如果您想拥有一个后处理逻辑collect stats,或者至少要完成爬网,这是一个重要的步骤,因为需要手动停止扭曲的reactor。 Scrapy 文档建议在 spider_closed signal 处理程序中停止 reactor

请注意,您还必须自己关闭 Twisted reactor 蜘蛛完成后。这可以通过连接一个 signal.spider_close 信号的处理程序。

def callback(spider, reason):
    stats = spider.crawler.stats.get_stats()
    # stats here is a dictionary of crawling stats that you usually see on the console        

    # here we need to stop the reactor
    reactor.stop()

crawler.signals.connect(callback, signal=signals.spider_closed)

使用传入的蜘蛛配置并启动爬虫实例:

crawler.configure()
crawler.crawl(spider)
crawler.start()

可选择启动logging:

log.start()

启动反应器 - 这会阻止脚本执行:

reactor.run()

这是一个使用 DmozSpider spider 并涉及 item loaders 与 input and output processors 和 item pipelines 的独立脚本示例:

import json

from scrapy.crawler import Crawler
from scrapy.contrib.loader import ItemLoader
from scrapy.contrib.loader.processor import Join, MapCompose, TakeFirst
from scrapy import log, signals, Spider, Item, Field
from scrapy.settings import Settings
from twisted.internet import reactor


# define an item class
class DmozItem(Item):
    title = Field()
    link = Field()
    desc = Field()


# define an item loader with input and output processors
class DmozItemLoader(ItemLoader):
    default_input_processor = MapCompose(unicode.strip)
    default_output_processor = TakeFirst()

    desc_out = Join()


# define a pipeline
class JsonWriterPipeline(object):
    def __init__(self):
        self.file = open('items.jl', 'wb')

    def process_item(self, item, spider):
        line = json.dumps(dict(item)) + "\n"
        self.file.write(line)
        return item


# define a spider
class DmozSpider(Spider):
    name = "dmoz"
    allowed_domains = ["dmoz.org"]
    start_urls = [
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
    ]

    def parse(self, response):
        for sel in response.xpath('//ul/li'):
            loader = DmozItemLoader(DmozItem(), selector=sel, response=response)
            loader.add_xpath('title', 'a/text()')
            loader.add_xpath('link', 'a/@href')
            loader.add_xpath('desc', 'text()')
            yield loader.load_item()


# callback fired when the spider is closed
def callback(spider, reason):
    stats = spider.crawler.stats.get_stats()  # collect/log stats?

    # stop the reactor
    reactor.stop()


# instantiate settings and provide a custom configuration
settings = Settings()
settings.set('ITEM_PIPELINES', 
    '__main__.JsonWriterPipeline': 100
)

# instantiate a crawler passing in settings
crawler = Crawler(settings)

# instantiate a spider
spider = DmozSpider()

# configure signals
crawler.signals.connect(callback, signal=signals.spider_closed)

# configure and start the crawler
crawler.configure()
crawler.crawl(spider)
crawler.start()

# start logging
log.start()

# start the reactor (blocks execution)
reactor.run()

以通常的方式运行它:

python runner.py

并在管道的帮助下观察导出到items.jl 的项目:

"desc": "", "link": "/", "title": "Top"
"link": "/Computers/", "title": "Computers"
"link": "/Computers/Programming/", "title": "Programming"
"link": "/Computers/Programming/Languages/", "title": "Languages"
"link": "/Computers/Programming/Languages/Python/", "title": "Python"
...

此处提供 Gist(请随时改进):

Self-contained minimum example script to run scrapy

注意事项:

如果您通过实例化 Settings() 对象来定义 settings - 您将获得所有默认的 Scrapy 设置。但是,例如,如果您想配置现有管道,或配置 DEPTH_LIMIT 或调整任何其他设置,则需要通过 settings.set() 在脚本中进行设置(如示例中所示):

pipelines = 
    'mypackage.pipelines.FilterPipeline': 100,
    'mypackage.pipelines.mysqlPipeline': 200

settings.set('ITEM_PIPELINES', pipelines, priority='cmdline')

或者,使用现有的 settings.py 并预先配置所有自定义设置:

from scrapy.utils.project import get_project_settings

settings = get_project_settings()

关于该主题的其他有用链接:

How to run Scrapy from within a Python script Confused about running Scrapy from within a Python script scrapy run spider from script

【讨论】:

我们可以手动调用管道以这种方式对项目进行后处理吗? 非常感谢@alecxe 的详细回答!为了使您的示例代码真正 100% 自包含并且可以很容易地用于Scrapy 学习者,您能否添加一个非常简单的蜘蛛示例? (例如爬取dmoz.org/Computers/Programming/Languages/Python/Books) @pad 添加了有关使用自定义设置(包括配置管道)的说明。谢谢,很好。 @Basj 我实际上正在考虑制作一个示例 github 项目,其中将包含一个简单的脚本来运行 Scrapy。希望这周有时间。谢谢。 哦,是的@alecxe,这会很好,甚至是要点。目标:使用python mycrawler.py 运行爬虫的最简单和最短的代码:)(自包含文件)【参考方案2】:

与“一目了然”网页相比,您可能会更幸运地先浏览the tutorial。

本教程暗示 Scrapy 实际上是一个单独的程序。

运行命令scrapy startproject tutorial 将创建一个名为tutorial 的文件夹,其中已经为您设置了几个文件。

例如,就我而言,模块/包itemspipelinessettingsspiders 已添加到根包tutorial

tutorial/
    scrapy.cfg
    tutorial/
        __init__.py
        items.py
        pipelines.py
        settings.py
        spiders/
            __init__.py
            ...

TorrentItem 类将放在 items.py 中,MininovaSpider 类将放在 spiders 文件夹中。

项目设置完成后,Scrapy 的命令行参数看起来相当简单。它们采用以下形式:

scrapy crawl <website-name> -o <output-file> -t <output-type>

或者,如果你想运行scrapy而不需要创建项目目录的开销,你可以使用runspider命令:

scrapy runspider my_spider.py

【讨论】:

以上是关于Scrapy 非常基本的例子的主要内容,如果未能解决你的问题,请参考以下文章

Scrapy框架的安装和基本用法 𙦑

转载Python爬虫框架Scrapy学习笔记

scrapy 的一个例子

爬虫日记(75):Scrapy的Settings源码分析

用一个非常简单的项目来了解Scrapy完成一遍抓取流程

用一个非常简单的项目来了解Scrapy完成一遍抓取流程