Skip to content
This repository has been archived by the owner on Nov 1, 2024. It is now read-only.

关于后续数据维护方案的讨论 #39

Closed
wxt2005 opened this issue Jun 30, 2016 · 23 comments
Closed

关于后续数据维护方案的讨论 #39

wxt2005 opened this issue Jun 30, 2016 · 23 comments

Comments

@wxt2005
Copy link
Owner

wxt2005 commented Jun 30, 2016

之前的讨论见 #38

现在的几种方案:

  1. 沿用手工维护 json 的方式
  2. 自建数据库
  3. 采用类似 LeanCloud 的解决方案
@weizhenye
Copy link
Contributor

如果要把数据部分独立出来,可以讨论一下数据的定位了。
是单纯地满足 bgmlist.com 就好?还是作为一个番组信息聚合的项目?
目前不少项目都在使用该数据,是否要满足他们的需求?(企图添加 S1 专楼的我

另外,数据维护面向的群体?会 HTTP 增删查改的人吗?会 GitHub 的人吗?一般大众吗?

在我看来,GitHub 上维护 JSON 提供的是数据,而 API 服务器提供的是服务。数据是去中心化的,服务则是要有各种保障。我该如何知道哪些数据更新了?假设你写完 API 服务器开源了,其他人要自行部署该如何同步到最新数据?

我是认为维护 JSON 的方式比较好,独立为 repository 可以有。

@wxt2005
Copy link
Owner Author

wxt2005 commented Jul 2, 2016

考虑了一下,我觉得去中心化的方案确实较优。大家都可以使用这份数据来构建自己的站点,同时也可以帮助完善内容。

数据定位来说,应该可以不限于 bgmlist.com 所需要的那些,但暂时还是以放送时间、放送站点以及一些主要的 meta data 为主会比较好(你提到的 S1 专楼,可以放在相关链接之类的字段中)。当然有人愿意贡献的话,可以考虑在将来添加更多的字段。

放在 GitHub 上的话,维护者应该主要还是 GitHub 用户了。对于普通用户来说,可以采用 @CnSimonChan 所移到的通过 bot 自动生成 issue 的方式来反馈问题。

@weizhenye
Copy link
Contributor

一些设想:

  1. 发布到 npm。更新数据增加修订号,扩展字段增加次版本号,不兼容的字段改变增加主版本号。
  2. 添加测试。比如一些必填字段有没有填写、字段顺序有没有对。可能的话可以增加「覆盖率」,非必填字段的填写情况。不知道测试和覆盖率能否生成某种形式的「报告」,丢一些 error 和 warning 出来,方便修改和补充。
  3. 尝试实现自动获取站点的放送数据,然后人工审核这些数据是否正确。如果难以实现,尝试检测站点是否有该番组,人工去获取。总之需要一个减少维护工作量的方案。
  4. 命令行工具或一些数据操作 API。假设 package 名为 bgmdata,可以使用 bgmdata -s 201607 -o ./json/bangumi-201607.json 之类的命令;或者 const bgmdata = require('bgmdata'); 后,可以使用 bgmdata.raw(); 之类的 API 来获取特定数据。不过严格来讲这些功能应该算是另一个项目,应该由 bgmdata-cli 之类的包来做,bgmdata 可能应该只提供一个 JSON。

@weizhenye
Copy link
Contributor

讨论下数据格式?

title 是扁平化还是结构化?

{
  "titleCN": "偶像大师 灰姑娘女孩",
  "titleEN": "THE IDOLM@STER CINDERELLA GIRLS",
  "titleJP": "アイドルマスター シンデレラガールズ"
}
{
  "title": {
    "en-US": "THE IDOLM@STER CINDERELLA GIRLS",
    "ja": "アイドルマスター シンデレラガールズ",
    "zh-Hans": "偶像大师 灰姑娘女孩",
    "zh-Hant": "偶像大師 灰姑娘女孩"
  }
}

放送时间是否使用世界标准时间?例如 {"showDate": "2015-01-09", "timeJP": "2300"},由 Date.parse('2015-01-09 23:00:00 UTC+8') 计算得,{"showTimeJP": 1420815600000}
weekDayJP 是冗余数据,newBgm 应该也算冗余。
另外和 title 一样,扁平还是结构?showTimeCN 足够表示放送信息吗?各视频站放送时间可能不同,是否都要收录?

{
  "time": {
    // 日本电视台放送开始
    "begin": 1420815600000,
    // 日本电视台放送结束
    "end": 1428678000000,
    // 各视频站放送开始
    "acfun": 1420821000000,
    "bilibili": 1420821000000
  }
}

最后是 sites 信息:

{
  "site": {
    "offical": {
      "type": "info",
      "url": "http://imas-cinderella.com/"
    },
    "tudou": {
      "type": "onair",
      "comment": "注释",
      "url": "http://www.tudou.com/albumcover/qgdKuHlPg9g.html",
      // or 
      "id": "qgdKuHlPg9g"
    }
  }
}

我是觉得 sites 为数组更方便 filter:

{
  "sites": [
    {
      "name": "offical",
      "type": "offical",
      "url": "http://imas-cinderella.com/"
    },
    {
      "name": "tudou",
      "type": "onair",
      "comment": "注释",
      "id": "qgdKuHlPg9g"
    },
    {
      "name": "saraba1st",
      "type": "info",
      "id": "1059367"
    },
    {
      "name": "dmhy",
      "type": "resource",
      "keyword": "娘女孩"
    }
  ]
}

最终的数据:

[
  {
    "id": 101399,
    "title": {},
    "time": {},
    "sites": []
  },
  {
    "id": 110600,
    "title": {},
    "time": {},
    "sites": []
  },
  // ...
]

@wxt2005
Copy link
Owner Author

wxt2005 commented Jul 17, 2016

参考你的建议,修改了一些地方:

[
    {
        // id 建议不要和 bangumi 挂钩比较好,毕竟数据本身是不依赖它的。
        // 可以用“年份+开播月份+index”
        "id": 161002,
        // meta data 尽量还是放在最外层
        "title": "アイドルマスター シンデレラガールズ",
        "officialSite": "http://imas-cinderella.com/",
        "begin": 1420815600000,
        "end": 1428678000000,
        "comments": "注释",
        // 所有翻译的标题放在一起
        "titleTrans": {
            "en-US": [
                "THE IDOLM@STER CINDERELLA GIRLS"
            ],
            // 考虑到多个译名的情况,可以为一个数组
            "zh-Hans": [
                "偶像大师 灰姑娘女孩",
                "爱马仕 灰姑娘"
            ],
            "zh-Hant": [
                "偶像大師 灰姑娘女孩"
            ]
        },
        // 放送站点、下载站点和其它站点分开
        "watchSites": {
            "tudou": {
                // url 建议还是用实际链接,有些站都换过几次链接格式了,id 不一定通用。
                // 可能增加一些维护成本
                "url": "http://www.tudou.com/albumcover/qgdKuHlPg9g.html",
                // 是否官方放送,例如 C 站就不能算
                "official": true,
                // 是否只有会员才能看
                "premuiumOnly": true,
                "begin": 1420821000000,
                // 是否为和谐版
                "censored": true,
                // 预留以后可能引入英文放送站的可能性
                "lang": "zh",
                "comments": "注释"
            }
        },
        "downloadSites": {
            "dmhy": {
                "keyword": "娘女孩"
            }
        },
        "otherSites": {
            "saraba1st": {
                "id": "1059367"
            },
            "bangumi": {
                "id": "68812"
            }
        }
    }
]

@weizhenye
Copy link
Contributor

id 用「年份+开播月份+index」可以,但这样的话最好是字符串,比如 "1610-1" 之类的,万一哪天业界起死回生了一季度上百部番(

标题、官网、放送时间这些 meta 可能确实是放在外层比较好,放在里面感觉变「特例」了。

标题翻译为数组的话,应该要保证流传最广的那个翻译作为第 0 个元素。

对于站点,各种类型分开目前看是可以,但其他类型直接一个 otherSites 感觉不太好。如果以后收录的站点多起来了全塞里面吗?如果为某个类型的站点新增一个字段以何为根据呢?watchSites 和 downloadSites 独立为字段只是因为 bgmlist.com 要用到吧。

我觉得,数据部分独立为一个项目后,应当与业务逻辑无关,要考虑的是数据结构怎样才能方便人工维护、方便程序读取。你的结构限定了先查询站点类型,再查询站点名称。仅仅作为例子,假设所有站点都可能有 comments 字段,而我要获取含有 comments 字段的那些站点,那我要先把所有类型的站点合并到一个数组里,然后再去 filter,这样就比较麻烦了。我更倾向于数组也是这个理由,把 "tudou" 作为 key 是因为绝大多数情况下我们都以站点名作为查询条件,但总会有其他情况。

@wxt2005
Copy link
Owner Author

wxt2005 commented Jul 24, 2016

站点链接用数组存储我没有什么意见。但是对于所有站点都混杂地放在一起,用 type 值来区分这点,我觉得在维护的时候会造成一些麻烦。各种类型的链接穿插在一起,肉眼分辨起来是很困难的。毕竟现在维护的时候,大部分情况下还是要靠人工的。

@yume-chan
Copy link
Contributor

标题的问题,现在提出的方案需要默认名称是日文,如果以后需要收录国产或欧美动画呢?可以改成和 translation 一样的模式

站点,我也赞同全部放在一起,用 type 区分的方式。

@weizhenye
Copy link
Contributor

在上面我有提到,测试部分可以检验字段顺序。或者我们直接写个 format.js,自动修正为规定的格式和顺序,要求提交 commit 前必须 npm run format 一下。这样,如果是添加新站点,直接填进去,npm run format 后就不用管了;如果是修改已有站点,就根据规定好的顺序去找,这个操作复杂度和分成多个字段是一样的。

或许 titleTrans 里应该加上 ja 字段?不懂 translation 是什么模式。

另外放送时间,我想了想还是应该使用 ISO 8601 格式,new Date('2015-01-09 23:00:00 UTC+8').toISOString() -> 2015-01-09T15:00:00.000Z,毕竟是人工维护的,可读性强一点比较好。

@wxt2005
Copy link
Owner Author

wxt2005 commented Jul 30, 2016

meta data 里的 title 就确定为作品的原名,如果是国产作品就为中文。这种情况下,如果有日文译名,则在 titleTrans 里增加 jp 字段好了。

那么现在决定的格式大致上是这样:

[
    {
        "id": "1607-1",
        "title": "アイドルマスター シンデレラガールズ",
        "officialSite": "http://imas-cinderella.com/",
        "begin": "2015-01-09T15:00:00.000Z",
        "end": "2015-01-09T15:00:00.000Z",
        "comments": "注释",
        "titleTrans": {
            "en-US": [
                "THE IDOLM@STER CINDERELLA GIRLS"
            ],
            "zh-Hans": [
                "偶像大师 灰姑娘女孩",
                "爱马仕 灰姑娘"
            ],
            "zh-Hant": [
                "偶像大師 灰姑娘女孩"
            ]
        },
        "sites": [
            {
                "type": "onair",
                "name": "tudou",
                "url": "http://www.tudou.com/albumcover/qgdKuHlPg9g.html",
                "official": true,
                "premuiumOnly": true,
                "begin": 1420821000000,
                "censored": true,
                "lang": "zh",
                "comments": "注释"
            },   
            {
                "type": "onair",
                "name": "bilibili",
                "url": "http://bangumi.bilibili.com/anime/5057/",
                "official": true,
                "premuiumOnly": false,
                "begin": 1420821000000,
                "censored": false,
                "lang": "zh",
                "comments": ""
            }, 
            {
                "type": "resource",
                "name": "dmhy",
                "keyword": "娘女孩"
            }
            {
                "type": "info",
                "name": "saraba1st",
                "id": "1059367"
            },
            {
                "type": "info",
                "name": "bangumi",
                "id": "12345"
            }
        ]
    }
]

@yume-chan
Copy link
Contributor

如果我想显示所有项目的中文名,该如何区分 1) 项目本来就是中文所以翻译列表里没有中文 和 2) 项目名暂时还没有中文翻译所以翻译列表里没有中文 ?

JSON 的 key 一般用全小写 + 下划线分割单词

sites 里的主要字段统一命名为 value,怎么理解是之后的事

@weizhenye
Copy link
Contributor

或许顶层得再加个 lang 字段指明作品语言,但感觉这样怪怪的。

JSON 的 key 我看到的是驼峰式的比较多,JS 在取值时出现下划线还是比较难受的。Google JSON Style Guide(中译)

sites 里的主要字段是指什么?

@wxt2005
Copy link
Owner Author

wxt2005 commented Aug 4, 2016

那可能真的得加个字段 lang 来指明作品的语言了,这样也方便筛选各种语言的番组。
sites 里的字段这样看起来确实有点乱,但是全用 Value 似乎也不太好,是不是需要有个文档来说明各个站点的规则?毕竟也不是所有 info 类的站点都可以用 id 来表示。或者干脆全部用 url

@weizhenye
Copy link
Contributor

info 类或许还能细分一下,可能可以加的站点有 aniDB、MyAnimeList、豆瓣、贴吧、维基(title 直接拼接?)。当然,这些是等有人能 PR 再考虑。

每种类型的站点有哪些字段肯定要有文档说明的。

主要字段可能是统一比较好,然后想了想该统一为 id 还是 url。

其实 id 肯定是有的,同一站点不同番组 url 中变化的部分就可以看作 id;对于某一番组而言,id 一般也是不会变的,我知道变过链接格式的有 AcFun、Bilibili、乐视、PPTV,只有 PPTV 是改了 id 的,但原 id 还是能用,拼接回去的 url 会跳转到新地址。

用 url 的话,如果链接格式改变就要改变所有番组的 url,但使用者就不用改了;用 id 的话,链接格式改变与本项目无关,需要变的是使用者,他要根据新的格式拼回去。上述的「使用者」是假定要使用 url(可能是大多数情况),如果「使用者」的目标是 id(比如我),那 url 就没什么好处了。

一些比较:

  • 兼容性:不能因为某个字段的值改变就导致使用者也要跟着改,为此升主版本号也是不合理的,这点上为满足大多数情况应该是用 url 比较好。
  • 有无冗余:这个肯定是 id 好。
  • 维护使用的便利性:维护的话 id 方便,基本不会改;使用的话 url 方便,满足大多数情况。

讲道理这时候应该优先考虑兼容性选择 url,但作为少数派的挣扎,我提个方案希望不会被打死:

在顶层加一个 urlTemplate 字段,指明某一站点的 url 模板。

{
  "urlTemplate": {
    "tudou": {
      "before": "http://www.tudou.com/albumcover/",
      "after": ".html"
    },
    // or
    "tudou": ["http://www.tudou.com/albumcover/", ".html"]
  },
  "sites": [
    {
      "type": "onair",
      "name": "tudou",
      "id": "uGqEOjd4Wd4"
    }
  ]
}

这样要 url 的有固定方法拼接不会有兼容问题,要 id 的不用另行为每一个站点写正则匹配。只是长得有点丑?

@wxt2005
Copy link
Owner Author

wxt2005 commented Aug 5, 2016

如果用这种方案的话,就干脆把站点的 meta data 分出来维护好了。
url 规则就用类似模板的方式去写。

{
    "sites": {
        "tudou": {
            "name": "土豆",
            "type": "onair",
            "urlTemplate": "http://www.tudou.com/albumcover/{{id}}.html"
        },
         "saraba1st": {
            "name": "S1",
            "type": "info",
            "urlTemplate": "http://bbs.saraba1st.com/2b/thread-{{id}}-1-1.html"
        },
        "dmhy": {
            "name": "动漫花园",
            "type": "resource",
            "urlTemplate": "https://share.dmhy.org/topics/list?keyword={{keyword}}"
        }
    },
    "bangumis": [
        // ...
    ]
}

@weizhenye
Copy link
Contributor

这么一说才发现 type 也算冗余,以后有没有可能出现一个站点有两种类型的情况?比如 S1 的讨论楼 type 为 forum,投票楼为 vote 之类的。

bangumis 字段指的是「番组们」而不是「Bangumi.tv 的数据」吧?罗马字加英文 s 实在是比较少见,况且与 Bangumi.tv 有歧义。不如直接命名为 sitessitesMeta

冗余和效率总是难以两全,type 作为最常用的字段,是否应该优先效率?

data.sites.filter(site => site.type === 'onair');
// vs
data.sites.filter(site => data.sitesMeta[site.name].type === 'onair');

不过感觉后者也能接受。

sites 中的 name 是来自域名的代号,sitesMeta 中的 name 是官方表达的名称,是否应该换个字段名防止歧义?

resource 类的主要字段用 keyword 不是又没有统一了么。像 acg.rip 使用的是数字 ID,应当统一为 id

模板的字符串替换怕一些奇葩的 url,不过应该不会有。另外主要字段统一为 id 后,{{id}} 中的 id 就不必须了,替换部分只要是个唯一的字符串就行了,替换更方便。

@wxt2005
Copy link
Owner Author

wxt2005 commented Aug 6, 2016

  • 如果 type 不同,干脆就用不同的 name 好了,S1Discussion S1Vote 之类的。
  • 那直接叫 itemssites 算了😌
  • 第二种其实也还好,效率不会大打折扣。
  • 站点的全名也叫 title 吧。
  • 我之所以提议用模板字符串,就是为了可以不用去统一字段名,这样只要模板字符串中所需的字段在站点数据中有对应就可以了(当然从规范角度来说,同类型的字段肯定要用同一个名字,不能乱取)。这样哪怕出现 url 中需要拼接两个字段数据的情况,也可以轻松应对。
  • 能和这种模板语法冲突的 url 至今没见过,希望不会有吧……

@weizhenye
Copy link
Contributor

如果主要字段只用作拼接 url 的话,那没什么问题;如果其他部分也要用到的话,还要先从 urlTemplate 里获取得知哪个字段是主要字段才行。现在暂时也想不出有什么其他用途。

另外腾讯视频的 url 有点特殊,http://v.qq.com/detail/w/wgzklo5zkrgalda.html 中 id 前面会有一个字符,与 id 的第一位相同,这个该怎么处理?直接 w/wgzklo5zkrgalda 作为 id 吗?
还有优酷,http://www.youku.com/show_page/id_z1e13314abec311e38b3f.html 的 id 部分似乎总是以 z 开头的,实际上在优酷的各种 API 中也是以 z 后面的那部分作为 id 的,应该要和官方保持一致吧?

@wxt2005
Copy link
Owner Author

wxt2005 commented Aug 8, 2016

虽然麻烦了点,不过想写正则替换的时候应该还是会瞄一眼字段里有啥字段名的吧。
或者用类似下面这样的函数,就不用去关心字段名是什么了。

urlTemplate.replace(/{{(\w+)}}/g, (match, key) => data.key);

id 规则特殊情况特殊处理。
腾讯视频的话,确实看起来比较难受,但也只能把变化的部分作为 id 了,用 w/wgzklo5zkrgalda 这部份。
优酷也是同样,既然变化的只有 z 之后的部分,而且官方 api 也有规定,那就遵序这个规则好了。

@weizhenye
Copy link
Contributor

先 repo 建起来文档写起来?

@GPBeta
Copy link

GPBeta commented Sep 2, 2016

目前 bangumi-list 有相关 API 么?

@wxt2005
Copy link
Owner Author

wxt2005 commented Sep 5, 2016

@weizhenye @CnSimonChan 总之先建了个 repo: https://github.com/bangumi-data/bangumi-data

@GPBeta 不好意思,暂时还没有哦

@weizhenye
Copy link
Contributor

给 bangumi-data 加个 gitter 或 Slack 的 badge 吧,简单的讨论就不必 issue 了。

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants