Scrapy非常基本的例子

问题描述 投票:19回答:2

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

他们试图运行命令:

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

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

python web-scraping scrapy
2个回答
24
投票

你可能有更好的运气首先通过the tutorial,而不是“一瞥Scrapy”网页。

该教程暗示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

52
投票

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

首先,建立一个普通的Scrapy项目,包括单独的.cfgsettings.pypipelines.pyitems.pyspiders包等,这是一种保持和处理网络抓取逻辑的推荐方法。它提供了模块化,关注点分离,使事物井井有条,清晰可测。

如果您按照official Scrapy tutorial创建项目,则通过特殊的scrapy命令行工具运行web-scraping:

scrapy crawl myspider

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

应该提到几个关键概念:

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

反应堆是Twisted中事件循环的核心 - 循环使用Twisted驱动应用程序。事件循环是一种编程构造,它等待和分派程序中的事件或消息。它通过调用一些内部或外部“事件提供程序”来工作,它通常会阻塞直到事件到达,然后调用相关的事件处理程序(“调度事件”)。该反应器为许多服务提供基本接口,包括网络通信,线程和事件分派。

以下是从脚本运行Scrapy的基本简化过程:

  • 创建一个Settings实例(或使用get_project_settings()来使用现有设置): settings = Settings() # or settings = get_project_settings()
  • 通过传入的Crawler实例实例化settingscrawler = Crawler(settings)
  • 实例化一只蜘蛛(这就是它最终的意义,对吧?): spider = MySpider()
  • 配置信号。如果你想要一个后处理逻辑,collect stats,或者至少要完成爬行,这是一个重要的步骤,因为需要手动停止扭曲的reactor。 Scrapy文档建议在reactor处理程序中停止spider_closed signal

请注意,在蜘蛛完成后您还必须自己关闭Twisted reactor。这可以通过将处理程序连接到signals.spider_closed信号来实现。

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()
  • 可选择启动logginglog.start()
  • 启动反应堆 - 这将阻止脚本执行: reactor.run()

这是一个使用DmozSpider spider的示例自包含脚本,涉及item loadersinput and output processorsitem 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(随意改进):


笔记:

如果通过实例化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()

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

© www.soinside.com 2019 - 2024. All rights reserved.