Scrapy 非常基本的示例
- 2025-03-21 09:07:00
- admin 原创
- 58
问题描述:
你好,我的 Mac 上安装了 Python Scrapy,并尝试按照他们网站上的第一个示例进行操作。
他们试图运行以下命令:
scrapy crawl mininova.org -o scraped_data.json -t json
我不太明白这是什么意思?看起来 scrapy 是一个单独的程序。我不认为他们有一个名为 crawl 的命令。在示例中,他们有一段代码,是 MininovaSpider 和 TorrentItem 类的定义。我不知道这两个类应该放在哪里,放进同一个文件,这个 python 文件的名字是什么?
解决方案 1:
TL;DR:请参阅运行 scrapy 的自包含最小示例脚本。
首先,建议使用带有单独.cfg
、settings.py
、pipelines.py
、items.py
、包等的普通 Scrapy 项目来保存和处理您的网页抓取逻辑。它提供了模块化、关注点分离,使事情井然有序、清晰易测。spiders
如果您按照官方的 Scrapy 教程创建项目,则您将通过特殊的scrapy
命令行工具运行网页抓取:
scrapy crawl myspider
但是,Scrapy
还提供了一个 API来从脚本运行爬网。
有几个关键概念需要提及:
Settings
类- 基本上是一个键值“容器”,用默认内置值初始化Crawler
class - 主类,充当使用 Scrapy 进行网页抓取所涉及的所有不同组件的粘合剂Twisted
reactor
- 因为 Scrapy 是内置于twisted
异步网络库之上的 - 要启动爬虫,我们需要将其放入Twisted Reactor中,简单来说就是一个事件循环:
反应器是 Twisted 中事件循环的核心 - 事件循环驱动使用 Twisted 的应用程序。事件循环是一种编程结构,用于在程序中等待和分派事件或消息。它通过调用一些内部或外部“事件提供程序”来工作,这些提供程序通常会阻塞直到事件到达,然后调用相关的事件处理程序(“分派事件”)。反应器为许多服务提供基本接口,包括网络通信、线程和事件分派。
以下是从脚本运行 Scrapy 的基本简化过程:
创建一个
Settings
实例(或使用get_project_settings()
现有设置):
settings = Settings() # or settings = get_project_settings()
Crawler
使用settings
传入的实例进行实例化:
crawler = Crawler(settings)
实例化一个蜘蛛(这最终就是它的全部内容,对吧?):
spider = MySpider()
配置信号。如果您想要有后处理逻辑、收集统计数据,或者至少要完成抓取,这是一个重要的步骤,因为 twisted需要手动停止。Scrapy 文档建议在信号
reactor
处理程序中停止:reactor
`spider_closed`
请注意,在 spider 完成后,您还必须自己关闭 Twisted 反应堆。这可以通过将处理程序连接到 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()
可选择开始记录:
log.start()
启动反应堆-这将阻止脚本执行:
reactor.run()
DmozSpider
这是一个使用蜘蛛的独立脚本示例,涉及带有输入和输出处理器和项目管道的项目加载器:
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)) + "
"
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"}
...
要点可在此处获得(请随意改进):
用于运行 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()
关于该主题的其他有用链接:
如何在 Python 脚本中运行 Scrapy
对在 Python 脚本中运行 Scrapy 感到困惑
scrapy 从脚本运行蜘蛛
解决方案 2:
与“一目了然的 Scrapy”网页相比,您可能更愿意先浏览教程。
本教程暗示 Scrapy 事实上是一个独立的程序。
运行该命令scrapy startproject tutorial
将创建一个名为“tutorial
已为您设置的几个文件的文件夹”。
例如,就我而言,模块/包items
、pipelines
和已添加到根包。settings
`spiders`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
扫码咨询,免费领取项目管理大礼包!