Web Service¶
Scrapy提供用于监控及控制运行中的爬虫的web服务(service)。 服务通过 JSON-RPC 2.0 协议提供大部分的资源,不过也有些(只读)资源仅仅输出JSON数据。
Scrapy为管理Scrapy进程提供了一个可扩展的web服务。 您可以通过 WEBSERVICE_ENABLED 来启用服务。 服务将会监听 WEBSERVICE_PORT 的端口,并将记录写入到 WEBSERVICE_LOGFILE 指定的文件中。
web服务是默认启用的 内置Scrapy扩展 , 不过如果您运行的环境内存紧张的话,也可以关闭该扩展。
Web Service资源(resources)¶
web service提供多种资源,定义在 WEBSERVICE_RESOURCES 设置中。 每个资源提供了不同的功能。参考 可用JSON-RPC对象 来查看默认可用的资源。
虽然您可以使用任何协议来实现您的资源,但有两种资源是和Scrapy绑定的:
- Simple JSON resources - 只读,输出JSON数据
- JSON-RPC resources - 通过使用 JSON-RPC 2.0 协议支持对一些Scrapy对象的直接访问
可用JSON-RPC对象¶
Scrapy默认支持以下JSON-RPC资源:
Crawler JSON-RPC资源¶
- class scrapy.contrib.webservice.crawler.CrawlerResource¶
提供对主Crawler对象的访问,来控制Scrapy进程。
默认访问地址: http://localhost:6080/crawler
状态收集器(Stats Collector)JSON-RPC资源¶
- class scrapy.contrib.webservice.stats.StatsResource¶
提供对crawler使用的状态收集器(Stats Collector)的访问。
默认访问地址: http://localhost:6080/stats
爬虫管理器(Spider Manager)JSON-RPC资源¶
您可以通过 Crawler JSON-RPC资源 来访问 爬虫管理器JSON-RPC资源。地址为: http://localhost:6080/crawler/spiders
扩展管理器(Extension Manager)JSON-RPC资源¶
您可以通过 Crawler JSON-RPC资源 来访问 扩展管理器JSON-RPC资源。地址为:
Web服务设置¶
您可以通过下列选项来设置web服务:
WEBSERVICE_RESOURCES¶
Default: {}
您的项目所启用的web服务资源的列表(list)。请参考 Web Service资源(resources) 。该列表将会添加/覆盖 WEBSERVICE_RESOURCES_BASE 中定义的Scrpay默认启用的资源的值。
WEBSERVICE_RESOURCES_BASE¶
Default:
{
'scrapy.contrib.webservice.crawler.CrawlerResource': 1,
'scrapy.contrib.webservice.enginestatus.EngineStatusResource': 1,
'scrapy.contrib.webservice.stats.StatsResource': 1,
}
Scrapy默认提供的web服务资源的列表。 您不应该对您的项目修改这个设置,而是修改 WEBSERVICE_RESOURCES 。 如果您想要关闭某些资源,您可以在 WEBSERVICE_RESOURCES 设置其的值为 None 。
编写web服务资源(resource)¶
web服务资源的实现采用了Twisted Web API。 Twisted web及Twisted web资源的更多详情请参考 Twisted Web guide 。
编写web服务资源您需要继承 JsonResource 或 JsonRpcResource 并实现 renderGET 方法。
- class scrapy.webservice.JsonResource¶
twisted.web.resource.Resource 的子类,实现了一个JSON web服务资源。参考
- ws_name¶
Scrapy web服务的名字,同时也是该资源监听的路径。举个例子, 假设Scrapy web服务监听 http://localhost:6080/ ,ws_name 是 'resource1' ,则该资源的URL为:
- class scrapy.webservice.JsonRpcResource(crawler, target=None)¶
JsonResource 的子类,实现了JSON-RPC资源。 JSON-RPC资源为Python(Scrapy)对象做了一层JSON-RPC API封装。 被封装的资源必须通过 get_target() 方法返回。该方法默认返回构造器传入的目标(target)。
- get_target()¶
返回JSON-RPC所封装的对象。默认情况下,返回构造器传入的对象。
web服务资源例子¶
StatsResource (JSON-RPC resource)¶
from scrapy.webservice import JsonRpcResource
class StatsResource(JsonRpcResource):
ws_name = 'stats'
def __init__(self, crawler):
JsonRpcResource.__init__(self, crawler, crawler.stats)
EngineStatusResource (JSON resource)¶
from scrapy.webservice import JsonResource
from scrapy.utils.engine import get_engine_status
class EngineStatusResource(JsonResource):
ws_name = 'enginestatus'
def __init__(self, crawler, spider_name=None):
JsonResource.__init__(self, crawler)
self._spider_name = spider_name
self.isLeaf = spider_name is not None
def render_GET(self, txrequest):
status = get_engine_status(self.crawler.engine)
if self._spider_name is None:
return status
for sp, st in status['spiders'].items():
if sp.name == self._spider_name:
return st
def getChild(self, name, txrequest):
return EngineStatusResource(name, self.crawler)
Example of web service client¶
scrapy-ws.py script¶
#!/usr/bin/env python
"""
Example script to control a Scrapy server using its JSON-RPC web service.
It only provides a reduced functionality as its main purpose is to illustrate
how to write a web service client. Feel free to improve or write you own.
Also, keep in mind that the JSON-RPC API is not stable. The recommended way for
controlling a Scrapy server is through the execution queue (see the "queue"
command).
"""
from __future__ import print_function
import sys, optparse, urllib, json
from urlparse import urljoin
from scrapy.utils.jsonrpc import jsonrpc_client_call, JsonRpcError
def get_commands():
return {
'help': cmd_help,
'stop': cmd_stop,
'list-available': cmd_list_available,
'list-running': cmd_list_running,
'list-resources': cmd_list_resources,
'get-global-stats': cmd_get_global_stats,
'get-spider-stats': cmd_get_spider_stats,
}
def cmd_help(args, opts):
"""help - list available commands"""
print("Available commands:")
for _, func in sorted(get_commands().items()):
print(" ", func.__doc__)
def cmd_stop(args, opts):
"""stop <spider> - stop a running spider"""
jsonrpc_call(opts, 'crawler/engine', 'close_spider', args[0])
def cmd_list_running(args, opts):
"""list-running - list running spiders"""
for x in json_get(opts, 'crawler/engine/open_spiders'):
print(x)
def cmd_list_available(args, opts):
"""list-available - list name of available spiders"""
for x in jsonrpc_call(opts, 'crawler/spiders', 'list'):
print(x)
def cmd_list_resources(args, opts):
"""list-resources - list available web service resources"""
for x in json_get(opts, '')['resources']:
print(x)
def cmd_get_spider_stats(args, opts):
"""get-spider-stats <spider> - get stats of a running spider"""
stats = jsonrpc_call(opts, 'stats', 'get_stats', args[0])
for name, value in stats.items():
print("%-40s %s" % (name, value))
def cmd_get_global_stats(args, opts):
"""get-global-stats - get global stats"""
stats = jsonrpc_call(opts, 'stats', 'get_stats')
for name, value in stats.items():
print("%-40s %s" % (name, value))
def get_wsurl(opts, path):
return urljoin("http://%s:%s/"% (opts.host, opts.port), path)
def jsonrpc_call(opts, path, method, *args, **kwargs):
url = get_wsurl(opts, path)
return jsonrpc_client_call(url, method, *args, **kwargs)
def json_get(opts, path):
url = get_wsurl(opts, path)
return json.loads(urllib.urlopen(url).read())
def parse_opts():
usage = "%prog [options] <command> [arg] ..."
description = "Scrapy web service control script. Use '%prog help' " \
"to see the list of available commands."
op = optparse.OptionParser(usage=usage, description=description)
op.add_option("-H", dest="host", default="localhost", \
help="Scrapy host to connect to")
op.add_option("-P", dest="port", type="int", default=6080, \
help="Scrapy port to connect to")
opts, args = op.parse_args()
if not args:
op.print_help()
sys.exit(2)
cmdname, cmdargs, opts = args[0], args[1:], opts
commands = get_commands()
if cmdname not in commands:
sys.stderr.write("Unknown command: %s\n\n" % cmdname)
cmd_help(None, None)
sys.exit(1)
return commands[cmdname], cmdargs, opts
def main():
cmd, args, opts = parse_opts()
try:
cmd(args, opts)
except IndexError:
print(cmd.__doc__)
except JsonRpcError as e:
print(str(e))
if e.data:
print("Server Traceback below:")
print(e.data)
if __name__ == '__main__':
main()