acfun json 弹幕 转换 bilibili xml 弹幕
2015-07-14 17:33
841 查看
以往一直使用 acdown 自带的 acplay 功能看 acfun 的视频, 然而 acdown 已经停止更新, 并且 acfun 又一次改版。。。
因此想继续用 acplay, 只能把A站的弹幕转换为B站的格式看了。
首先, 想要转换弹幕文件, 我们首先要下载解析出A站和B站的弹幕。 关于如何获取弹幕, 参见https://tiansh.github.io/的ASS 项目。 具体来说, 就是提取cid, 然后下载弹幕。
我借鉴了该项目下载弹幕的程序。 分别是:
A站
B站:
在此向原作者致敬!
接下来, 我们下载了acun和bilibili的json和xml格式, 那么简单, 就是转换文件而已。 在此我用了 python 做 json转换。
代码本身很简单:
代码不复杂, 但是有些问题值得记录。 首先是python的编码问题, 开始用json.loads()直接读的时候老出错, 后来才发现是编码问题没有处理好。 然后还有, 读取到txt之后, 可以print, 但输出文件的时候显示“'ascii' codec can't encode character u'\u5657' in position 0: ordinal not in range(128)”
搜索后发现, 写的时候也要指定编码。
参考了一下文章: http://hjc73.blog.163.com/blog/static/1046929201364115635197/
http://python3-cookbook.readthedocs.org/zh_CN/latest/c06/p02_read-write_json_data.html
over, enjoy it!
因此想继续用 acplay, 只能把A站的弹幕转换为B站的格式看了。
首先, 想要转换弹幕文件, 我们首先要下载解析出A站和B站的弹幕。 关于如何获取弹幕, 参见https://tiansh.github.io/的ASS 项目。 具体来说, 就是提取cid, 然后下载弹幕。
我借鉴了该项目下载弹幕的程序。 分别是:
A站
// 获取弹幕id var getVid = function (callback) { var player, m, vid = null; try { player = document.querySelector('iframe#ACFlashPlayer-re'); m = player.src.match(/vid=(\d+)/); vid = Number(m[1]); } catch (e) { } if (!vid) try { player = document.querySelector('object#ACFlashPlayer-re'); m = player.querySelector('param[name="flashvars"]').getAttribute('value').match(/videoId=(\d+)/); vid = Number(m[1]); } catch (e) { } if (!vid) setTimeout(function () { getVid(callback); }, 1000); else callback(vid); }; // 通过弹幕id获取弹幕内容 // 弹幕内容是A站直接提供的数据 var getDanmaku = function (vid, callback) { GM_xmlhttpRequest({ 'method': 'GET', // FIXME 最后可能需要个弹幕上限,不过就先这样吧 'url': 'http://static.comment.acfun.mm111.net/' + vid, 'onload': function (resp) { var data; try { data = JSON.parse(resp.responseText); data = data.reduce(function (x, y) { return x.concat(y); }); } catch (e) { data = null; } if (!data || typeof data.length !== 'number') callback(vid); else callback(vid, data); }, 'onerror': function () { callback(getVid); }, }); }; // 将弹幕内容转换为程序内部的表达方式 var mina = function (vid, danmaku) { danmaku = danmaku.map(function (line) { var info = line.c.split(','), text = line.m; return { 'text': text, 'time': Number(info[0]), 'color': RRGGBB(Number(info[1])), 'mode': [undefined, 'R2L', undefined, undefined, 'BOTTOM', 'TOP'][Number(info[2])], 'size': Number(info[3]), 'bottom': false, // 'sender': String(info[4]), // 'create': new Date(Number(info[5]) * 1000), }; }); var name; try { name = document.querySelector('#txt-title-view').textContent; } catch (e) { name = '' + vid; } var ass = generateASS(setPosition(danmaku), { 'title': document.title, 'ori': location.href, }); startDownload('\ufeff' + ass, name + '.ass'); };
B站:
/* * bilibili */ // 获取xml var fetchXML = function (cid, callback) { GM_xmlhttpRequest({ 'method': 'GET', 'url': 'http://comment.bilibili.com/{{cid}}.xml'.replace('{{cid}}', cid), 'onload': function (resp) { var data = (new DOMParser()).parseFromString(resp.responseText, 'text/xml'); var danmaku = Array.apply(Array, data.querySelectorAll('d')).map(function (line) { var info = line.getAttribute('p').split(','), text = line.textContent; return { 'text': text, 'time': Number(info[0]), 'mode': [undefined, 'R2L', 'R2L', 'R2L', 'BOTTOM', 'TOP'][Number(info[1])], 'size': Number(info[2]), 'color': RRGGBB(Number(info[3])), 'bottom': Number(info[5]) > 0, // 'create': new Date(Number(info[4])), // 'pool': Number(info[5]), // 'sender': String(info[6]), // 'dmid': Number(info[7]), }; }); callback(danmaku); } }); }; // 获取当前cid var getCid = function (callback) { debug('get cid...'); var cid = null, src = null; try { src = document.querySelector('#bofqi iframe').src.replace(/^.*\?/, ''); cid = Number(src.match(/cid=(\d+)/)[1]); } catch (e) { } if (!cid) try { src = document.querySelector('#bofqi embed').getAttribute('flashvars'); cid = Number(src.match(/cid=(\d+)/)[1]); } catch (e) { } if (!cid) try { src = document.querySelector('#bofqi object param[name="flashvars"]').getAttribute('value'); cid = Number(src.match(/cid=(\d+)/)[1]); } catch (e) { } if (cid) setTimeout(callback, 0, cid); else if (src) GM_xmlhttpRequest({ 'method': 'GET', 'url': 'http://interface.bilibili.com/player?' + src, 'onload': function (resp) { try { cid = Number(resp.responseText.match(/<chatid>(\d+)<\/chatid>/)[1]); } catch (e) { } setTimeout(callback, 0, cid || undefined); }, 'onerror': function () { setTimeout(callback, 0); } }); else { setTimeout(getCid, 100, callback); } };
在此向原作者致敬!
接下来, 我们下载了acun和bilibili的json和xml格式, 那么简单, 就是转换文件而已。 在此我用了 python 做 json转换。
代码本身很简单:
import sys reload(sys) sys.setdefaultencoding('utf-8') file = open('C:\\Users\\Administrator\\Desktop\\ab\\2.json') try: content = file.read() finally: file.close() import json jcon = json.loads(content, encoding='GB2312') f2 = open('C:\\Users\\Administrator\\Desktop\\ab\\2.xml', 'w') f2.write('<?xml version="1.0" encoding="UTF-8"?>\n') f2.write('<i><chatserver>chat.bilibili.com</chatserver><chatid>3978802</chatid><mission>0</mission><maxlimit>1000</maxlimit><source>k-v</source>') jcs = jcon[0] for jc in jcs: a = jc['m'] b = jc['c'] # c: time, color, mode, size, sender, create, ? c = b.split(',') f2.write('<d p="') # time str = '%s,' % (c[0]) f2.write(str) # mode str = '%s,' % (c[2]) f2.write(str) # size str = '%s,' % (c[3]) f2.write(str) # color str = '%s,' % (c[1]) f2.write(str) # create str = '%s,' % (c[5]) f2.write(str) # pool f2.write('0,') # sender str = '%s,' % (c[4]) f2.write(str) # dmid str = '%s">' % (c[6]) f2.write(str) # text str = '%s</d>\n' % (a) f2.write(str) f2.write('</i>')
代码不复杂, 但是有些问题值得记录。 首先是python的编码问题, 开始用json.loads()直接读的时候老出错, 后来才发现是编码问题没有处理好。 然后还有, 读取到txt之后, 可以print, 但输出文件的时候显示“'ascii' codec can't encode character u'\u5657' in position 0: ordinal not in range(128)”
搜索后发现, 写的时候也要指定编码。
参考了一下文章: http://hjc73.blog.163.com/blog/static/1046929201364115635197/
http://python3-cookbook.readthedocs.org/zh_CN/latest/c06/p02_read-write_json_data.html
over, enjoy it!
相关文章推荐
- JS实现密码加密
- video.js使用教程API
- 列出对像属性,for(var i in obj)[转]
- Flex通过javascript读写cookie
- 改进 ThinkJS 的异步编程方式
- JS遮罩层——如何使被遮罩后的链接可以点击
- ExtJs grid中 datefield 列数据 提交格式问题
- Ajax方法不执行success回调函数,而执error回调函数
- 异步加载js
- JSON 数据格式
- JSON转换类
- 异步编程:When.js快速上手
- JSON日期格式化
- form.validate
- 【js】弹出文件选择框,可用与文件上传(适配所有浏览器)
- Javascript日期对象的dateAdd与dateDiff方法
- select2
- jsp的select控件,怎么用EL表达式自动选中??
- js用Date对象的setDate()函数对日期进行加减操作
- validate