一位用户在使用一个 Python 脚本来广播 Twitch TV 频道上线状态时遇到问题。该脚本在 Twitch TV 频道下线时工作正常,但在频道上线时却会抛出如下错误:
2013-12-08 22:42:12+0000 [-] exceptions.ValueError: No JSON object could be decoded
2、解决方案
经过分析,问题的原因是脚本尝试解析一个无效的 JSON 响应。为了解决这个问题,需要在调用 json() 方法之前检查响应的内容是否有效。
具体地,可以在脚本中添加以下代码来打印响应的内容:
response = requests.get("http://api.justin.tv/api/stream/list.json?channel=" + channel)
print(response.text)
这样,就可以看到响应的内容,并确定它是否是一个有效的 JSON 对象。
如果响应的内容不是一个有效的 JSON 对象,则需要进一步检查请求的 URL 和其他参数,以确保它们是正确的。
另外,还可以尝试使用其他 JSON 解析库,例如 simplejson 或 ujson,看看是否能解决问题。
代码例子
以下是在脚本中添加了打印响应内容的代码后的完整代码:
import requests
import yaml
from HTMLParser import HTMLParser
from sys import stdout
from twisted.internet import reactor, task, protocol
from twisted.python import log
from twisted.words.protocols import irc
from twisted.application import internet, service
with open('config.yml') as f:
config = yaml.load(f.read())
HOST, PORT = config['host'], config['port']
def munge(inp):
# Prevents highlight notification in most clients
return inp[0] + u"\u200b" + inp[1:]
class TwitchProtocol(irc.IRCClient):
password = config["password"] if "password" in config else None
nickname = 'Twitch'
username = 'Twitch'
versionName = 'Twitch'
versionNum = 'v1.0'
realname = 'by blha303. https://gist.github.com/blha303'
loopcall = None
status = False
def signedOn(self):
for channel in self.factory.channels:
self.join(channel)
#Quakenet
self._send_message("auth %s %s" % (self.nickname, config["nspass"]), "Q")
#Nickserv
self._send_message("identify %s %s" % (self.nickname, config["nspass"]), "NickServ")
#Nickserv that doesn't support specifying a nickname
self._send_message("identify %s" % config["nspass"], "NickServ")
def restartloop(reason):
reason.printTraceback()
print "Loop crashed: " + reason.getErrorMessage()
self.loopcall.start(5.0).addErrback(restartloop)
self.loopcall = task.LoopingCall(self.getTwitchStatus)
self.loopcall.start(5.0).addErrback(restartloop)
def getTwitchStatus(self):
channel = config["twitch"]
response = requests.get("http://api.justin.tv/api/stream/list.json?channel=" + channel)
print(response.text)
data = response.json()
if data and not self.status:
fmt = "{}: {} {} ({})"
self.status = True
title = data[0]['title']
playing = ("playing " + data[0]['meta_game']) if "meta_game" in data[0] else ""
viewers = "\x033\x02Online now!\x02\x0f " + str(data[0]["channel_count"]) + " viewer"
print viewers
viewers = viewers + "s" if not " 1 view" in viewers else viewers
print viewers
h = HTMLParser()
for ch in self.factory.channels:
self._send_message(h.unescape(fmt.format(title, munge(channel), playing, viewers)), ch)
elif not data and self.status:
self.status = False
for ch in self.factory.channels:
self._send_message("%s is now offline." % channel, ch)
def privmsg(self, user, channel, message):
nick, _, host = user.partition('!')
print "<%s> %s" % (nick, message)
def _send_message(self, msg, target, nick=None):
if nick:
msg = '%s, %s' % (nick, msg)
self.msg(target, msg)
print "<%s> %s" % (self.nickname, msg)
class TwitchFactory(protocol.ReconnectingClientFactory):
protocol = TwitchProtocol
channels = config["channels"]
if __name__ == '__main__':
reactor.connectTCP(HOST, PORT, TwitchFactory())
log.startLogging(stdout)
reactor.run()
elif __name__ == '__builtin__':
application = service.Application('Twitch')
ircService = internet.TCPClient(HOST, PORT, TwitchFactory())
ircService.setServiceParent(application)