├── Alfred
├── Bangumi
│ ├── Source
│ │ ├── Feedback.py
│ │ ├── bangumi.py
│ │ ├── bangumis.py
│ │ ├── biclass.py
│ │ ├── icon.png
│ │ ├── support.py
│ │ └── zhuanti.py
│ └── bangumi.alfredworkflow
├── Bilibili Hot
│ ├── Bilibili Hot.alfredworkflow
│ └── Source
│ │ ├── biclass.py
│ │ ├── blhot.py
│ │ ├── icon.png
│ │ └── support.py
└── BilibiliSearch
│ ├── Source
│ ├── bilibiliSearch.py
│ └── icon.png
│ └── bilibili.alfredworkflow
├── BiliMerge
├── BiliMergeFlv.py
└── README.md
├── GetDanmuAss
├── GetAss.py
├── README.md
├── biclass.py
├── spview danmaku
│ ├── GetAssDanmaku.py
│ ├── biclass.py
│ ├── bilibili.py
│ ├── main.py
│ └── support.py
└── support.py
├── GetVideoUrl
├── biliDownLoad.py
└── biliurl
├── LICENSE
├── README.md
├── api.md
├── bili-monitor
├── biclass.py
├── bilibili.py
├── main.py
└── support.py
├── bili_live_guaji
└── bili_guaji.py
├── bilibili-po
├── biclass.py
├── bilibili-relation.txt
├── bilibili.py
├── finished.txt
├── main.py
├── polist.txt
├── support.py
├── 分析
│ ├── article-fans.txt
│ ├── po-analyse.py
│ ├── up-follow.rar
│ ├── upinfo.txt
│ ├── 关注圈
│ │ ├── 1.txt
│ │ ├── 2.txt
│ │ ├── 3.txt
│ │ ├── 4.txt
│ │ ├── 5.txt
│ │ ├── 6.txt
│ │ ├── 7.txt
│ │ ├── 8.txt
│ │ └── 9.txt
│ └── 分析.rar
└── 爬取结果
│ └── bilibili-relation.rar
├── bilibili-video
├── .gitignore
├── GetAssDanmaku.py
├── biclass.py
├── bilibili.py
├── main.py
└── support.py
├── danmu-Delay
├── README.md
└── danmu_delay.py
└── python API
├── .gitignore
├── GetAssDanmaku.py
├── biclass.py
├── bilibili.py
└── support.py
/Alfred/Bangumi/Source/Feedback.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Fri Sep 26 00:07:49 2014
4 |
5 | @author: vespa
6 | """
7 | import sys
8 |
9 | import xml.etree.ElementTree as et
10 | default_encoding = 'utf-8'
11 | if sys.getdefaultencoding() != default_encoding:
12 | reload(sys)
13 | sys.setdefaultencoding(default_encoding)
14 |
15 | class Feedback():
16 | """Feeback used by Alfred Script Filter
17 |
18 | Usage:
19 | fb = Feedback()
20 | fb.add_item('Hello', 'World')
21 | fb.add_item('Foo', 'Bar')
22 | print fb
23 |
24 | """
25 |
26 | def __init__(self):
27 | self.feedback = et.Element('items')
28 |
29 | def __repr__(self):
30 | """XML representation used by Alfred
31 |
32 | Returns:
33 | XML string
34 | """
35 | return et.tostring(self.feedback)
36 |
37 | def add_item(self, title, subtitle = "", arg = "", valid = "yes", autocomplete = "", icon = "icon.png"):
38 | """
39 | Add item to alfred Feedback
40 |
41 | Args:
42 | title(str): the title displayed by Alfred
43 | Keyword Args:
44 | subtitle(str): the subtitle displayed by Alfred
45 | arg(str): the value returned by alfred when item is selected
46 | valid(str): whether or not the entry can be selected in Alfred to trigger an action
47 | autcomplete(str): the text to be inserted if an invalid item is selected. This is only used if 'valid' is 'no'
48 | icon(str): filename of icon that Alfred will display
49 | """
50 | item = et.SubElement(self.feedback, 'item', uid=str(len(self.feedback)), arg=arg, valid=valid, autocomplete=autocomplete)
51 | _title = et.SubElement(item, 'title')
52 | _title.text = title
53 | _sub = et.SubElement(item, 'subtitle')
54 | _sub.text = subtitle
55 | _icon = et.SubElement(item, 'icon')
56 | _icon.text = icon
--------------------------------------------------------------------------------
/Alfred/Bangumi/Source/bangumi.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:42:03 2014
4 |
5 | @author: Administrator
6 | """
7 |
8 | from support import *
9 | from Feedback import *
10 | import hashlib
11 | import datetime
12 |
13 | def GetSign(params,appkey,AppSecret=None):
14 | """
15 | 获取新版API的签名,不然会返回-3错误
16 | 待添加:【重要!】
17 | 需要做URL编码并保证字母都是大写,如 %2F
18 | """
19 | params['appkey']=appkey;
20 | data = "";
21 | paras = params.keys();
22 | paras.sort();
23 | for para in paras:
24 | if data != "":
25 | data += "&";
26 | data += para + "=" + params[para];
27 | if AppSecret == None:
28 | return data
29 | m = hashlib.md5()
30 | m.update(data+AppSecret)
31 | return data+'&sign='+m.hexdigest()
32 |
33 | def GetGangumi(appkey,btype,weekday,mode,week):
34 | """
35 | 获取新番信息
36 | 输入:
37 | btype:番剧类型 2: 二次元新番 3: 三次元新番 默认:所有
38 | weekday:周一:1 周二:2 ...周六:6
39 | """
40 | paras = {};
41 | paras['btype'] = GetString(btype)
42 | if weekday != None:
43 | paras['weekday'] = GetString(weekday)
44 | url = 'http://api.bilibili.cn/bangumi?' + GetSign(paras,appkey,None);
45 | jsoninfo = JsonInfo(url);
46 | bangumilist = [];
47 | for bgm in jsoninfo.Getvalue('list'):
48 | if mode == 't' and bgm['weekday'] != int(time.strftime("%w",time.localtime())):
49 | continue;
50 | if mode != 't' and week != None and bgm['weekday'] != week:
51 | continue
52 | bangumi = Bangumi();
53 | bangumi.lastupdate = bgm['lastupdate']
54 | bangumi.title = bgm['title']
55 | bangumi.lastupdate_at = bgm['lastupdate_at']
56 | bangumi.weekday = bgm['weekday']
57 | bangumi.bgmcount = bgm['bgmcount']
58 | bangumilist.append(bangumi)
59 | if mode == 'r':
60 | bangumilist = sorted(bangumilist,key=lambda x:x.lastupdate)
61 | bangumilist.reverse();
62 | if len(bangumilist) > 20:
63 | bangumilist = bangumilist[0:20]
64 | return bangumilist
65 |
66 | def datetime_timestamp(dt):
67 | time.strptime(dt, '%Y-%m-%d %H:%M:%S')
68 | s = time.mktime(time.strptime(dt, '%Y-%m-%d %H:%M:%S'))
69 | return int(s)
70 |
71 | def timestamp_datetime(value):
72 | format = '%Y-%m-%d %H:%M:%S'
73 | value = time.localtime(value)
74 | dt = time.strftime(format, value)
75 | return dt
76 |
77 | def Getweek(num):
78 | string = ['日','一','二','三','四','五','六']
79 | return string[num]
80 |
81 |
82 | fb = Feedback()
83 | query = '{query}'
84 | # t:今天新番
85 | # r:最近更新
86 | # 3:三次元
87 | # wn:查询星期n
88 |
89 | appkey='03fc8eb101b091fb';
90 |
91 | qtype = 2;
92 | qmode = 'r'
93 | qweek = None
94 | opt = re.findall(r'^(\d)',query)
95 | if opt != []:
96 | qtype = int(opt[0])
97 | if qtype not in [2,3]:
98 | qtype = 2
99 |
100 | opt = re.findall(r'w(\d)',query)
101 | if opt != []:
102 | qweek = int(opt[0])
103 | if not 0 <= qweek <= 6:
104 | qweek = None
105 |
106 |
107 | opt = re.findall(r'r',query)
108 | if opt != []:
109 | qmode = 'r'
110 |
111 | opt = re.findall(r't',query)
112 | if opt != []:
113 | qmode = 't'
114 |
115 |
116 | bangumilist = GetGangumi(appkey,btype = qtype,weekday=0,mode = qmode,week = qweek);
117 | try:
118 | for bgm in bangumilist:
119 | fb.add_item(bgm.title,subtitle="【周%s】最后更新时间:%s,现有%s集"%(Getweek(bgm.weekday),bgm.lastupdate_at,bgm.bgmcount),arg=bgm.title)
120 |
121 | except SyntaxError as e:
122 | if ('EOF', 'EOL' in e.msg):
123 | fb.add_item('...')
124 | else:
125 | fb.add_item('SyntaxError', e.msg)
126 | except Exception as e:
127 | fb.add_item(e.__class__.__name__,subtitle=e.message)
128 | print fb
--------------------------------------------------------------------------------
/Alfred/Bangumi/Source/bangumis.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:42:03 2014
4 |
5 | @author: Administrator
6 | """
7 |
8 | from support import *
9 | from Feedback import *
10 | import hashlib
11 | import datetime
12 |
13 | def GetSign(params,appkey,AppSecret=None):
14 | """
15 | 获取新版API的签名,不然会返回-3错误
16 | 待添加:【重要!】
17 | 需要做URL编码并保证字母都是大写,如 %2F
18 | """
19 | params['appkey']=appkey;
20 | data = "";
21 | paras = params.keys();
22 | paras.sort();
23 | for para in paras:
24 | if data != "":
25 | data += "&";
26 | data += para + "=" + params[para];
27 | if AppSecret == None:
28 | return data
29 | m = hashlib.md5()
30 | m.update(data+AppSecret)
31 | return data+'&sign='+m.hexdigest()
32 |
33 | def GetGangumi(appkey,btype,weekday,mode,week):
34 | """
35 | 获取新番信息
36 | 输入:
37 | btype:番剧类型 2: 二次元新番 3: 三次元新番 默认:所有
38 | weekday:周一:1 周二:2 ...周六:6
39 | """
40 | paras = {};
41 | paras['btype'] = GetString(btype)
42 | if weekday != None:
43 | paras['weekday'] = GetString(weekday)
44 | url = 'http://api.bilibili.cn/bangumi?' + GetSign(paras,appkey,None);
45 | jsoninfo = JsonInfo(url);
46 | bangumilist = [];
47 | for bgm in jsoninfo.Getvalue('list'):
48 | if mode == 't' and bgm['weekday'] != int(time.strftime("%w",time.localtime())):
49 | continue;
50 | if mode != 't' and week != None and bgm['weekday'] != week:
51 | continue
52 | bangumi = Bangumi();
53 | bangumi.lastupdate = bgm['lastupdate']
54 | bangumi.title = bgm['title']
55 | bangumi.lastupdate_at = bgm['lastupdate_at']
56 | bangumi.weekday = bgm['weekday']
57 | bangumi.bgmcount = bgm['bgmcount']
58 | bangumi.spid = bgm['spid']
59 | bangumilist.append(bangumi)
60 | if mode == 'r':
61 | bangumilist = sorted(bangumilist,key=lambda x:x.lastupdate)
62 | bangumilist.reverse();
63 | if len(bangumilist) > 20:
64 | bangumilist = bangumilist[0:20]
65 | return bangumilist
66 |
67 | def datetime_timestamp(dt):
68 | time.strptime(dt, '%Y-%m-%d %H:%M:%S')
69 | s = time.mktime(time.strptime(dt, '%Y-%m-%d %H:%M:%S'))
70 | return int(s)
71 |
72 | def timestamp_datetime(value):
73 | format = '%Y-%m-%d %H:%M:%S'
74 | value = time.localtime(value)
75 | dt = time.strftime(format, value)
76 | return dt
77 |
78 | def Getweek(num):
79 | string = ['日','一','二','三','四','五','六']
80 | return string[num]
81 |
82 |
83 | fb = Feedback()
84 | query = '{query}'
85 | # t:今天新番
86 | # r:最近更新
87 | # 3:三次元
88 | # wn:查询星期n
89 |
90 | appkey='03fc8eb101b091fb';
91 |
92 | qtype = 2;
93 | qmode = 'r'
94 | qweek = None
95 | opt = re.findall(r'^(\d)',query)
96 | if opt != []:
97 | qtype = int(opt[0])
98 | if qtype not in [2,3]:
99 | qtype = 2
100 |
101 | opt = re.findall(r'w(\d)',query)
102 | if opt != []:
103 | qweek = int(opt[0])
104 | if not 0 <= qweek <= 6:
105 | qweek = None
106 |
107 |
108 | opt = re.findall(r'r',query)
109 | if opt != []:
110 | qmode = 'r'
111 |
112 | opt = re.findall(r't',query)
113 | if opt != []:
114 | qmode = 't'
115 |
116 |
117 | bangumilist = GetGangumi(appkey,btype = qtype,weekday=0,mode = qmode,week = qweek);
118 | try:
119 | for bgm in bangumilist:
120 | fb.add_item(bgm.title,subtitle="【周%s】最后更新时间:%s,现有%s集"%(Getweek(bgm.weekday),bgm.lastupdate_at,bgm.bgmcount),arg=str(bgm.spid))
121 |
122 | except SyntaxError as e:
123 | if ('EOF', 'EOL' in e.msg):
124 | fb.add_item('...')
125 | else:
126 | fb.add_item('SyntaxError', e.msg)
127 | except Exception as e:
128 | fb.add_item(e.__class__.__name__,subtitle=e.message)
129 | print fb
--------------------------------------------------------------------------------
/Alfred/Bangumi/Source/biclass.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Wed May 28 01:22:20 2014
4 |
5 | @author: Administrator
6 | """
7 |
8 | class User():
9 | def __init__(self,m_mid=None,m_name=None):
10 | if m_mid:
11 | self.mid = m_mid;
12 | if m_name:
13 | self.name = m_name;
14 | def saveToFile(self,fid):
15 | fid.write('名字:%s\n'%self.name);
16 | fid.write('id:%s\n'%self.mid);
17 | fid.write('是否认证:%s\n'%self.isApprove);
18 | fid.write('空间:%s\n'%self.spaceName);
19 | fid.write('性别:%s\n'%self.sex);
20 | fid.write('账号显示标识:%s\n'%self.rank);
21 | fid.write('头像:%s\n'%self.avatar);
22 | fid.write('关注好友数目:%d\n'%self.follow);
23 | fid.write('粉丝数目:%d\n'%self.fans);
24 | fid.write('投稿数:%d\n'%self.article);
25 | fid.write('地点:%s\n'%self.place);
26 | fid.write('认证信息:%s\n'%self.description);
27 | fid.write('关注好友:\n');
28 | if self.followlist:
29 | for fo in self.followlist:
30 | fid.write('\t%s\n'%fo);
31 | # 获取空间地址
32 | def GetSpace(self):
33 | return 'http://space.bilibili.tv/'+str(self.mid);
34 | mid = None;
35 | name = None;
36 | isApprove = False;#是否是认证账号
37 | spaceName = "";
38 | sex = ""
39 | rank = None;
40 | avatar = None;
41 | follow = 0;#关注好友数目
42 | fans = 0;#粉丝数目
43 | article = 0;#投稿数
44 | place = None;#所在地
45 | description = None;#认证用户为认证信息 普通用户为交友宣言
46 | followlist = None;#关注的好友列表
47 |
48 |
49 | class Video():
50 | def __init__(self,m_aid=None,m_title=None):
51 | if m_aid:
52 | self.aid = m_aid;
53 | if m_title:
54 | self.title = m_title;
55 | # 写到文件中
56 | def saveToFile(self,fid):
57 | fid.write('av号:%d\n'%self.aid);
58 | fid.write('标题:%s\n'%self.title);
59 | fid.write('观看:%d\n'%self.guankan);
60 | fid.write('收藏:%d\n'%self.shoucang);
61 | fid.write('弹幕:%d\n'%self.danmu);
62 | fid.write('日期:%s\n'%self.date);
63 | fid.write('封面地址:%s\n'%self.cover);
64 | fid.write('Up主:\n');
65 | self.author.saveToFile(fid);
66 | fid.write('\n');
67 | aid = None;
68 | title = None;
69 | guankan = None;
70 | shoucang = None;
71 | danmu = None;
72 | date = None;
73 | cover = None;
74 | commentNumber = None;
75 | description = None;
76 | tag = None;
77 | author = None;
78 | page = None;
79 | credit = None;
80 | coin = None;
81 | spid = None;
82 | cid = None;
83 | offsite = None;#Flash播放调用地址
84 | Iscopy = None;
85 | subtitle = None;
86 | duration = None;
87 | #不明:
88 | tid = None;
89 | typename = None;
90 | instant_server = None;
91 | src = None;
92 | partname = None;
93 | #播放信息:
94 | play_site = None;
95 | play_forward = None;
96 | play_mobile = None;
97 |
98 | class Bangumi():
99 | def __init__(self):
100 | pass;
101 | typeid = None;
102 | lastupdate = None;
103 | areaid = None;
104 | bgmcount = None;#番剧当前总集数
105 | title = None;
106 | lastupdate_at = None;
107 | attention = None;
108 | cover = None;
109 | priority = None;
110 | area = None;
111 | weekday = None;
112 | spid = None;
113 | new = None;
114 | scover = None;
115 | mcover = None;
116 | click = None;
117 | recentupdate = None;
118 |
119 | class Comment():
120 | def __init__(self):
121 | self.post_user = User();
122 | lv = None;#楼层
123 | fbid = None;#评论id
124 | msg = None;
125 | ad_check = None;#状态 (0: 正常 1: UP主隐藏 2: 管理员删除 3: 因举报删除)
126 | post_user = None;
127 |
128 | class CommentList():
129 | def __init__(self):
130 | pass;
131 | comments = None;
132 | commentLen = None;
133 | page = None;
134 |
135 |
--------------------------------------------------------------------------------
/Alfred/Bangumi/Source/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vespa314/bilibili-api/42b6b90aa7c141f5cfb0fdc754435518106f6966/Alfred/Bangumi/Source/icon.png
--------------------------------------------------------------------------------
/Alfred/Bangumi/Source/support.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:59:09 2014
4 |
5 | @author: Administrator
6 | """
7 | import urllib2
8 | import re
9 | import json
10 | from biclass import *
11 | import time
12 | def GetRE(content,regexp):
13 | return re.findall(regexp, content)
14 |
15 | def getURLContent(url):
16 | while True:
17 | flag = 1;
18 | try:
19 | headers = {'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
20 | req = urllib2.Request(url = url,headers = headers);
21 | content = urllib2.urlopen(req).read();
22 | except:
23 | flag = 0;
24 | time.sleep(5)
25 | if flag == 1:
26 | break;
27 | return content;
28 |
29 | #def FromJson(url):
30 | # return json.loads(getURLContent(url))
31 |
32 | class JsonInfo():
33 | def __init__(self,url):
34 | self.info = json.loads(getURLContent(url));
35 | def Getvalue(self,*keys):
36 | if len(keys) == 0:
37 | return None
38 | if self.info.has_key(keys[0]):
39 | temp = self.info[keys[0]];
40 | else:
41 | return None;
42 | if len(keys) > 1:
43 | for key in keys[1:]:
44 | if temp.has_key(key):
45 | temp = temp[key]
46 | else:
47 | return None;
48 | return temp
49 | info = None;
50 |
51 | def GetString(t):
52 | if type(t) == int:
53 | return str(t)
54 | return t
55 |
56 | def getint(string):
57 | try:
58 | i = int(string)
59 | except:
60 | i = 0
61 | return i
62 |
63 | #从视频源码获取视频信息
64 | def GetVideoFromRate(content):
65 | #av号和标题
66 | regular1 = r'([^/]+)';
67 | info1 = GetRE(content,regular1)
68 | #观看数
69 | regular2 = r'(.+)';
70 | info2 = GetRE(content,regular2)
71 | #收藏
72 | regular3 = r'(.+)';
73 | info3 = GetRE(content,regular3)
74 | #弹幕
75 | regular4 = r'(.+)';
76 | info4 = GetRE(content,regular4)
77 | #日期
78 | regular5 = r'(\d+-\d+-\d+ \d+:\d+)';
79 | info5 = GetRE(content,regular5)
80 | #封面
81 | regular6 = r'
';
82 | info6 = GetRE(content,regular6)
83 | #Up的id和名字
84 | regular7 = r'(.+)'
85 | info7 = GetRE(content,regular7)
86 | #!!!!!!!!这里可以断言所有信息长度相等
87 | videoNum = len(info1);#视频长度
88 | videoList = [];
89 | for i in range(videoNum):
90 | video_t = Video();
91 | video_t.aid = getint(info1[i][0]);
92 | video_t.title = info1[i][1];
93 | video_t.guankan = getint(info2[i]);
94 | video_t.shoucang = getint(info3[i]);
95 | video_t.danmu = getint(info4[i]);
96 | video_t.date = info5[i];
97 | video_t.cover = info6[i];
98 | video_t.author = User(info7[i][0],info7[i][1])
99 | videoList.append(video_t);
100 | return videoList
101 |
--------------------------------------------------------------------------------
/Alfred/Bangumi/Source/zhuanti.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:42:03 2014
4 |
5 | @author: Administrator
6 | """
7 |
8 | from support import *
9 | import hashlib
10 | import datetime
11 |
12 | def GetVideoOfZhuanti(spid,season_id=None,bangumi=None):
13 | """
14 | 输入:
15 | spid:专题id
16 | season_id:分季ID
17 | bangumi:设置为1返回剧番,不设置或者设置为0返回相关视频
18 | 返回:
19 | 视频列表,包含av号,标题,封面和观看数
20 | """
21 | url = ' http://api.bilibili.cn/spview?spid='+GetString(spid);
22 | if season_id != None:
23 | url += '&season_id='+GetString(season_id);
24 | if bangumi != None:
25 | url += '&bangumi='+GetString(bangumi);
26 | jsoninfo = json.loads(getURLContent(url))
27 | try:
28 | print jsoninfo['list'][0]['aid'],
29 | except:
30 | pass
31 |
32 |
33 | query = '{query}'
34 | # t:今天新番
35 | # r:最近更新
36 | # 3:三次元
37 | # wn:查询星期n
38 |
39 | GetVideoOfZhuanti(query,bangumi = 1)
40 |
--------------------------------------------------------------------------------
/Alfred/Bangumi/bangumi.alfredworkflow:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vespa314/bilibili-api/42b6b90aa7c141f5cfb0fdc754435518106f6966/Alfred/Bangumi/bangumi.alfredworkflow
--------------------------------------------------------------------------------
/Alfred/Bilibili Hot/Bilibili Hot.alfredworkflow:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vespa314/bilibili-api/42b6b90aa7c141f5cfb0fdc754435518106f6966/Alfred/Bilibili Hot/Bilibili Hot.alfredworkflow
--------------------------------------------------------------------------------
/Alfred/Bilibili Hot/Source/biclass.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Wed May 28 01:22:20 2014
4 |
5 | @author: Administrator
6 | """
7 |
8 | class User():
9 | def __init__(self,m_mid=None,m_name=None):
10 | if m_mid:
11 | self.mid = m_mid;
12 | if m_name:
13 | self.name = m_name;
14 | def saveToFile(self,fid):
15 | fid.write('名字:%s\n'%self.name);
16 | fid.write('id:%s\n'%self.mid);
17 | fid.write('是否认证:%s\n'%self.isApprove);
18 | fid.write('空间:%s\n'%self.spaceName);
19 | fid.write('性别:%s\n'%self.sex);
20 | fid.write('账号显示标识:%s\n'%self.rank);
21 | fid.write('头像:%s\n'%self.avatar);
22 | fid.write('关注好友数目:%d\n'%self.follow);
23 | fid.write('粉丝数目:%d\n'%self.fans);
24 | fid.write('投稿数:%d\n'%self.article);
25 | fid.write('地点:%s\n'%self.place);
26 | fid.write('认证信息:%s\n'%self.description);
27 | fid.write('关注好友:\n');
28 | if self.followlist:
29 | for fo in self.followlist:
30 | fid.write('\t%s\n'%fo);
31 | # 获取空间地址
32 | def GetSpace(self):
33 | return 'http://space.bilibili.tv/'+str(self.mid);
34 | mid = None;
35 | name = None;
36 | isApprove = False;#是否是认证账号
37 | spaceName = "";
38 | sex = ""
39 | rank = None;
40 | avatar = None;
41 | follow = 0;#关注好友数目
42 | fans = 0;#粉丝数目
43 | article = 0;#投稿数
44 | place = None;#所在地
45 | description = None;#认证用户为认证信息 普通用户为交友宣言
46 | followlist = None;#关注的好友列表
47 |
48 |
49 | class Video():
50 | def __init__(self,m_aid=None,m_title=None):
51 | if m_aid:
52 | self.aid = m_aid;
53 | if m_title:
54 | self.title = m_title;
55 | # 写到文件中
56 | def saveToFile(self,fid):
57 | fid.write('av号:%d\n'%self.aid);
58 | fid.write('标题:%s\n'%self.title);
59 | fid.write('观看:%d\n'%self.guankan);
60 | fid.write('收藏:%d\n'%self.shoucang);
61 | fid.write('弹幕:%d\n'%self.danmu);
62 | fid.write('日期:%s\n'%self.date);
63 | fid.write('封面地址:%s\n'%self.cover);
64 | fid.write('Up主:\n');
65 | self.author.saveToFile(fid);
66 | fid.write('\n');
67 | aid = None;
68 | title = None;
69 | guankan = None;
70 | shoucang = None;
71 | danmu = None;
72 | date = None;
73 | cover = None;
74 | commentNumber = None;
75 | description = None;
76 | tag = None;
77 | author = None;
78 | page = None;
79 | credit = None;
80 | coin = None;
81 | spid = None;
82 | cid = None;
83 | offsite = None;#Flash播放调用地址
84 | Iscopy = None;
85 | subtitle = None;
86 | duration = None;
87 | #不明:
88 | tid = None;
89 | typename = None;
90 | instant_server = None;
91 | src = None;
92 | partname = None;
93 | #播放信息:
94 | play_site = None;
95 | play_forward = None;
96 | play_mobile = None;
97 |
98 | class Bangumi():
99 | def __init__(self):
100 | pass;
101 | typeid = None;
102 | lastupdate = None;
103 | areaid = None;
104 | bgmcount = None;#番剧当前总集数
105 | title = None;
106 | lastupdate_at = None;
107 | attention = None;
108 | cover = None;
109 | priority = None;
110 | area = None;
111 | weekday = None;
112 | spid = None;
113 | new = None;
114 | scover = None;
115 | mcover = None;
116 | click = None;
117 | recentupdate = None;
118 |
119 | class Comment():
120 | def __init__(self):
121 | self.post_user = User();
122 | lv = None;#楼层
123 | fbid = None;#评论id
124 | msg = None;
125 | ad_check = None;#状态 (0: 正常 1: UP主隐藏 2: 管理员删除 3: 因举报删除)
126 | post_user = None;
127 |
128 | class CommentList():
129 | def __init__(self):
130 | pass;
131 | comments = None;
132 | commentLen = None;
133 | page = None;
134 |
135 |
--------------------------------------------------------------------------------
/Alfred/Bilibili Hot/Source/blhot.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:42:03 2014
4 |
5 | @author: Administrator
6 | """
7 |
8 |
9 | from support import *
10 | import hashlib
11 | import datetime
12 | import sys
13 |
14 |
15 |
16 |
17 |
18 | import xml.etree.ElementTree as et
19 | default_encoding = 'utf-8'
20 | if sys.getdefaultencoding() != default_encoding:
21 | reload(sys)
22 | sys.setdefaultencoding(default_encoding)
23 |
24 | class Feedback():
25 | """Feeback used by Alfred Script Filter
26 |
27 | Usage:
28 | fb = Feedback()
29 | fb.add_item('Hello', 'World')
30 | fb.add_item('Foo', 'Bar')
31 | print fb
32 |
33 | """
34 |
35 | def __init__(self):
36 | self.feedback = et.Element('items')
37 |
38 | def __repr__(self):
39 | """XML representation used by Alfred
40 |
41 | Returns:
42 | XML string
43 | """
44 | return et.tostring(self.feedback)
45 |
46 | def add_item(self, title, subtitle = "", arg = "", valid = "yes", autocomplete = "", icon = "icon.png"):
47 | """
48 | Add item to alfred Feedback
49 |
50 | Args:
51 | title(str): the title displayed by Alfred
52 | Keyword Args:
53 | subtitle(str): the subtitle displayed by Alfred
54 | arg(str): the value returned by alfred when item is selected
55 | valid(str): whether or not the entry can be selected in Alfred to trigger an action
56 | autcomplete(str): the text to be inserted if an invalid item is selected. This is only used if 'valid' is 'no'
57 | icon(str): filename of icon that Alfred will display
58 | """
59 | item = et.SubElement(self.feedback, 'item', uid=str(len(self.feedback)), arg=arg, valid=valid, autocomplete=autocomplete)
60 | _title = et.SubElement(item, 'title')
61 | _title.text = title
62 | _sub = et.SubElement(item, 'subtitle')
63 | _sub.text = subtitle
64 | _icon = et.SubElement(item, 'icon')
65 | _icon.text = icon
66 |
67 |
68 |
69 | def GetSign(params,appkey,AppSecret=None):
70 | """
71 | 获取新版API的签名,不然会返回-3错误
72 | 待添加:【重要!】
73 | 需要做URL编码并保证字母都是大写,如 %2F
74 | """
75 | params['appkey']=appkey;
76 | data = "";
77 | paras = params.keys();
78 | paras.sort();
79 | for para in paras:
80 | if data != "":
81 | data += "&";
82 | data += para + "=" + params[para];
83 | if AppSecret == None:
84 | return data
85 | m = hashlib.md5()
86 | m.update(data+AppSecret)
87 | return data+'&sign='+m.hexdigest()
88 |
89 | def GetRank(appkey,tid,begin=None,end=None,page = None,pagesize=None,click_detail =None,order = None,AppSecret=None):
90 | paras = {};
91 | paras['appkey']=appkey;
92 | paras['tid']=GetString(tid);
93 | if order:
94 | paras['order']=order;
95 | if click_detail:
96 | paras['click_detail']=click_detail;
97 | if pagesize:
98 | paras['pagesize']=GetString(pagesize);
99 | if begin != None and len(begin)==3:
100 | paras['begin']='%d-%d-%d'%(begin[0],begin[1],begin[2]);
101 | if end != None and len(end)==3:
102 | paras['end']='%d-%d-%d'%(end[0],end[1],end[2]);
103 | if page:
104 | paras['page']=GetString(page);
105 | if click_detail:
106 | paras['click_detail'] = click_detail;
107 | url = 'http://api.bilibili.cn/list?' + GetSign(paras,appkey,AppSecret);
108 | jsoninfo = JsonInfo(url);
109 | videolist = [];
110 | for i in range(len(jsoninfo.Getvalue('list'))-1):
111 | idx = str(i);
112 | item = jsoninfo.Getvalue('list',idx);
113 | video = Video(item['aid'],item['title']);
114 | video.guankan = item['play'];
115 | video.tid = item['typeid'];
116 | video.author = User(item['mid'],item['author'])
117 | video.description = item['description'];
118 | video.duration = item['duration'];
119 | videolist.append(video)
120 | return videolist
121 |
122 | query = '{query}'
123 | fb = Feedback()
124 | appkey = "03fc8eb101b091fb"
125 | dayspan = 3
126 |
127 | modelist = {'dm':'damku','sc':'stow','pl':"review",'yb':'promote'}
128 | mode = None
129 | for k in modelist:
130 | opt = re.findall(k,query)
131 | if opt != []:
132 | mode = modelist[k]
133 | break
134 | if mode == None:
135 | mode = 'hot'
136 |
137 | zonelist = {'dh':1,'yy':3,'yx':4,'kj':36,'yl':5}
138 | zone = None
139 | for k in zonelist:
140 | opt = re.findall(k,query)
141 | if opt != []:
142 | zone = zonelist[k]
143 | break
144 | if zone == None:
145 | zone = 0
146 |
147 | opt = re.findall(r'd(\d+)',query)
148 | if opt != []:
149 | dayspan = int(opt[0])
150 | if dayspan > 90:
151 | dayspan = 3
152 |
153 |
154 | endday = datetime.datetime.now()
155 | beginday = endday - datetime.timedelta(days =dayspan)
156 |
157 | videolist = GetRank(appkey,zone,begin=[beginday.year,beginday.month,beginday.day],end=[endday.year,endday.month,endday.day],page = None,pagesize=30,click_detail =None,order = mode,AppSecret=None)
158 |
159 | try:
160 | for bgm in videolist:
161 | if bgm.tid not in [33,32,94]:
162 | fb.add_item("%s(%s)"%(bgm.title,str(bgm.guankan)),subtitle="【%s】%s"%(bgm.author.name,bgm.description),arg=bgm.aid)
163 |
164 | except SyntaxError as e:
165 | if ('EOF', 'EOL' in e.msg):
166 | fb.add_item('...')
167 | else:
168 | fb.add_item('SyntaxError', e.msg)
169 | except Exception as e:
170 | fb.add_item(e.__class__.__name__,subtitle=e.message)
171 | print fb
172 |
--------------------------------------------------------------------------------
/Alfred/Bilibili Hot/Source/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vespa314/bilibili-api/42b6b90aa7c141f5cfb0fdc754435518106f6966/Alfred/Bilibili Hot/Source/icon.png
--------------------------------------------------------------------------------
/Alfred/Bilibili Hot/Source/support.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:59:09 2014
4 |
5 | @author: Administrator
6 | """
7 | import urllib2
8 | import re
9 | import json
10 | from biclass import *
11 | import time
12 | def GetRE(content,regexp):
13 | return re.findall(regexp, content)
14 |
15 | def getURLContent(url):
16 | while True:
17 | flag = 1;
18 | try:
19 | headers = {'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
20 | req = urllib2.Request(url = url,headers = headers);
21 | content = urllib2.urlopen(req).read();
22 | except:
23 | flag = 0;
24 | time.sleep(5)
25 | if flag == 1:
26 | break;
27 | return content;
28 |
29 | #def FromJson(url):
30 | # return json.loads(getURLContent(url))
31 |
32 | class JsonInfo():
33 | def __init__(self,url):
34 | self.info = json.loads(getURLContent(url));
35 | def Getvalue(self,*keys):
36 | if len(keys) == 0:
37 | return None
38 | if self.info.has_key(keys[0]):
39 | temp = self.info[keys[0]];
40 | else:
41 | return None;
42 | if len(keys) > 1:
43 | for key in keys[1:]:
44 | if temp.has_key(key):
45 | temp = temp[key]
46 | else:
47 | return None;
48 | return temp
49 | info = None;
50 |
51 | def GetString(t):
52 | if type(t) == int:
53 | return str(t)
54 | return t
55 |
56 | def getint(string):
57 | try:
58 | i = int(string)
59 | except:
60 | i = 0
61 | return i
62 |
63 | #从视频源码获取视频信息
64 | def GetVideoFromRate(content):
65 | #av号和标题
66 | regular1 = r'([^/]+)';
67 | info1 = GetRE(content,regular1)
68 | #观看数
69 | regular2 = r'(.+)';
70 | info2 = GetRE(content,regular2)
71 | #收藏
72 | regular3 = r'(.+)';
73 | info3 = GetRE(content,regular3)
74 | #弹幕
75 | regular4 = r'(.+)';
76 | info4 = GetRE(content,regular4)
77 | #日期
78 | regular5 = r'(\d+-\d+-\d+ \d+:\d+)';
79 | info5 = GetRE(content,regular5)
80 | #封面
81 | regular6 = r'
';
82 | info6 = GetRE(content,regular6)
83 | #Up的id和名字
84 | regular7 = r'(.+)'
85 | info7 = GetRE(content,regular7)
86 | #!!!!!!!!这里可以断言所有信息长度相等
87 | videoNum = len(info1);#视频长度
88 | videoList = [];
89 | for i in range(videoNum):
90 | video_t = Video();
91 | video_t.aid = getint(info1[i][0]);
92 | video_t.title = info1[i][1];
93 | video_t.guankan = getint(info2[i]);
94 | video_t.shoucang = getint(info3[i]);
95 | video_t.danmu = getint(info4[i]);
96 | video_t.date = info5[i];
97 | video_t.cover = info6[i];
98 | video_t.author = User(info7[i][0],info7[i][1])
99 | videoList.append(video_t);
100 | return videoList
101 |
--------------------------------------------------------------------------------
/Alfred/BilibiliSearch/Source/bilibiliSearch.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import sys
4 | import re
5 | import zlib
6 | import urllib2
7 |
8 | import xml.etree.ElementTree as et
9 | default_encoding = 'utf-8'
10 | if sys.getdefaultencoding() != default_encoding:
11 | reload(sys)
12 | sys.setdefaultencoding(default_encoding)
13 |
14 | class Feedback():
15 | """Feeback used by Alfred Script Filter
16 |
17 | Usage:
18 | fb = Feedback()
19 | fb.add_item('Hello', 'World')
20 | fb.add_item('Foo', 'Bar')
21 | print fb
22 |
23 | """
24 |
25 | def __init__(self):
26 | self.feedback = et.Element('items')
27 |
28 | def __repr__(self):
29 | """XML representation used by Alfred
30 |
31 | Returns:
32 | XML string
33 | """
34 | return et.tostring(self.feedback)
35 |
36 | def add_item(self, title, subtitle = "", arg = "", valid = "yes", autocomplete = "", icon = "icon.png"):
37 | """
38 | Add item to alfred Feedback
39 |
40 | Args:
41 | title(str): the title displayed by Alfred
42 | Keyword Args:
43 | subtitle(str): the subtitle displayed by Alfred
44 | arg(str): the value returned by alfred when item is selected
45 | valid(str): whether or not the entry can be selected in Alfred to trigger an action
46 | autcomplete(str): the text to be inserted if an invalid item is selected. This is only used if 'valid' is 'no'
47 | icon(str): filename of icon that Alfred will display
48 | """
49 | item = et.SubElement(self.feedback, 'item', uid=str(len(self.feedback)), arg=arg, valid=valid, autocomplete=autocomplete)
50 | _title = et.SubElement(item, 'title')
51 | _title.text = title
52 | _sub = et.SubElement(item, 'subtitle')
53 | _sub.text = subtitle
54 | _icon = et.SubElement(item, 'icon')
55 | _icon.text = icon
56 |
57 | query = '{query}'
58 | url = "http://www.bilibili.com/search?keyword=%s&orderby=&formsubmit="%query
59 | req = urllib2.Request(url = url);
60 | content = urllib2.urlopen(req,timeout = 10).read();
61 | content = zlib.decompress(content, 16+zlib.MAX_WBITS)
62 |
63 | reg = r'
([^<]*)([^<]*)
';
64 | result = re.findall(reg,content,re.S)
65 | fb = Feedback()
66 |
67 | try:
68 | for item in result:
69 | avnum = item[0]
70 | avtype = item[1]
71 | title = item[2].strip()
72 | fb.add_item(title,subtitle="%s : http://www.bilibili.tv/video/%s"%(avtype,avnum),arg=avnum)
73 |
74 | except SyntaxError as e:
75 | if ('EOF', 'EOL' in e.msg):
76 | fb.add_item('...')
77 | else:
78 | fb.add_item('SyntaxError', e.msg)
79 | except Exception as e:
80 | fb.add_item(e.__class__.__name__,subtitle=e.message)
81 | print fb
82 |
--------------------------------------------------------------------------------
/Alfred/BilibiliSearch/Source/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vespa314/bilibili-api/42b6b90aa7c141f5cfb0fdc754435518106f6966/Alfred/BilibiliSearch/Source/icon.png
--------------------------------------------------------------------------------
/Alfred/BilibiliSearch/bilibili.alfredworkflow:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vespa314/bilibili-api/42b6b90aa7c141f5cfb0fdc754435518106f6966/Alfred/BilibiliSearch/bilibili.alfredworkflow
--------------------------------------------------------------------------------
/BiliMerge/BiliMergeFlv.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import subprocess
4 | import os
5 | import sys
6 | import glob
7 |
8 | def merge(folder):
9 | flv_list = sorted(glob.glob('{folder}/*.flv'.format(folder = folder)))
10 | fid = open('%s/filelist.txt' % (folder), 'w')
11 | for idx in flv_list:
12 | fid.write("file '%s/%d.flv'\n" % (folder, idx))
13 | fid.close()
14 |
15 | cmd = ['ffmpeg', '-f', 'concat', '-i', folder+'/'+'filelist.txt','-codec', 'copy', folder+'/'+'output.mp4']
16 | subprocess.Popen(cmd).wait()
17 |
18 | if __name__ == "__main__":
19 | merge(sys.argv[1]);
--------------------------------------------------------------------------------
/BiliMerge/README.md:
--------------------------------------------------------------------------------
1 | ## 说明
2 |
3 | B站手机客户端(安卓)离线下载的视频文件和弹幕文件可以在`/Android/data/tv.danmaku.bili`目录中找到,然后将其拷贝至PC;
4 |
5 | 运行
6 |
7 | ```
8 | BiliMergeFlv.py xxxxxxx
9 | ```
10 |
11 | 其中后面的参数是flv文件所在目录,即可自动统计flv数目,然后实现转换
12 |
13 | ## 环境要求
14 |
15 | 安装有ffmpeg
--------------------------------------------------------------------------------
/GetDanmuAss/README.md:
--------------------------------------------------------------------------------
1 | ## 说明
2 |
3 | 本模块主要可以通过输入B站视频链接获得由弹幕xml文件转换而成的ass字幕文件,供本地视频加载用
4 |
5 | 输入:
6 | av号
7 | 返回:
8 | 在桌面获得视频同名ass文件
9 |
10 | ## 注意
11 | 代码暂时只在MAC系统下测试通过,对于其他系统可以自行研究,至少。。。。。下面这句代码的目标路径你要改一下吧。。。
12 |
13 | ```
14 | Danmaku2ASS(GetDanmuku(video.cid),r'%s/Desktop/%s.ass'%(os.path.expanduser('~'),video.title), 640, 360, 0, 'sans-serif', 15, 0.5, 10, False)
15 | ```
16 | 如果有疑问想交流,可以电邮:`kylensherlock艾特gmail.com`
17 |
18 |
19 | ## 缺陷
20 | 暂时而言字母参数写死了,懒得通过外部修改
21 |
22 | ~~暂时不支持下载P2弹幕。。。后期会加上。。。~~ 【已支持】
23 |
24 | ##鸣谢
25 |
26 | 我只是写了一下B站api获得弹幕,而转换模块基本参考[m13253](https://github.com/m13253)所写的[danmaku2ass](https://github.com/m13253/danmaku2ass)项目!!!
27 |
28 | > 做了些许修改。。。
--------------------------------------------------------------------------------
/GetDanmuAss/biclass.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Wed May 28 01:22:20 2014
4 |
5 | @author: Administrator
6 | """
7 |
8 | class User():
9 | def __init__(self,m_mid=None,m_name=None):
10 | if m_mid:
11 | self.mid = m_mid;
12 | if m_name:
13 | self.name = m_name;
14 | def saveToFile(self,fid):
15 | fid.write('名字:%s\n'%self.name);
16 | fid.write('id:%s\n'%self.mid);
17 | fid.write('是否认证:%s\n'%self.isApprove);
18 | fid.write('空间:%s\n'%self.spaceName);
19 | fid.write('性别:%s\n'%self.sex);
20 | fid.write('账号显示标识:%s\n'%self.rank);
21 | fid.write('头像:%s\n'%self.avatar);
22 | fid.write('关注好友数目:%d\n'%self.follow);
23 | fid.write('粉丝数目:%d\n'%self.fans);
24 | fid.write('投稿数:%d\n'%self.article);
25 | fid.write('地点:%s\n'%self.place);
26 | fid.write('认证信息:%s\n'%self.description);
27 | fid.write('关注好友:\n');
28 | if self.followlist:
29 | for fo in self.followlist:
30 | fid.write('\t%s\n'%fo);
31 | # 获取空间地址
32 | def GetSpace(self):
33 | return 'http://space.bilibili.tv/'+str(self.mid);
34 | mid = None;
35 | name = None;
36 | isApprove = False;#是否是认证账号
37 | spaceName = "";
38 | sex = ""
39 | rank = None;
40 | avatar = None;
41 | follow = 0;#关注好友数目
42 | fans = 0;#粉丝数目
43 | article = 0;#投稿数
44 | place = None;#所在地
45 | description = None;#认证用户为认证信息 普通用户为交友宣言
46 | followlist = None;#关注的好友列表
47 |
48 |
49 | class Video():
50 | def __init__(self,m_aid=None,m_title=None):
51 | if m_aid:
52 | self.aid = m_aid;
53 | if m_title:
54 | self.title = m_title;
55 | # 写到文件中
56 | def saveToFile(self,fid):
57 | fid.write('av号:%d\n'%self.aid);
58 | fid.write('标题:%s\n'%self.title);
59 | fid.write('观看:%d\n'%self.guankan);
60 | fid.write('收藏:%d\n'%self.shoucang);
61 | fid.write('弹幕:%d\n'%self.danmu);
62 | fid.write('日期:%s\n'%self.date);
63 | fid.write('封面地址:%s\n'%self.cover);
64 | fid.write('Up主:\n');
65 | self.author.saveToFile(fid);
66 | fid.write('\n');
67 | aid = None;
68 | title = None;
69 | guankan = None;
70 | shoucang = None;
71 | danmu = None;
72 | date = None;
73 | cover = None;
74 | commentNumber = None;
75 | description = None;
76 | tag = None;
77 | author = None;
78 | page = None;
79 | credit = None;
80 | coin = None;
81 | spid = None;
82 | cid = None;
83 | offsite = None;#Flash播放调用地址
84 | Iscopy = None;
85 | subtitle = None;
86 | duration = None;
87 | episode = None;
88 | #不明:
89 | tid = None;
90 | typename = None;
91 | instant_server = None;
92 | src = None;
93 | partname = None;
94 | #播放信息:
95 | play_site = None;
96 | play_forward = None;
97 | play_mobile = None;
98 |
99 | class Bangumi():
100 | def __init__(self):
101 | pass;
102 | typeid = None;
103 | lastupdate = None;
104 | areaid = None;
105 | bgmcount = None;#番剧当前总集数
106 | title = None;
107 | lastupdate_at = None;
108 | attention = None;
109 | cover = None;
110 | priority = None;
111 | area = None;
112 | weekday = None;
113 | spid = None;
114 | new = None;
115 | scover = None;
116 | mcover = None;
117 | click = None;
118 | season_id = None;
119 |
120 | class Comment():
121 | def __init__(self):
122 | self.post_user = User();
123 | lv = None;#楼层
124 | fbid = None;#评论id
125 | msg = None;
126 | ad_check = None;#状态 (0: 正常 1: UP主隐藏 2: 管理员删除 3: 因举报删除)
127 | post_user = None;
128 |
129 | class CommentList():
130 | def __init__(self):
131 | pass;
132 | comments = None;
133 | commentLen = None;
134 | page = None;
135 |
136 |
--------------------------------------------------------------------------------
/GetDanmuAss/spview danmaku/biclass.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Wed May 28 01:22:20 2014
4 |
5 | @author: Vespa
6 | """
7 |
8 | class User():
9 | def __init__(self,m_mid=None,m_name=None):
10 | if m_mid:
11 | self.mid = m_mid
12 | if m_name:
13 | if isinstance(m_name,unicode):
14 | m_name = m_name.encode('utf8')
15 | self.name = m_name
16 | # 获取空间地址
17 | def GetSpace(self):
18 | return 'http://space.bilibili.tv/'+str(self.mid)
19 | mid = None
20 | name = None
21 | isApprove = None#是否是认证账号
22 | spaceName = None
23 | sex = None
24 | rank = None
25 | avatar = None
26 | follow = None#关注好友数目
27 | fans = None#粉丝数目
28 | article = None#投稿数
29 | place = None#所在地
30 | description = None#认证用户为认证信息 普通用户为交友宣言
31 | followlist = None#关注的好友列表
32 | friend = None
33 | DisplayRank = None
34 |
35 |
36 | class Video():
37 | def __init__(self,m_aid=None,m_title=None):
38 | if m_aid:
39 | self.aid = m_aid
40 | if m_title:
41 | if isinstance(m_title,unicode):
42 | m_title = m_title.encode('utf8')
43 | self.title = m_title
44 | aid = None
45 | title = None
46 | guankan = None
47 | shoucang = None
48 | danmu = None
49 | date = None
50 | cover = None
51 | commentNumber = None
52 | description = None
53 | tag = None
54 | author = None
55 | page = None
56 | credit = None
57 | coin = None
58 | spid = None
59 | cid = None
60 | offsite = None#Flash播放调用地址
61 | Iscopy = None
62 | subtitle = None
63 | duration = None
64 | episode = None
65 | arcurl = None#网页地址
66 | arcrank = None#不明
67 | #不明:
68 | tid = None
69 | typename = None
70 | instant_server = None
71 | src = None
72 | partname = None
73 | allow_bp = None
74 | allow_feed = None
75 | created = None
76 | #播放信息:
77 | play_site = None
78 | play_forward = None
79 | play_mobile = None
80 |
81 | class Bangumi():
82 | def __init__(self):
83 | pass
84 | typeid = None
85 | lastupdate = None
86 | areaid = None
87 | bgmcount = None#番剧当前总集数
88 | title = None
89 | lastupdate_at = None
90 | attention = None #订阅数
91 | cover = None
92 | priority = None
93 | area = None
94 | weekday = None
95 | spid = None
96 | new = None
97 | scover = None
98 | mcover = None
99 | click = None
100 | season_id = None
101 | click = None # 浏览数
102 | video_view = None
103 |
104 | class Comment():
105 | def __init__(self):
106 | self.post_user = User()
107 | lv = None#楼层
108 | fbid = None#评论id
109 | msg = None
110 | ad_check = None#状态 (0: 正常 1: UP主隐藏 2: 管理员删除 3: 因举报删除)
111 | post_user = None
112 |
113 | class CommentList():
114 | def __init__(self):
115 | pass
116 | comments = None
117 | commentLen = None
118 | page = None
119 |
120 | class ZhuantiInfo():
121 | def __init__(self, m_spid,m_title):
122 | self.spid = m_spid
123 | if isinstance(m_title,unicode):
124 | m_title = m_title.encode('utf8')
125 | self.title = m_title
126 | spid = None
127 | title = None
128 | author = None
129 | cover = None
130 | thumb = None
131 | ischeck = None #不明
132 | typeurl = None #总是"http://www.bilibili.com"
133 | tag = None
134 | description = None
135 | pubdate = None # 不明
136 | postdate = None
137 | lastupdate = None
138 | click = None
139 | favourite = None
140 | attention = None
141 | count = None
142 | bgmcount = None
143 | spcount = None
144 | season_id = None
145 | is_bangumi = None
146 | arcurl = None
--------------------------------------------------------------------------------
/GetDanmuAss/spview danmaku/bilibili.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:42:03 2014
4 |
5 | @author: Vespa
6 | """
7 |
8 |
9 | from support import *
10 |
11 | ############################常量定义
12 |
13 | #####排序方式
14 | #收藏
15 | TYPE_SHOUCANG = 'stow'
16 | #评论数
17 | TYPE_PINGLUN = 'review'
18 | #播放数
19 | TYPE_BOFANG = 'hot'
20 | #硬币数
21 | TYPE_YINGBI = 'promote'
22 | #用户评分
23 | TYPE_PINGFEN = 'comment'
24 | #弹幕数
25 | TYPE_DANMU = 'damku'
26 | #拼音
27 | TYPE_PINYIN = 'pinyin'
28 | #投稿时间
29 | TYPE_TOUGAO = 'default'
30 | ############################常量定义结束
31 |
32 | def GetPopularVideo(begintime, endtime, sortType=TYPE_BOFANG, zone=0, page=1, original=0):
33 | """
34 | 输入:
35 | begintime:起始时间,三元数组[year1,month1,day1]
36 | endtime:终止时间,三元数组[year2,month2,day2]
37 | sortType:字符串,排序方式,参照TYPE_开头的常量
38 | zone:整数,分区,参照api.md文档说明
39 | page:整数,页数
40 | 返回:
41 | 视频列表,包含AV号,标题,观看数,收藏数,弹幕数,投稿日期,封面,UP的id号和名字
42 | """
43 | # TYPE_PINYIN和TYPE_TOUGAO情况下zone不可以等于[0,1,3,4,5,36,11,13]
44 | if sortType in [TYPE_PINYIN,TYPE_TOUGAO]:
45 | if zone in [0,1,3,4,5,36,11,13]:
46 | return []
47 | #判断是否原创
48 | if original:
49 | ori = '-original'
50 | else:
51 | ori = ''
52 | url = 'http://www.bilibili.tv/list/%s-%d-%d-%d-%d-%d~%d-%d-%d%s.html'%(sortType,zone,page,begintime[0],begintime[1],begintime[2],endtime[0],endtime[1],endtime[2],ori)
53 | content = getURLContent(url)
54 | return GetVideoFromRate(content)
55 |
56 |
57 | def GetUserInfo(url):
58 | """
59 | 由GetUserInfoBymid(mid)或者GetUserInfoByName(name)调用
60 | 返回:
61 | 用户信息
62 | """
63 | jsoninfo = JsonInfo(url)
64 | user = User(jsoninfo.Getvalue('mid'), jsoninfo.Getvalue('name'))
65 | user.isApprove = jsoninfo.Getvalue('approve')
66 | #b站现在空间名暂时不返回
67 | #user.spaceName = jsoninfo.Getvalue('spacename')
68 | user.sex = jsoninfo.Getvalue('sex')
69 | user.rank = jsoninfo.Getvalue('rank')
70 | user.avatar = jsoninfo.Getvalue('face')
71 | user.follow = jsoninfo.Getvalue('attention')
72 | user.fans = jsoninfo.Getvalue('fans')
73 | user.article = jsoninfo.Getvalue('article')
74 | user.place = jsoninfo.Getvalue('place')
75 | user.description = jsoninfo.Getvalue('description')
76 | user.friend = jsoninfo.Getvalue('friend')
77 | user.DisplayRank = jsoninfo.Getvalue('DisplayRank')
78 | user.followlist = []
79 | for fo in jsoninfo.Getvalue('attentions'):
80 | user.followlist.append(fo)
81 | return user
82 |
83 | def GetUserInfoBymid(mid):
84 | """
85 | 输入:
86 | mid:查询的用户的id
87 | 返回:
88 | 查看GetUserInfo()函数
89 | """
90 | mid = GetString(mid)
91 | url = 'http://api.bilibili.cn/userinfo'+"?mid="+mid
92 | return GetUserInfo(url)
93 |
94 | def GetUserInfoByName(name):
95 | """
96 | 输入:
97 | mid:查询的用户的昵称
98 | 返回:
99 | 查看GetUserInfo()函数
100 | """
101 | name = GetString(name)
102 | url = 'http://api.bilibili.cn/userinfo'+"?user="+name
103 | return GetUserInfo(url)
104 |
105 | def GetVideoOfZhuanti(spid, season_id=None, bangumi=None):
106 | """
107 | 输入:
108 | spid:专题id
109 | season_id:分季ID
110 | bangumi:设置为1返回剧番,不设置或者设置为0返回相关视频
111 | 返回:
112 | 视频列表,包含av号,标题,封面和观看数
113 | """
114 | url = ' http://api.bilibili.cn/spview?spid='+GetString(spid)
115 | if season_id:
116 | url += '&season_id='+GetString(season_id)
117 | if bangumi:
118 | url += '&bangumi='+GetString(bangumi)
119 | jsoninfo = JsonInfo(url)
120 | videolist = []
121 | for video_idx in jsoninfo.Getvalue('list'):
122 | video_idx = DictDecode2UTF8(video_idx)
123 | video = Video(video_idx['aid'],video_idx['title'])
124 | video.cover = video_idx['cover']
125 | video.guankan = video_idx['click']
126 | if video_idx.has_key('episode'):
127 | video.episode = video_idx['episode']
128 | video.src = video_idx["from"]
129 | video.cid = video_idx["cid"]
130 | video.page = video_idx["page"]
131 | videolist.append(video)
132 | return videolist
133 |
134 | def GetComment(aid, page = None, pagesize = None, order = None):
135 | """
136 | 输入:
137 | aid:AV号
138 | page:页码
139 | pagesize:单页返回的记录条数,最大不超过300,默认为10。
140 | order:排序方式 默认按发布时间倒序 可选:good 按点赞人数排序 hot 按热门回复排序
141 | 返回:
142 | 评论列表
143 | """
144 | url = 'http://api.bilibili.cn/feedback?aid='+GetString(aid)
145 | if page:
146 | url += '&page='+GetString(page)
147 | if pagesize:
148 | url += '&pagesize='+GetString(pagesize)
149 | if order:
150 | url += '&order='+GetString(order)
151 | jsoninfo = JsonInfo(url)
152 | commentList = CommentList()
153 | commentList.comments = []
154 | commentList.commentLen = jsoninfo.Getvalue('totalResult')
155 | commentList.page = jsoninfo.Getvalue('pages')
156 | idx = 0
157 | while jsoninfo.Getvalue(str(idx)):
158 | liuyan = Comment()
159 | liuyan.lv = jsoninfo.Getvalue(str(idx),'lv')
160 | liuyan.fbid = jsoninfo.Getvalue(str(idx),'fbid')
161 | liuyan.msg = jsoninfo.Getvalue(str(idx),'msg')
162 | liuyan.ad_check = jsoninfo.Getvalue(str(idx),'ad_check')
163 | liuyan.post_user.mid = jsoninfo.Getvalue(str(idx),'mid')
164 | liuyan.post_user.avatar = jsoninfo.Getvalue(str(idx),'face')
165 | liuyan.post_user.rank = jsoninfo.Getvalue(str(idx),'rank')
166 | liuyan.post_user.name = jsoninfo.Getvalue(str(idx),'nick')
167 | commentList.comments.append(liuyan)
168 | idx += 1
169 | return commentList
170 |
171 | def GetAllComment(aid, order = None):
172 | """
173 | 获取一个视频全部评论,有可能需要多次爬取,所以会有较大耗时
174 | 输入:
175 | aid:AV号
176 | order:排序方式 默认按发布时间倒序 可选:good 按点赞人数排序 hot 按热门回复排序
177 | 返回:
178 | 评论列表
179 | """
180 | MaxPageSize = 300
181 | commentList = GetComment(aid=aid, pagesize=MaxPageSize, order=order)
182 | if commentList.page == 1:
183 | return commentList
184 | for p in range(2,commentList.page+1):
185 | t_commentlist = GetComment(aid=aid,pagesize=MaxPageSize,page=p,ver=ver,order=order)
186 | for liuyan in t_commentlist.comments:
187 | commentList.comments.append(liuyan)
188 | time.sleep(0.5)
189 | return commentList
190 |
191 | def GetVideoInfo(aid, appkey,page = 1, AppSecret=None, fav = None):
192 | """
193 | 获取视频信息
194 | 输入:
195 | aid:AV号
196 | page:页码
197 | fav:是否读取会员收藏状态 (默认 0)
198 | """
199 | paras = {'id': GetString(aid),'page': GetString(page)}
200 | if fav:
201 | paras['fav'] = fav
202 | url = 'http://api.bilibili.cn/view?'+GetSign(paras,appkey,AppSecret)
203 | jsoninfo = JsonInfo(url)
204 | video = Video(aid,jsoninfo.Getvalue('title'))
205 | video.guankan = jsoninfo.Getvalue('play')
206 | video.commentNumber = jsoninfo.Getvalue('review')
207 | video.danmu = jsoninfo.Getvalue('video_review')
208 | video.shoucang = jsoninfo.Getvalue('favorites')
209 | video.description = jsoninfo.Getvalue('description')
210 | video.tag = []
211 | taglist = jsoninfo.Getvalue('tag')
212 | if taglist:
213 | for tag in taglist.split(','):
214 | video.tag.append(tag)
215 | video.cover = jsoninfo.Getvalue('pic')
216 | video.author = User(jsoninfo.Getvalue('mid'),jsoninfo.Getvalue('author'))
217 | video.page = jsoninfo.Getvalue('pages')
218 | video.date = jsoninfo.Getvalue('created_at')
219 | video.credit = jsoninfo.Getvalue('credit')
220 | video.coin = jsoninfo.Getvalue('coins')
221 | video.spid = jsoninfo.Getvalue('spid')
222 | video.cid = jsoninfo.Getvalue('cid')
223 | video.offsite = jsoninfo.Getvalue('offsite')
224 | video.partname = jsoninfo.Getvalue('partname')
225 | video.src = jsoninfo.Getvalue('src')
226 | video.tid = jsoninfo.Getvalue('tid')
227 | video.typename = jsoninfo.Getvalue('typename')
228 | video.instant_server = jsoninfo.Getvalue('instant_server')
229 | ## 以下三个意义不明。。
230 | # video.allow_bp = jsoninfo.Getvalue('allow_bp')
231 | # video.allow_feed = jsoninfo.Getvalue('allow_feed')
232 | # video.created = jsoninfo.Getvalue('created')
233 | return video
234 |
235 |
236 | def GetBangumi(appkey, btype = None, weekday = None, AppSecret=None):
237 | """
238 | 获取新番信息
239 | 输入:
240 | btype:番剧类型 2: 二次元新番 3: 三次元新番 默认(0):所有
241 | weekday:周一:1 周二:2 ...周六:6
242 | """
243 | paras = {}
244 | if btype != None and btype in [2,3]:
245 | paras['btype'] = GetString(btype)
246 | if weekday != None:
247 | paras['weekday'] = GetString(weekday)
248 | url = 'http://api.bilibili.cn/bangumi?' + GetSign(paras, appkey, AppSecret)
249 | jsoninfo = JsonInfo(url)
250 | bangumilist = []
251 | if jsoninfo.Getvalue('code') != 0:
252 | print jsoninfo.Getvalue('error')
253 | return bangumilist
254 | for bgm in jsoninfo.Getvalue('list'):
255 | bangumi = Bangumi()
256 | bgm = DictDecode2UTF8(bgm)
257 | bangumi.typeid = bgm['typeid']
258 | bangumi.lastupdate = bgm['lastupdate']
259 | bangumi.areaid = bgm['areaid']
260 | bangumi.bgmcount = getint(bgm['bgmcount'])
261 | bangumi.title = bgm['title']
262 | bangumi.lastupdate_at = bgm['lastupdate_at']
263 | bangumi.attention = bgm['attention']
264 | bangumi.cover = bgm['cover']
265 | bangumi.priority = bgm['priority']
266 | bangumi.area = bgm['area']
267 | bangumi.weekday = bgm['weekday']
268 | bangumi.spid = bgm['spid']
269 | bangumi.new = bgm['new']
270 | bangumi.scover = bgm['scover']
271 | bangumi.mcover = bgm['mcover']
272 | bangumi.click = bgm['click']
273 | bangumi.season_id = bgm['season_id']
274 | bangumi.click = bgm['click']
275 | bangumi.video_view = bgm['video_view']
276 | bangumilist.append(bangumi)
277 | return bangumilist
278 |
279 | def biliVideoSearch(appkey, AppSecret, keyword, order = 'default', pagesize = 20, page = 1):
280 | """
281 | 【注】:
282 | 旧版Appkey不可用,必须配合AppSecret使用!!
283 |
284 | 根据关键词搜索视频
285 | 输入:
286 | order:排序方式 默认default,其余待测试
287 | keyword:关键词
288 | pagesize:返回条目多少
289 | page:页码
290 | """
291 | paras = {}
292 | paras['keyword'] = GetString(keyword)
293 | paras['order'] = GetString(order)
294 | paras['pagesize'] = GetString(pagesize)
295 | paras['page'] = GetString(page)
296 | url = 'http://api.bilibili.cn/search?' + GetSign(paras, appkey, AppSecret)
297 | jsoninfo = JsonInfo(url)
298 | videolist = []
299 | for video_idx in jsoninfo.Getvalue('result'):
300 | if video_idx['type'] != 'video':
301 | continue
302 | video_idx = DictDecode2UTF8(video_idx)
303 | video = Video(video_idx['aid'], video_idx['title'])
304 | video.typename = video_idx['typename']
305 | video.author = User(video_idx['mid'], video_idx['author'])
306 | video.acurl = video_idx['arcurl']
307 | video.description = video_idx['description']
308 | video.arcrank = video_idx['arcrank']
309 | video.cover = video_idx['pic']
310 | video.guankan = video_idx['play']
311 | video.danmu = video_idx['video_review']
312 | video.shoucang = video_idx['favorites']
313 | video.commentNumber = video_idx['review']
314 | video.date = video_idx['pubdate']
315 | video.tag = video_idx['tag'].split(',')
316 | videolist.append(video)
317 | return videolist
318 |
319 | def biliZhuantiSearch(appkey, AppSecret, keyword):
320 | """
321 | 根据关键词搜索专题
322 | 输入:
323 | keyword:关键词
324 | """
325 | paras = {}
326 | paras['keyword'] = GetString(keyword)
327 | url = 'http://api.bilibili.cn/search?' + GetSign(paras, appkey, AppSecret)
328 | jsoninfo = JsonInfo(url)
329 | zhuantiList = []
330 | for zhuanti_idx in jsoninfo.Getvalue('result'):
331 | if zhuanti_idx['type'] != 'special':
332 | continue
333 | zhuanti_idx = DictDecode2UTF8(zhuanti_idx)
334 | zhuanti = ZhuantiInfo(zhuanti_idx['spid'], zhuanti_idx['title'])
335 | zhuanti.author = User(zhuanti_idx['mid'], zhuanti_idx['author'])
336 | zhuanti.cover = zhuanti_idx['pic']
337 | zhuanti.thumb = zhuanti_idx['thumb']
338 | zhuanti.ischeck = zhuanti_idx['ischeck']
339 | zhuanti.tag = zhuanti_idx['tag'].split(',')
340 | zhuanti.description = zhuanti_idx['description']
341 | zhuanti.pubdate = zhuanti_idx['pubdate']
342 | zhuanti.postdate = zhuanti_idx['postdate']
343 | zhuanti.lastupdate = zhuanti_idx['lastupdate']
344 | zhuanti.click = zhuanti_idx['click']
345 | zhuanti.favourite = zhuanti_idx['favourite']
346 | zhuanti.attention = zhuanti_idx['attention']
347 | zhuanti.count = zhuanti_idx['count']
348 | zhuanti.bgmcount = zhuanti_idx['bgmcount']
349 | zhuanti.spcount = zhuanti_idx['spcount']
350 | zhuanti.season_id = zhuanti_idx['season_id']
351 | zhuanti.is_bangumi = zhuanti_idx['is_bangumi']
352 | zhuanti.arcurl = zhuanti_idx['arcurl']
353 | zhuantiList.append(zhuanti)
354 | return zhuantiList
355 |
356 | #def GetBangumiByTime(year, month):
357 | # url='http://www.bilibili.tv/index/bangumi/%s-%s.json'%(GetString(year),GetString(month))
358 | # print url
359 | # jsoninfo = getURLContent(url)
360 | # print jsoninfo
361 |
362 | def GetRank(appkey, tid, begin=None, end=None, page = None, pagesize=None, click_detail =None, order = None, AppSecret=None):
363 | """
364 | 获取排行信息
365 | 输入:
366 | 详见https://github.com/Vespa314/bilibili-api/blob/master/api.md
367 | 输出:
368 | 详见https://github.com/Vespa314/bilibili-api/blob/master/api.md
369 | """
370 | paras = {}
371 | paras['appkey']=appkey
372 | paras['tid']=GetString(tid)
373 | if order:
374 | paras['order']=order
375 | if click_detail:
376 | paras['click_detail']=click_detail
377 | if pagesize:
378 | paras['pagesize']=GetString(pagesize)
379 | if begin != None and len(begin)==3:
380 | paras['begin']='%d-%d-%d'%(begin[0],begin[1],begin[2])
381 | if end != None and len(end)==3:
382 | paras['end']='%d-%d-%d'%(end[0],end[1],end[2])
383 | if page:
384 | paras['page']=GetString(page)
385 | if click_detail:
386 | paras['click_detail'] = click_detail
387 | url = 'http://api.bilibili.cn/list?' + GetSign(paras,appkey,AppSecret)
388 | jsoninfo = JsonInfo(url)
389 | videolist = []
390 | if jsoninfo.Getvalue('code') != 0:
391 | print jsoninfo.Getvalue('error')
392 | return videolist
393 | page = jsoninfo.Getvalue('pages')
394 | name = jsoninfo.Getvalue('name')
395 | for i in range(len(jsoninfo.Getvalue('list'))-1):
396 | idx = str(i)
397 | video = Video(jsoninfo.Getvalue('list',idx,'aid'),jsoninfo.Getvalue('list',idx,'title'))
398 | video.Iscopy = jsoninfo.Getvalue('list',idx,'copyright')
399 | video.tid = jsoninfo.Getvalue('list',idx,'typeid')
400 | video.typename = jsoninfo.Getvalue('list',idx,'typename')
401 | video.subtitle = jsoninfo.Getvalue('list',idx,'subtitle')
402 | video.guankan = jsoninfo.Getvalue('list',idx,'play')
403 | # video.commentNumber = jsoninfo.Getvalue('list',idx,'review')
404 | video.danmu = jsoninfo.Getvalue('list',idx,'video_review')
405 | video.shoucang = jsoninfo.Getvalue('list',idx,'favorites')
406 | video.author = User(jsoninfo.Getvalue('list',idx,'mid'),jsoninfo.Getvalue('list',idx,'author'))
407 | video.description = jsoninfo.Getvalue('list',idx,'description')
408 | video.date = jsoninfo.Getvalue('list',idx,'create')
409 | video.cover = jsoninfo.Getvalue('list',idx,'pic')
410 | video.credit = jsoninfo.Getvalue('list',idx,'credit')
411 | video.coin = jsoninfo.Getvalue('list',idx,'coins')
412 | video.commentNumber = jsoninfo.Getvalue('list',idx,'comment')
413 | video.duration = jsoninfo.Getvalue('list',idx,'duration')
414 | if click_detail != None:
415 | video.play_site = jsoninfo.Getvalue('list',idx,'play_site')
416 | video.play_forward = jsoninfo.Getvalue('list',idx,'play_forward')
417 | video.play_mobile = jsoninfo.Getvalue('list',idx,'play_mobile')
418 | videolist.append(video)
419 | return [page,name,videolist]
420 |
421 | def GetBilibiliUrl(url, appkey, AppSecret=None):
422 | overseas=False
423 | url_get_media = 'http://interface.bilibili.com/playurl?' if not overseas else 'http://interface.bilibili.com/v_cdn_play?'
424 | regex_match = re.findall('http:/*[^/]+/video/av(\\d+)(/|/index.html|/index_(\\d+).html)?(\\?|#|$)',url)
425 | if not regex_match:
426 | return []
427 | aid = regex_match[0][0]
428 | pid = regex_match[0][2] or '1'
429 | video = GetVideoInfo(aid,appkey,pid,AppSecret)
430 | cid = video.cid
431 | media_args = {'cid': cid,'quality':4}
432 | resp_media = getURLContent(url_get_media+GetSign(media_args,appkey,AppSecret))
433 | media_urls = [str(k.wholeText).strip() for i in xml.dom.minidom.parseString(resp_media.decode('utf-8', 'replace')).getElementsByTagName('durl') for j in i.getElementsByTagName('url')[:1] for k in j.childNodes if k.nodeType == 4]
434 | return media_urls
435 |
--------------------------------------------------------------------------------
/GetDanmuAss/spview danmaku/main.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | @author: Vespa
4 | """
5 |
6 | import sys
7 | import os
8 | from bilibili import *
9 | from GetAssDanmaku import *
10 | def main(argv):
11 | appkey = '70472776da900153'
12 | secretkey = 'f7d9146f9363f3407d31098918493336'
13 | SPList = biliZhuantiSearch(appkey,secretkey,argv)
14 | if 0 == len(SPList):
15 | print "【Error】SPview Not Found!!"
16 | return
17 | for idx,sp in enumerate(SPList):
18 | print "[%d]:%s(spid = %d)"%(idx+1,sp.title,getint(sp.spid))
19 | choise = int(raw_input("请选择专题:"))-1
20 |
21 | if choise < 0 or choise >= len(SPList):
22 | print "【Error】Range Error"
23 | return
24 | else:
25 | print "\n"
26 |
27 | print "【Info】Getting Video info of %s"%(SPList[choise].title)
28 | videoList = GetVideoOfZhuanti(SPList[choise].spid,SPList[choise].season_id,1)
29 | if len(videoList) == 0:
30 | print "【Error】Vedio Not Found!!"
31 | return
32 |
33 | # fid = open('%s.rule'%(SPList[choise].title),'w')
34 | # for video in videoList:
35 | # url= "http://www.bilibili.com/video/av%d/"%(video.aid)
36 | # # print video.title
37 | # for mediaurl in GetBilibiliUrl(url,appkey,secretkey):
38 | # print mediaurl
39 | # filename = GetRE(mediaurl,'[^\.|/]+\.(flv|hlv)')
40 | # fid.write('%s->%s'%(filename[0],video.title))
41 | # fid.close()
42 | # 视频合并待实现
43 |
44 | for video in videoList:
45 | Danmaku2ASS(GetDanmuku(video.cid),r'%s/Desktop/%s.ass'%(os.path.expanduser('~'),video.title.replace(r'/','')), 640, 360, 0, 'sans-serif', 15, 0.5, 10, False)
46 | print "%s Download Finished!"%(video.title)
47 | time.sleep(1)
48 |
49 | if __name__ == "__main__":
50 | if len(sys.argv) == 1:
51 | print "【Error】python main.py xxx"
52 | else:
53 | main(sys.argv[1])
--------------------------------------------------------------------------------
/GetDanmuAss/spview danmaku/support.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:59:09 2014
4 |
5 | @author: Vespa
6 | """
7 | import urllib2
8 | import urllib
9 | import re
10 | import json
11 | import zlib
12 | import gzip
13 | import xml.dom.minidom
14 | import hashlib
15 | from biclass import *
16 | import time
17 | def GetRE(content,regexp):
18 | return re.findall(regexp, content)
19 |
20 | def getURLContent(url):
21 | while True:
22 | flag = 1
23 | try:
24 | headers = {'User-Agent':'Mozilla/5.0 (Windows U Windows NT 6.1 en-US rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
25 | req = urllib2.Request(url = url,headers = headers)
26 | content = urllib2.urlopen(req).read()
27 | except:
28 | flag = 0
29 | time.sleep(5)
30 | if flag == 1:
31 | break
32 | return content
33 |
34 | class JsonInfo():
35 | def __init__(self,url):
36 | self.info = json.loads(getURLContent(url))
37 | if self.info.has_key('code') and self.info['code'] != 0:
38 | if self.info.has_key('message'):
39 | print "【Error】code=%d, msg=%s, url=%s"%(self.info['code'],self.Getvalue('message'),url)
40 | elif self.info.has_key('error'):
41 | print "【Error】code=%d, msg=%s, url=%s"%(self.info['code'],self.Getvalue('error'),url)
42 | error = True
43 | def Getvalue(self,*keys):
44 | if len(keys) == 0:
45 | return None
46 | if self.info.has_key(keys[0]):
47 | temp = self.info[keys[0]]
48 | else:
49 | return None
50 | if len(keys) > 1:
51 | for key in keys[1:]:
52 | if temp.has_key(key):
53 | temp = temp[key]
54 | else:
55 | return None
56 | if isinstance(temp,unicode):
57 | temp = temp.encode('utf8')
58 | return temp
59 | info = None
60 | error = False
61 |
62 | def GetString(t):
63 | if type(t) == int:
64 | return str(t)
65 | return t
66 |
67 | def getint(string):
68 | try:
69 | i = int(string)
70 | except:
71 | i = 0
72 | return i
73 |
74 | def DictDecode2UTF8(dict):
75 | for keys in dict:
76 | if isinstance(dict[keys],unicode):
77 | dict[keys] = dict[keys].encode('utf8')
78 | return dict
79 |
80 | def GetVideoFromRate(content):
81 | """
82 | 从视频搜索源码页面提取视频信息
83 | """
84 | #av号和标题
85 | regular1 = r'
]*>([^/]+)'
86 | info1 = GetRE(content,regular1)
87 | #观看数
88 | regular2 = r'
]*>(.+)'
89 | info2 = GetRE(content,regular2)
90 | #收藏
91 | regular3 = r'
]*>(.+)'
92 | info3 = GetRE(content,regular3)
93 | #弹幕
94 | regular4 = r'
]*>(.+)'
95 | info4 = GetRE(content,regular4)
96 | #日期
97 | regular5 = r'
(\d+-\d+-\d+ \d+:\d+)'
98 | info5 = GetRE(content,regular5)
99 | #封面
100 | regular6 = r'
)
]*>'
101 | info6 = GetRE(content,regular6)
102 | #Up的id和名字
103 | regular7 = r'
(.*)'
104 | info7 = GetRE(content,regular7)
105 | #!!!!!!!!这里可以断言所有信息长度相等
106 | videoNum = len(info1)#视频长度
107 | videoList = []
108 | for i in range(videoNum):
109 | video_t = Video()
110 | video_t.aid = getint(info1[i][0])
111 | video_t.title = info1[i][1]
112 | video_t.guankan = getint(info2[i])
113 | video_t.shoucang = getint(info3[i])
114 | video_t.danmu = getint(info4[i])
115 | video_t.date = info5[i]
116 | video_t.cover = info6[i]
117 | video_t.author = User(info7[i][0],info7[i][1])
118 | videoList.append(video_t)
119 | return videoList
120 |
121 | def GetSign(params, appkey, AppSecret=None):
122 | """
123 | 获取新版API的签名,不然会返回-3错误
124 | 待添加:【重要!】
125 | 需要做URL编码并保证字母都是大写,如 %2F
126 | """
127 | params['appkey']=appkey
128 | data = ""
129 | paras = params.keys()
130 | paras.sort()
131 | data = urllib.urlencode(params)
132 | # for para in paras:
133 | # if data != "":
134 | # data += "&"
135 | # data += para + "=" + str(params[para])
136 | if AppSecret == None:
137 | return data
138 | m = hashlib.md5()
139 | m.update(data+AppSecret)
140 | return data+'&sign='+m.hexdigest()
--------------------------------------------------------------------------------
/GetDanmuAss/support.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:59:09 2014
4 |
5 | @author: Administrator
6 | """
7 | import urllib2
8 | import re
9 | import json
10 | import zlib
11 | from biclass import *
12 | import time
13 | def GetRE(content,regexp):
14 | return re.findall(regexp, content)
15 |
16 | def getURLContent(url):
17 | while True:
18 | flag = 1;
19 | try:
20 | headers = {'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
21 | req = urllib2.Request(url = url,headers = headers);
22 | content = urllib2.urlopen(req).read();
23 | except:
24 | flag = 0;
25 | time.sleep(5)
26 | if flag == 1:
27 | break;
28 | return content;
29 |
30 | #def FromJson(url):
31 | # return json.loads(getURLContent(url))
32 |
33 | class JsonInfo():
34 | def __init__(self,url):
35 | self.info = json.loads(getURLContent(url));
36 | def Getvalue(self,*keys):
37 | if len(keys) == 0:
38 | return None
39 | if self.info.has_key(keys[0]):
40 | temp = self.info[keys[0]];
41 | else:
42 | return None;
43 | if len(keys) > 1:
44 | for key in keys[1:]:
45 | if temp.has_key(key):
46 | temp = temp[key]
47 | else:
48 | return None;
49 | return temp
50 | info = None;
51 |
52 | def GetString(t):
53 | if type(t) == int:
54 | return str(t)
55 | return t
56 |
57 | def getint(string):
58 | try:
59 | i = int(string)
60 | except:
61 | i = 0
62 | return i
63 |
64 | #从视频源码获取视频信息
65 | def GetVideoFromRate(content):
66 | #av号和标题
67 | regular1 = r'
([^/]+)';
68 | info1 = GetRE(content,regular1)
69 | #观看数
70 | regular2 = r'
(.+)';
71 | info2 = GetRE(content,regular2)
72 | #收藏
73 | regular3 = r'
(.+)';
74 | info3 = GetRE(content,regular3)
75 | #弹幕
76 | regular4 = r'
(.+)';
77 | info4 = GetRE(content,regular4)
78 | #日期
79 | regular5 = r'
(\d+-\d+-\d+ \d+:\d+)';
80 | info5 = GetRE(content,regular5)
81 | #封面
82 | regular6 = r'
)
';
83 | info6 = GetRE(content,regular6)
84 | #Up的id和名字
85 | regular7 = r'
(.+)'
86 | info7 = GetRE(content,regular7)
87 | #!!!!!!!!这里可以断言所有信息长度相等
88 | videoNum = len(info1);#视频长度
89 | videoList = [];
90 | for i in range(videoNum):
91 | video_t = Video();
92 | video_t.aid = getint(info1[i][0]);
93 | video_t.title = info1[i][1];
94 | video_t.guankan = getint(info2[i]);
95 | video_t.shoucang = getint(info3[i]);
96 | video_t.danmu = getint(info4[i]);
97 | video_t.date = info5[i];
98 | video_t.cover = info6[i];
99 | video_t.author = User(info7[i][0],info7[i][1])
100 | videoList.append(video_t);
101 | return videoList
102 |
--------------------------------------------------------------------------------
/GetVideoUrl/biliDownLoad.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | import sys
4 | import gzip
5 | import json
6 | import hashlib
7 | import re
8 | import urllib2
9 | import xml.dom.minidom
10 | import zlib
11 |
12 | USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36'
13 | APPKEY = '85eb6835b0a1034e'
14 | APPSEC = '2ad42749773c441109bdc0191257a664'
15 |
16 | def GetBilibiliUrl(url):
17 | overseas=False
18 | url_get_media = 'http://interface.bilibili.com/playurl?' if not overseas else 'http://interface.bilibili.com/v_cdn_play?'
19 | regex_match = re.findall('http:/*[^/]+/video/av(\\d+)(/|/index.html|/index_(\\d+).html)?(\\?|#|$)',url)
20 | if not regex_match:
21 | raise ValueError('Invalid URL: %s' % url)
22 | aid = regex_match[0][0]
23 | pid = regex_match[0][2] or '1'
24 | cid_args = {'type': 'json', 'id': aid, 'page': pid}
25 | resp_cid = urlfetch('http://api.bilibili.com/view?'+GetSign(cid_args,APPKEY,APPSEC))
26 | resp_cid = dict(json.loads(resp_cid.decode('utf-8', 'replace')))
27 | cid = resp_cid.get('cid')
28 | media_args = {'otype': 'json', 'cid': cid, 'type': 'mp4', 'quality': 4, 'appkey': APPKEY}
29 | resp_media = urlfetch(url_get_media+GetSign(media_args,APPKEY,APPSEC))
30 | resp_media = dict(json.loads(resp_media.decode('utf-8', 'replace')))
31 | res = []
32 | for media_url in resp_media.get('durl'):
33 | res.append(media_url.get('url'))
34 | return res
35 |
36 | def GetSign(params,appkey,AppSecret=None):
37 | params['appkey']=appkey
38 | data = ""
39 | paras = sorted(params)
40 | paras.sort()
41 | for para in paras:
42 | if data != "":
43 | data += "&"
44 | data += para + "=" + str(params[para])
45 | if AppSecret == None:
46 | return data
47 | m = hashlib.md5()
48 | m.update((data+AppSecret).encode('utf-8'))
49 | return data+'&sign='+m.hexdigest()
50 |
51 | def urlfetch(url):
52 | req_headers = {'User-Agent': USER_AGENT}
53 | req = urllib2.Request(url=url, headers=req_headers)
54 | return urllib2.urlopen(req).read()
55 |
56 | if __name__ == '__main__':
57 | if len(sys.argv) == 1:
58 | print('输入视频播放地址')
59 | else:
60 | media_urls = GetBilibiliUrl(sys.argv[1])
61 | for media_url in media_urls:
62 | print media_url
63 |
--------------------------------------------------------------------------------
/GetVideoUrl/biliurl:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # copy this script to /usr/bin/
3 | # usage:
4 | # biliurl http://www.bilibili.com/video/avxxxx/
5 | # the download url will be automatically copied to clipboard
6 |
7 | ~/danmaku2ass/biliDownLoad.py $@ | pbcopy
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Vespa
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ##B站API收集整理及开发,测试【开发中】
2 | ============
3 |
4 | ### 目录:
5 | * python API/:python版本API
6 | * bilibili-po/:测试爬取B站up的关注关系网,以便后期分析【已完成】
7 | * bilibili-po/爬取结果:爬取的原始数据,包括每一个up的id,昵称,投稿数,粉丝数以及关注列表
8 | * bilibili-po/分析:分析爬取的数据的python代码和Mathematica代码
9 | * bilibili-video/:爬取B站所有视频信息【已完成,数据暂不公开】
10 | * bili-monitor/:监视B站新番各种数据脚本【已完成】
11 | * Alfred/:几个基于此API开发的Workflow,此处不再更新,具体参见[Github](https://github.com/Vespa314/AlfredWorkFlows)【已完成】
12 | * GetDanmuAss/:通过输入av号获得本地弹幕播放用的ASS文件【已完成】
13 | * spview danmaku/:批量获取专题弹幕文件【已完成】
14 | * GetVideoUrl/:输入视频URL地址获得下载URL(改造自[biligrab](https://github.com/m13253/biligrab-danmaku2ass)】)【已完成】
15 | * BiliMerge/:随手写的合并来自B站手机客户端离线下载的视频【已完成】
16 | * danmu-Delay/:随手写的弹幕字幕文件延时。。【已完成】
17 | * bili_live_guaji/:直播经验挂机脚本【已完成】
18 |
19 | ### 文件:
20 | * api.md :API的详细说明
21 | * README.md:return this
22 |
23 | ###主要三部分API组成:
24 | * 根据爬取页面获取到的信息:
25 | * 视频排行【已完成】
26 | * 根据条件筛选视频
27 | * 按年份月份获取动画新番信息
28 | * 无需认证的API接口获取:
29 | * 获取各个板块本周最火视频
30 | * 读取视频评论【已完成】
31 | * 读取专题信息
32 | * 获取专题视频信息【已完成】
33 | * 获取用户信息【已完成】
34 | * 需要appkey才可以获得的信息:
35 | * 获取视频信息【已完成】
36 | * 获取新番信息【已完成】
37 | * 获取排行视频信息【已完成】
38 | * ...
39 |
40 | ###类接口:
41 |
42 | ####用户类:
43 | ```python
44 | class User():
45 | def __init__(self,m_mid=None,m_name=None):
46 | if m_mid:
47 | self.mid = m_mid;
48 | if m_name:
49 | self.name = m_name;
50 | mid = None;
51 | name = None;
52 | isApprove = False;#是否是认证账号
53 | spaceName = "";
54 | sex = ""
55 | rank = None;
56 | avatar = None;
57 | follow = 0;#关注好友数目
58 | fans = 0;#粉丝数目
59 | article = 0;#投稿数
60 | place = None;#所在地
61 | description = None;#认证用户为认证信息 普通用户为交友宣言
62 | followlist = None;#关注的好友列表
63 | ```
64 |
65 | ####视频类:
66 | ```python
67 | class Video():
68 | def __init__(self,m_aid=None,m_title=None):
69 | if m_aid:
70 | self.aid = m_aid;
71 | if m_title:
72 | self.title = m_title;
73 | aid = None;
74 | title = None;
75 | guankan = None;
76 | shoucang = None;
77 | danmu = None;
78 | date = None;
79 | cover = None;
80 | commentNumber = None;
81 | description = None;
82 | tag = None;
83 | author = None;
84 | page = None;
85 | credit = None;
86 | coin = None;
87 | spid = None;
88 | cid = None;
89 | offsite = None;#Flash播放调用地址
90 | Iscopy = None;
91 | subtitle = None;
92 | duration = None;
93 | episode = None;
94 | arcurl = None;#网页地址
95 | arcrank = None;#不明
96 | #不明:
97 | tid = None;
98 | typename = None;
99 | instant_server = None;
100 | src = None;
101 | partname = None;
102 | #播放信息:
103 | play_site = None;
104 | play_forward = None;
105 | play_mobile = None;
106 | ```
107 |
108 | ####评论类:
109 | ```
110 | class Comment():
111 | def __init__(self):
112 | self.post_user = User();
113 | lv = None;#楼层
114 | fbid = None;#评论id
115 | msg = None;
116 | ad_check = None;#状态 (0: 正常 1: UP主隐藏 2: 管理员删除 3: 因举报删除)
117 | post_user = None;
118 | ```
119 |
120 | ####评论组(一组评论):
121 | ```
122 | class CommentList():
123 | def __init__(self):
124 | pass;
125 | comments = None;
126 | commentLen = None;
127 | page = None;
128 | ```
129 |
130 | ####新番类:
131 | ```
132 | class Bangumi():
133 | def __init__(self):
134 | pass;
135 | typeid = None;
136 | lastupdate = None;
137 | areaid = None;
138 | bgmcount = None;#番剧当前总集数
139 | title = None;
140 | lastupdate_at = None;
141 | attention = None;
142 | cover = None;
143 | priority = None;
144 | area = None;
145 | weekday = None;
146 | spid = None;
147 | new = None;
148 | scover = None;
149 | mcover = None;
150 | click = None;
151 | ```
152 |
153 | 专题类
154 | ```
155 | class ZhuantiInfo():
156 | def __init__(self, m_spid,m_title):
157 | self.spid = m_spid
158 | self.title = m_title
159 | spid = None
160 | title = None
161 | author = None
162 | cover = None
163 | thumb = None
164 | ischeck = None #不明
165 | typeurl = None #总是”http://www.bilibili.com”
166 | tag = None
167 | description = None
168 | pubdate = None # 不明
169 | postdate = None
170 | lastupdate = None
171 | click = None
172 | favorite = None
173 | attention = None
174 | count = None
175 | bgmcount = None
176 | spcount = None
177 | season_id = None
178 | is_bangumi = None
179 | arcurl = None
180 | ```
181 |
182 | 弹幕类:
183 | ```
184 | class Danmu():
185 | def __init__(self):
186 | pass
187 | t_video = None
188 | t_stamp = None
189 | mid_crc = None # 值为:hex(binascii.crc32(mid))
190 | danmu_type = None # 1:滚动弹幕 5:顶端弹幕 4:底部弹幕
191 | content = None
192 | danmu_color = None
193 | ```
--------------------------------------------------------------------------------
/bili-monitor/biclass.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Wed May 28 01:22:20 2014
4 |
5 | @author: Vespa
6 | """
7 |
8 | class User():
9 | def __init__(self,m_mid=None,m_name=None):
10 | if m_mid:
11 | self.mid = m_mid
12 | if m_name:
13 | if isinstance(m_name,unicode):
14 | m_name = m_name.encode('utf8')
15 | self.name = m_name
16 | # 获取空间地址
17 | def GetSpace(self):
18 | return 'http://space.bilibili.tv/'+str(self.mid)
19 | mid = None
20 | name = None
21 | isApprove = None#是否是认证账号
22 | spaceName = None
23 | sex = None
24 | rank = None
25 | avatar = None
26 | follow = None#关注好友数目
27 | fans = None#粉丝数目
28 | article = None#投稿数
29 | place = None#所在地
30 | description = None#认证用户为认证信息 普通用户为交友宣言
31 | followlist = None#关注的好友列表
32 | friend = None
33 | DisplayRank = None
34 |
35 |
36 | class Video():
37 | def __init__(self,m_aid=None,m_title=None):
38 | if m_aid:
39 | self.aid = m_aid
40 | if m_title:
41 | if isinstance(m_title,unicode):
42 | m_title = m_title.encode('utf8')
43 | self.title = m_title
44 | aid = None
45 | title = None
46 | guankan = None
47 | shoucang = None
48 | danmu = None
49 | date = None
50 | cover = None
51 | commentNumber = None
52 | description = None
53 | tag = None
54 | author = None
55 | page = None
56 | credit = None
57 | coin = None
58 | spid = None
59 | cid = None
60 | offsite = None#Flash播放调用地址
61 | Iscopy = None
62 | subtitle = None
63 | duration = None
64 | episode = None
65 | arcurl = None#网页地址
66 | arcrank = None#不明
67 | #不明:
68 | tid = None
69 | typename = None
70 | instant_server = None
71 | src = None
72 | partname = None
73 | allow_bp = None
74 | allow_feed = None
75 | created = None
76 | #播放信息:
77 | play_site = None
78 | play_forward = None
79 | play_mobile = None
80 |
81 | class Bangumi():
82 | def __init__(self):
83 | pass
84 | typeid = None
85 | lastupdate = None
86 | areaid = None
87 | bgmcount = None#番剧当前总集数
88 | title = None
89 | lastupdate_at = None
90 | attention = None #订阅数
91 | cover = None
92 | priority = None
93 | area = None
94 | weekday = None
95 | spid = None
96 | new = None
97 | scover = None
98 | mcover = None
99 | click = None
100 | season_id = None
101 | click = None # 浏览数
102 | video_view = None
103 |
104 | class Comment():
105 | def __init__(self):
106 | self.post_user = User()
107 | lv = None#楼层
108 | fbid = None#评论id
109 | msg = None
110 | ad_check = None#状态 (0: 正常 1: UP主隐藏 2: 管理员删除 3: 因举报删除)
111 | post_user = None
112 |
113 | class CommentList():
114 | def __init__(self):
115 | pass
116 | comments = None
117 | commentLen = None
118 | page = None
119 |
120 | class ZhuantiInfo():
121 | def __init__(self, m_spid,m_title):
122 | self.spid = m_spid
123 | if isinstance(m_title,unicode):
124 | m_title = m_title.encode('utf8')
125 | self.title = m_title
126 | spid = None
127 | title = None
128 | author = None
129 | cover = None
130 | thumb = None
131 | ischeck = None #不明
132 | typeurl = None #总是"http://www.bilibili.com"
133 | tag = None
134 | description = None
135 | pubdate = None # 不明
136 | postdate = None
137 | lastupdate = None
138 | click = None
139 | favourite = None
140 | attention = None
141 | count = None
142 | bgmcount = None
143 | spcount = None
144 | season_id = None
145 | is_bangumi = None
146 | arcurl = None
--------------------------------------------------------------------------------
/bili-monitor/bilibili.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:42:03 2014
4 |
5 | @author: Vespa
6 | """
7 |
8 |
9 | from support import *
10 |
11 | ############################常量定义
12 |
13 | #####排序方式
14 | #收藏
15 | TYPE_SHOUCANG = 'stow'
16 | #评论数
17 | TYPE_PINGLUN = 'review'
18 | #播放数
19 | TYPE_BOFANG = 'hot'
20 | #硬币数
21 | TYPE_YINGBI = 'promote'
22 | #用户评分
23 | TYPE_PINGFEN = 'comment'
24 | #弹幕数
25 | TYPE_DANMU = 'damku'
26 | #拼音
27 | TYPE_PINYIN = 'pinyin'
28 | #投稿时间
29 | TYPE_TOUGAO = 'default'
30 | ############################常量定义结束
31 |
32 | def GetPopularVideo(begintime, endtime, sortType=TYPE_BOFANG, zone=0, page=1, original=0):
33 | """
34 | 输入:
35 | begintime:起始时间,三元数组[year1,month1,day1]
36 | endtime:终止时间,三元数组[year2,month2,day2]
37 | sortType:字符串,排序方式,参照TYPE_开头的常量
38 | zone:整数,分区,参照api.md文档说明
39 | page:整数,页数
40 | 返回:
41 | 视频列表,包含AV号,标题,观看数,收藏数,弹幕数,投稿日期,封面,UP的id号和名字
42 | """
43 | # TYPE_PINYIN和TYPE_TOUGAO情况下zone不可以等于[0,1,3,4,5,36,11,13]
44 | if sortType in [TYPE_PINYIN,TYPE_TOUGAO]:
45 | if zone in [0,1,3,4,5,36,11,13]:
46 | return []
47 | #判断是否原创
48 | if original:
49 | ori = '-original'
50 | else:
51 | ori = ''
52 | url = 'http://www.bilibili.tv/list/%s-%d-%d-%d-%d-%d~%d-%d-%d%s.html'%(sortType,zone,page,begintime[0],begintime[1],begintime[2],endtime[0],endtime[1],endtime[2],ori)
53 | content = getURLContent(url)
54 | return GetVideoFromRate(content)
55 |
56 |
57 | def GetUserInfo(url):
58 | """
59 | 由GetUserInfoBymid(mid)或者GetUserInfoByName(name)调用
60 | 返回:
61 | 用户信息
62 | 待添加:
63 | 如果用户不存在返回的是:{"code":-626,"message":"User is not exists."}
64 | """
65 | jsoninfo = JsonInfo(url)
66 | user = User(jsoninfo.Getvalue('mid'), jsoninfo.Getvalue('name'))
67 | user.isApprove = jsoninfo.Getvalue('approve')
68 | #b站现在空间名暂时不返回
69 | #user.spaceName = jsoninfo.Getvalue('spacename')
70 | user.sex = jsoninfo.Getvalue('sex')
71 | user.rank = jsoninfo.Getvalue('rank')
72 | user.avatar = jsoninfo.Getvalue('face')
73 | user.follow = jsoninfo.Getvalue('attention')
74 | user.fans = jsoninfo.Getvalue('fans')
75 | user.article = jsoninfo.Getvalue('article')
76 | user.place = jsoninfo.Getvalue('place')
77 | user.description = jsoninfo.Getvalue('description')
78 | user.friend = jsoninfo.Getvalue('friend')
79 | user.DisplayRank = jsoninfo.Getvalue('DisplayRank')
80 | user.followlist = []
81 | for fo in jsoninfo.Getvalue('attentions'):
82 | user.followlist.append(fo)
83 | return user
84 |
85 | def GetUserInfoBymid(mid):
86 | """
87 | 输入:
88 | mid:查询的用户的id
89 | 返回:
90 | 查看GetUserInfo()函数
91 | """
92 | mid = GetString(mid)
93 | url = 'http://api.bilibili.cn/userinfo'+"?mid="+mid
94 | return GetUserInfo(url)
95 |
96 | def GetUserInfoByName(name):
97 | """
98 | 输入:
99 | mid:查询的用户的昵称
100 | 返回:
101 | 查看GetUserInfo()函数
102 | """
103 | name = GetString(name)
104 | url = 'http://api.bilibili.cn/userinfo'+"?user="+name
105 | return GetUserInfo(url)
106 |
107 | def GetVideoOfZhuanti(spid, season_id=None, bangumi=None):
108 | """
109 | 输入:
110 | spid:专题id
111 | season_id:分季ID
112 | bangumi:设置为1返回剧番,不设置或者设置为0返回相关视频
113 | 返回:
114 | 视频列表,包含av号,标题,封面和观看数
115 | """
116 | url = ' http://api.bilibili.cn/spview?spid='+GetString(spid)
117 | if season_id:
118 | url += '&season_id='+GetString(season_id)
119 | if bangumi:
120 | url += '&bangumi='+GetString(bangumi)
121 | jsoninfo = JsonInfo(url)
122 | videolist = []
123 | for video_idx in jsoninfo.Getvalue('list'):
124 | video_idx = DictDecode2UTF8(video_idx)
125 | video = Video(video_idx['aid'],video_idx['title'])
126 | video.cover = video_idx['cover']
127 | video.guankan = video_idx['click']
128 | if video_idx.has_key('episode'):
129 | video.episode = video_idx['episode']
130 | video.src = video_idx["from"]
131 | video.cid = video_idx["cid"]
132 | video.page = video_idx["page"]
133 | videolist.append(video)
134 | return videolist
135 |
136 | def GetComment(aid, page = None, pagesize = None, order = None):
137 | """
138 | 输入:
139 | aid:AV号
140 | page:页码
141 | pagesize:单页返回的记录条数,最大不超过300,默认为10。
142 | order:排序方式 默认按发布时间倒序 可选:good 按点赞人数排序 hot 按热门回复排序
143 | 返回:
144 | 评论列表
145 | """
146 | url = 'http://api.bilibili.cn/feedback?aid='+GetString(aid)
147 | if page:
148 | url += '&page='+GetString(page)
149 | if pagesize:
150 | url += '&pagesize='+GetString(pagesize)
151 | if order:
152 | url += '&order='+GetString(order)
153 | jsoninfo = JsonInfo(url)
154 | commentList = CommentList()
155 | commentList.comments = []
156 | commentList.commentLen = jsoninfo.Getvalue('totalResult')
157 | commentList.page = jsoninfo.Getvalue('pages')
158 | idx = 0
159 | while jsoninfo.Getvalue(str(idx)):
160 | liuyan = Comment()
161 | liuyan.lv = jsoninfo.Getvalue(str(idx),'lv')
162 | liuyan.fbid = jsoninfo.Getvalue(str(idx),'fbid')
163 | liuyan.msg = jsoninfo.Getvalue(str(idx),'msg')
164 | liuyan.ad_check = jsoninfo.Getvalue(str(idx),'ad_check')
165 | liuyan.post_user.mid = jsoninfo.Getvalue(str(idx),'mid')
166 | liuyan.post_user.avatar = jsoninfo.Getvalue(str(idx),'face')
167 | liuyan.post_user.rank = jsoninfo.Getvalue(str(idx),'rank')
168 | liuyan.post_user.name = jsoninfo.Getvalue(str(idx),'nick')
169 | commentList.comments.append(liuyan)
170 | idx += 1
171 | return commentList
172 |
173 | def GetAllComment(aid, order = None):
174 | """
175 | 获取一个视频全部评论,有可能需要多次爬取,所以会有较大耗时
176 | 输入:
177 | aid:AV号
178 | order:排序方式 默认按发布时间倒序 可选:good 按点赞人数排序 hot 按热门回复排序
179 | 返回:
180 | 评论列表
181 | """
182 | MaxPageSize = 300
183 | commentList = GetComment(aid=aid, pagesize=MaxPageSize, order=order)
184 | if commentList.page == 1:
185 | return commentList
186 | for p in range(2,commentList.page+1):
187 | t_commentlist = GetComment(aid=aid,pagesize=MaxPageSize,page=p,ver=ver,order=order)
188 | for liuyan in t_commentlist.comments:
189 | commentList.comments.append(liuyan)
190 | time.sleep(0.5)
191 | return commentList
192 |
193 | def GetVideoInfo(aid, appkey,page = 1, AppSecret=None, fav = None):
194 | """
195 | 获取视频信息
196 | 输入:
197 | aid:AV号
198 | page:页码
199 | fav:是否读取会员收藏状态 (默认 0)
200 | """
201 | paras = {'id': GetString(aid),'page': GetString(page)}
202 | if fav:
203 | paras['fav'] = fav
204 | url = 'http://api.bilibili.cn/view?'+GetSign(paras,appkey,AppSecret)
205 | jsoninfo = JsonInfo(url)
206 | video = Video(aid,jsoninfo.Getvalue('title'))
207 | video.guankan = jsoninfo.Getvalue('play')
208 | video.commentNumber = jsoninfo.Getvalue('review')
209 | video.danmu = jsoninfo.Getvalue('video_review')
210 | video.shoucang = jsoninfo.Getvalue('favorites')
211 | video.description = jsoninfo.Getvalue('description')
212 | video.tag = []
213 | taglist = jsoninfo.Getvalue('tag')
214 | if taglist:
215 | for tag in taglist.split(','):
216 | video.tag.append(tag)
217 | video.cover = jsoninfo.Getvalue('pic')
218 | video.author = User(jsoninfo.Getvalue('mid'),jsoninfo.Getvalue('author'))
219 | video.page = jsoninfo.Getvalue('pages')
220 | video.date = jsoninfo.Getvalue('created_at')
221 | video.credit = jsoninfo.Getvalue('credit')
222 | video.coin = jsoninfo.Getvalue('coins')
223 | video.spid = jsoninfo.Getvalue('spid')
224 | video.cid = jsoninfo.Getvalue('cid')
225 | video.offsite = jsoninfo.Getvalue('offsite')
226 | video.partname = jsoninfo.Getvalue('partname')
227 | video.src = jsoninfo.Getvalue('src')
228 | video.tid = jsoninfo.Getvalue('tid')
229 | video.typename = jsoninfo.Getvalue('typename')
230 | video.instant_server = jsoninfo.Getvalue('instant_server')
231 | ## 以下三个意义不明。。
232 | # video.allow_bp = jsoninfo.Getvalue('allow_bp')
233 | # video.allow_feed = jsoninfo.Getvalue('allow_feed')
234 | # video.created = jsoninfo.Getvalue('created')
235 | return video
236 |
237 |
238 | def GetBangumi(appkey, btype = None, weekday = None, AppSecret=None):
239 | """
240 | 获取新番信息
241 | 输入:
242 | btype:番剧类型 2: 二次元新番 3: 三次元新番 默认(0):所有
243 | weekday:周一:1 周二:2 ...周六:6
244 | """
245 | paras = {}
246 | if btype != None and btype in [2,3]:
247 | paras['btype'] = GetString(btype)
248 | if weekday != None:
249 | paras['weekday'] = GetString(weekday)
250 | url = 'http://api.bilibili.cn/bangumi?' + GetSign(paras, appkey, AppSecret)
251 | jsoninfo = JsonInfo(url)
252 | bangumilist = []
253 | if jsoninfo.Getvalue('code') != 0:
254 | print jsoninfo.Getvalue('error')
255 | return bangumilist
256 | for bgm in jsoninfo.Getvalue('list'):
257 | bangumi = Bangumi()
258 | bgm = DictDecode2UTF8(bgm)
259 | bangumi.typeid = bgm['typeid']
260 | bangumi.lastupdate = bgm['lastupdate']
261 | bangumi.areaid = bgm['areaid']
262 | bangumi.bgmcount = getint(bgm['bgmcount'])
263 | bangumi.title = bgm['title']
264 | bangumi.lastupdate_at = bgm['lastupdate_at']
265 | bangumi.attention = bgm['attention']
266 | bangumi.cover = bgm['cover']
267 | bangumi.priority = bgm['priority']
268 | bangumi.area = bgm['area']
269 | bangumi.weekday = bgm['weekday']
270 | bangumi.spid = bgm['spid']
271 | bangumi.new = bgm['new']
272 | bangumi.scover = bgm['scover']
273 | bangumi.mcover = bgm['mcover']
274 | bangumi.click = bgm['click']
275 | bangumi.season_id = bgm['season_id']
276 | bangumi.click = bgm['click']
277 | bangumi.video_view = bgm['video_view']
278 | bangumilist.append(bangumi)
279 | return bangumilist
280 |
281 | def biliVideoSearch(appkey, AppSecret, keyword, order = 'default', pagesize = 20, page = 1):
282 | """
283 | 【注】:
284 | 旧版Appkey不可用,必须配合AppSecret使用!!
285 |
286 | 根据关键词搜索视频
287 | 输入:
288 | order:排序方式 默认default,其余待测试
289 | keyword:关键词
290 | pagesize:返回条目多少
291 | page:页码
292 | """
293 | paras = {}
294 | paras['keyword'] = GetString(keyword)
295 | paras['order'] = GetString(order)
296 | paras['pagesize'] = GetString(pagesize)
297 | paras['page'] = GetString(page)
298 | url = 'http://api.bilibili.cn/search?' + GetSign(paras, appkey, AppSecret)
299 | jsoninfo = JsonInfo(url)
300 | videolist = []
301 | for video_idx in jsoninfo.Getvalue('result'):
302 | if video_idx['type'] != 'video':
303 | continue
304 | video = Video(video_idx['aid'], video_idx['title'])
305 | video.typename = video_idx['typename']
306 | video.author = User(video_idx['mid'], video_idx['author'])
307 | video.acurl = video_idx['arcurl']
308 | video.description = video_idx['description']
309 | video.arcrank = video_idx['arcrank']
310 | video.cover = video_idx['pic']
311 | video.guankan = video_idx['play']
312 | video.danmu = video_idx['video_review']
313 | video.shoucang = video_idx['favorites']
314 | video.commentNumber = video_idx['review']
315 | video.date = video_idx['pubdate']
316 | video.tag = video_idx['tag'].split(',')
317 | videolist.append(video)
318 | return videolist
319 |
320 | def biliZhuantiSearch(appkey, AppSecret, keyword):
321 | """
322 | 根据关键词搜索专题
323 | 输入:
324 | keyword:关键词
325 | """
326 | paras = {}
327 | paras['keyword'] = GetString(keyword)
328 | url = 'http://api.bilibili.cn/search?' + GetSign(paras, appkey, AppSecret)
329 | jsoninfo = JsonInfo(url)
330 | zhuantiList = []
331 | for zhuanti_idx in jsoninfo.Getvalue('result'):
332 | if zhuanti_idx['type'] != 'special':
333 | continue
334 | zhuanti = ZhuantiInfo(zhuanti_idx['spid'], zhuanti_idx['title'])
335 | zhuanti.author = User(zhuanti_idx['mid'], zhuanti_idx['author'])
336 | zhuanti.cover = zhuanti_idx['pic']
337 | zhuanti.thumb = zhuanti_idx['thumb']
338 | zhuanti.ischeck = zhuanti_idx['ischeck']
339 | zhuanti.tag = zhuanti_idx['tag'].split(',')
340 | zhuanti.description = zhuanti_idx['description']
341 | zhuanti.pubdate = zhuanti_idx['pubdate']
342 | zhuanti.postdate = zhuanti_idx['postdate']
343 | zhuanti.lastupdate = zhuanti_idx['lastupdate']
344 | zhuanti.click = zhuanti_idx['click']
345 | zhuanti.favourite = zhuanti_idx['favourite']
346 | zhuanti.attention = zhuanti_idx['attention']
347 | zhuanti.count = zhuanti_idx['count']
348 | zhuanti.bgmcount = zhuanti_idx['bgmcount']
349 | zhuanti.spcount = zhuanti_idx['spcount']
350 | zhuanti.season_id = zhuanti_idx['season_id']
351 | zhuanti.is_bangumi = zhuanti_idx['is_bangumi']
352 | zhuanti.arcurl = zhuanti_idx['arcurl']
353 | zhuantiList.append(zhuanti)
354 | return zhuantiList
355 |
356 | #def GetBangumiByTime(year, month):
357 | # url='http://www.bilibili.tv/index/bangumi/%s-%s.json'%(GetString(year),GetString(month))
358 | # print url
359 | # jsoninfo = getURLContent(url)
360 | # print jsoninfo
361 |
362 | def GetRank(appkey, tid, begin=None, end=None, page = None, pagesize=None, click_detail =None, order = None, AppSecret=None):
363 | """
364 | 获取排行信息
365 | 输入:
366 | 详见https://github.com/Vespa314/bilibili-api/blob/master/api.md
367 | 输出:
368 | 详见https://github.com/Vespa314/bilibili-api/blob/master/api.md
369 | """
370 | paras = {}
371 | paras['appkey']=appkey
372 | paras['tid']=GetString(tid)
373 | if order:
374 | paras['order']=order
375 | if click_detail:
376 | paras['click_detail']=click_detail
377 | if pagesize:
378 | paras['pagesize']=GetString(pagesize)
379 | if begin != None and len(begin)==3:
380 | paras['begin']='%d-%d-%d'%(begin[0],begin[1],begin[2])
381 | if end != None and len(end)==3:
382 | paras['end']='%d-%d-%d'%(end[0],end[1],end[2])
383 | if page:
384 | paras['page']=GetString(page)
385 | if click_detail:
386 | paras['click_detail'] = click_detail
387 | url = 'http://api.bilibili.cn/list?' + GetSign(paras,appkey,AppSecret)
388 | jsoninfo = JsonInfo(url)
389 | videolist = []
390 | if jsoninfo.Getvalue('code') != 0:
391 | print jsoninfo.Getvalue('error')
392 | return videolist
393 | page = jsoninfo.Getvalue('pages')
394 | name = jsoninfo.Getvalue('name')
395 | for i in range(len(jsoninfo.Getvalue('list'))-1):
396 | idx = str(i)
397 | video = Video(jsoninfo.Getvalue('list',idx,'aid'),jsoninfo.Getvalue('list',idx,'title'))
398 | video.Iscopy = jsoninfo.Getvalue('list',idx,'copyright')
399 | video.tid = jsoninfo.Getvalue('list',idx,'typeid')
400 | video.typename = jsoninfo.Getvalue('list',idx,'typename')
401 | video.subtitle = jsoninfo.Getvalue('list',idx,'subtitle')
402 | video.guankan = jsoninfo.Getvalue('list',idx,'play')
403 | # video.commentNumber = jsoninfo.Getvalue('list',idx,'review')
404 | video.danmu = jsoninfo.Getvalue('list',idx,'video_review')
405 | video.shoucang = jsoninfo.Getvalue('list',idx,'favorites')
406 | video.author = User(jsoninfo.Getvalue('list',idx,'mid'),jsoninfo.Getvalue('list',idx,'author'))
407 | video.description = jsoninfo.Getvalue('list',idx,'description')
408 | video.date = jsoninfo.Getvalue('list',idx,'create')
409 | video.cover = jsoninfo.Getvalue('list',idx,'pic')
410 | video.credit = jsoninfo.Getvalue('list',idx,'credit')
411 | video.coin = jsoninfo.Getvalue('list',idx,'coins')
412 | video.commentNumber = jsoninfo.Getvalue('list',idx,'comment')
413 | video.duration = jsoninfo.Getvalue('list',idx,'duration')
414 | if click_detail != None:
415 | video.play_site = jsoninfo.Getvalue('list',idx,'play_site')
416 | video.play_forward = jsoninfo.Getvalue('list',idx,'play_forward')
417 | video.play_mobile = jsoninfo.Getvalue('list',idx,'play_mobile')
418 | videolist.append(video)
419 | return [page,name,videolist]
420 |
421 | def GetDanmuku(cid):
422 | cid = getint(cid)
423 | url = "http://comment.bilibili.cn/%d.xml"%(cid)
424 | content = zlib.decompressobj(-zlib.MAX_WBITS).decompress(getURLContent(url))
425 | content = GetRE(content,r'
]*>([^<]*)<')
426 | return content
427 |
428 | def GetBilibiliUrl(url, appkey, AppSecret=None):
429 | overseas=False
430 | url_get_media = 'http://interface.bilibili.com/playurl?' if not overseas else 'http://interface.bilibili.com/v_cdn_play?'
431 | regex_match = re.findall('http:/*[^/]+/video/av(\\d+)(/|/index.html|/index_(\\d+).html)?(\\?|#|$)',url)
432 | if not regex_match:
433 | return []
434 | aid = regex_match[0][0]
435 | pid = regex_match[0][2] or '1'
436 | video = GetVideoInfo(aid,appkey,pid,AppSecret)
437 | cid = video.cid
438 | media_args = {'cid': cid,'quality':4}
439 | resp_media = getURLContent(url_get_media+GetSign(media_args,appkey,AppSecret))
440 | media_urls = [str(k.wholeText).strip() for i in xml.dom.minidom.parseString(resp_media.decode('utf-8', 'replace')).getElementsByTagName('durl') for j in i.getElementsByTagName('url')[:1] for k in j.childNodes if k.nodeType == 4]
441 | return media_urls
442 |
443 | if __name__ == "__main__":
444 | pass
445 | #获取最热视频
446 | # videoList = GetPopularVideo([2014,05,20],[2014,05,27],TYPE_BOFANG,0,1)
447 | # for video in videoList:
448 | # print video.title
449 | #获取用户信息
450 | # user = GetUserInfoBymid('72960')
451 | # print user.name,user.DisplayRank
452 | # user = GetUserInfoByName('vespa')
453 | # print user.friend
454 | #获取专题视频信息
455 | # videolist = GetVideoOfZhuanti('46465',bangumi=1)
456 | # for video in videolist:
457 | # print video.title
458 | #获取评论
459 | # commentList = GetAllComment('1154794')
460 | # for liuyan in commentList.comments:
461 | # print liuyan.lv,'-',liuyan.post_user.name,':',liuyan.msg
462 | #获取视频信息
463 | # appkey = '************'
464 | # secretkey = None #选填
465 | # video = GetVideoInfo(1152959,appkey=appkey,AppSecret=secretkey)
466 | # for tag in video.tag:
467 | # print tag
468 | #获取新番
469 | # bangumilist = GetBangumi(appkey,btype = 2,weekday=1,AppSecret=secretkey)
470 | # for bangumi in bangumilist:
471 | # print bangumi.title
472 | #获取分类排行
473 | # [page,name,videolist] = GetRank(appkey,tid='0',order='hot',page=1,pagesize = 100,begin=[2014,1,1],end=[2014,2,1],click_detail='true')
474 | # for video in videolist:
475 | # print video.title,video.play_site
476 | #获取弹幕
477 | # video = GetVideoInfo(1677082,appkey,AppSecret=secretkey)
478 | # for danmu in GetDanmuku(video.cid):
479 | # print danmu
480 | #获取视频下载地址列表
481 | # media_urls = GetBilibiliUrl('http://www.bilibili.com/video/av1691618/',appkey = appkey)
482 | # for url in media_urls:
483 | # print(url)
484 | #视频搜索
485 | # for video in biliVideoSearch(appkey,secretkey,'rwby'):
486 | # print video.title
487 | #专题搜索
488 | # for zhuanti in biliZhuantiSearch(appkey,secretkey,'rwby'):
489 | # print zhuanti.title
--------------------------------------------------------------------------------
/bili-monitor/main.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:42:03 2014
4 |
5 | @author: Administrator
6 | """
7 |
8 | from bilibili import *
9 | import os
10 |
11 | def fileRename(title):
12 | if title.find('/') >= 0:
13 | title = title.replace('/','');
14 | if title.find(':') >= 0:
15 | title = title.replace(':','');
16 | if title.find('?') >= 0:
17 | title = title.replace('?','');
18 | if title.find('|') >= 0:
19 | title = title.replace('|','');
20 | if title.find('<') >= 0:
21 | title = title.replace('<','');
22 | if title.find('>') >= 0:
23 | title = title.replace('>','');
24 | if title.find('*') >= 0:
25 | title = title.replace('*','');
26 | return title
27 |
28 | def mMkdir(path):
29 | if not os.path.exists(path):
30 | os.mkdir(path)
31 |
32 | if __name__ == "__main__":
33 | appkey='03fc8eb101b091fb';
34 | secretkey = None #选填
35 | bangumilist = GetBangumi(appkey,btype = 2,weekday=0,AppSecret=secretkey);
36 | for bangumi in bangumilist:
37 | bangumi.title = fileRename(bangumi.title)
38 | print "updating bangumi info of:",bangumi.title
39 | path = "./%s"%(bangumi.title)
40 | mMkdir(path)
41 | videolist = GetVideoOfZhuanti(str(bangumi.spid),bangumi=1,season_id=bangumi.season_id)
42 | for video in videolist:
43 | print "Getting info of:",video.title
44 | videoinfo = GetVideoInfo(video.aid,appkey=appkey,AppSecret=secretkey)
45 | filepath = "%s/%s.txt"%(path,video.episode)
46 | if not os.path.isfile(filepath):
47 | fid = open(filepath,"a+")
48 | bgminfo = "Name:%s\nav=%s\nfrom:%s\nupdate day:%s\n"%(videoinfo.title,videoinfo.aid,video.src,videoinfo.date)
49 | fid.write(bgminfo)
50 | else:
51 | fid = open(filepath,"a+");
52 | cur_time = time.strftime('%Y-%m-%d %H:%M',time.localtime(time.time()))
53 |
54 | info = "%s: gk(%s) pl(%s) dm(%s) sc(%s) yb(%s)\n"%(cur_time,videoinfo.guankan,videoinfo.commentNumber,videoinfo.danmu,videoinfo.shoucang,videoinfo.coin)
55 | fid.write(info)
56 | fid.close()
57 | time.sleep(1)
--------------------------------------------------------------------------------
/bili-monitor/support.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:59:09 2014
4 |
5 | @author: Vespa
6 | """
7 | import urllib2
8 | import re
9 | import json
10 | import zlib
11 | import gzip
12 | import xml.dom.minidom
13 | import hashlib
14 | from biclass import *
15 | import time
16 | def GetRE(content,regexp):
17 | return re.findall(regexp, content)
18 |
19 | def getURLContent(url):
20 | while True:
21 | flag = 1
22 | try:
23 | headers = {'User-Agent':'Mozilla/5.0 (Windows U Windows NT 6.1 en-US rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
24 | req = urllib2.Request(url = url,headers = headers)
25 | content = urllib2.urlopen(req).read()
26 | except:
27 | flag = 0
28 | time.sleep(5)
29 | if flag == 1:
30 | break
31 | return content
32 |
33 | class JsonInfo():
34 | def __init__(self,url):
35 | self.info = json.loads(getURLContent(url))
36 | def Getvalue(self,*keys):
37 | if len(keys) == 0:
38 | return None
39 | if self.info.has_key(keys[0]):
40 | temp = self.info[keys[0]]
41 | else:
42 | return None
43 | if len(keys) > 1:
44 | for key in keys[1:]:
45 | if temp.has_key(key):
46 | temp = temp[key]
47 | else:
48 | return None
49 | if isinstance(temp,unicode):
50 | temp = temp.encode('utf8')
51 | return temp
52 | info = None
53 |
54 | def GetString(t):
55 | if type(t) == int:
56 | return str(t)
57 | return t
58 |
59 | def getint(string):
60 | try:
61 | i = int(string)
62 | except:
63 | i = 0
64 | return i
65 |
66 | def DictDecode2UTF8(dict):
67 | for keys in dict:
68 | if isinstance(dict[keys],unicode):
69 | dict[keys] = dict[keys].encode('utf8')
70 | return dict
71 |
72 | def GetVideoFromRate(content):
73 | """
74 | 从视频搜索源码页面提取视频信息
75 | """
76 | #av号和标题
77 | regular1 = r']*>([^/]+)'
78 | info1 = GetRE(content,regular1)
79 | #观看数
80 | regular2 = r']*>(.+)'
81 | info2 = GetRE(content,regular2)
82 | #收藏
83 | regular3 = r']*>(.+)'
84 | info3 = GetRE(content,regular3)
85 | #弹幕
86 | regular4 = r']*>(.+)'
87 | info4 = GetRE(content,regular4)
88 | #日期
89 | regular5 = r'(\d+-\d+-\d+ \d+:\d+)'
90 | info5 = GetRE(content,regular5)
91 | #封面
92 | regular6 = r'
]*>'
93 | info6 = GetRE(content,regular6)
94 | #Up的id和名字
95 | regular7 = r'(.*)'
96 | info7 = GetRE(content,regular7)
97 | #!!!!!!!!这里可以断言所有信息长度相等
98 | videoNum = len(info1)#视频长度
99 | videoList = []
100 | for i in range(videoNum):
101 | video_t = Video()
102 | video_t.aid = getint(info1[i][0])
103 | video_t.title = info1[i][1]
104 | video_t.guankan = getint(info2[i])
105 | video_t.shoucang = getint(info3[i])
106 | video_t.danmu = getint(info4[i])
107 | video_t.date = info5[i]
108 | video_t.cover = info6[i]
109 | video_t.author = User(info7[i][0],info7[i][1])
110 | videoList.append(video_t)
111 | return videoList
112 |
113 | def GetSign(params, appkey, AppSecret=None):
114 | """
115 | 获取新版API的签名,不然会返回-3错误
116 | 待添加:【重要!】
117 | 需要做URL编码并保证字母都是大写,如 %2F
118 | """
119 | params['appkey']=appkey
120 | data = ""
121 | paras = params.keys()
122 | paras.sort()
123 | for para in paras:
124 | if data != "":
125 | data += "&"
126 | data += para + "=" + str(params[para])
127 | if AppSecret == None:
128 | return data
129 | m = hashlib.md5()
130 | m.update(data+AppSecret)
131 | return data+'&sign='+m.hexdigest()
--------------------------------------------------------------------------------
/bili_live_guaji/bili_guaji.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | import requests
4 | import time
5 | import re
6 |
7 | def GetOneRoomId():
8 | r = requests.get('http://live.bilibili.com/').text
9 | res = re.search(r'data-room-id="(\d+)"', r)
10 | if res:
11 | return res.group(1)
12 |
13 | def post_heartbeat(headers):
14 | url = 'http://live.bilibili.com/User/userOnlineHeart'
15 | headers['Referer'] = "http://live.bilibili.com/%s"%(GetOneRoomId())
16 | response = requests.post(url, headers=headers)
17 | print response.content
18 |
19 | def read_cookie(cookiepath):
20 | with open(cookiepath, 'r') as fid:
21 | cookies = fid.readlines()
22 | return cookies
23 |
24 | def main(headers = {}):
25 | while True:
26 | print "Post:",time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
27 | post_heartbeat(headers)
28 | time.sleep(300)
29 |
30 | if __name__=='__main__':
31 | cookies = read_cookie('./bilicookies')[0]
32 | headers = {
33 | 'accept-encoding': 'gzip, deflate, sdch',
34 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.16 Safari/537.36',
35 | 'authority': 'live.bilibili.com',
36 | 'cookie': cookies,
37 | # 'Referer':'http://live.bilibili.com/39936',
38 | }
39 | main(headers)
--------------------------------------------------------------------------------
/bilibili-po/biclass.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Wed May 28 01:22:20 2014
4 |
5 | @author: Administrator
6 | """
7 |
8 | class User():
9 | def __init__(self,m_mid=None,m_name=None):
10 | if m_mid:
11 | self.mid = m_mid;
12 | if m_name:
13 | self.name = m_name;
14 | def saveToFile(self,fid):
15 | fid.write('名字:%s\n'%self.name);
16 | fid.write('id:%s\n'%self.mid);
17 | fid.write('是否认证:%s\n'%self.isApprove);
18 | fid.write('空间:%s\n'%self.spaceName);
19 | fid.write('性别:%s\n'%self.sex);
20 | fid.write('账号显示标识:%s\n'%self.rank);
21 | fid.write('头像:%s\n'%self.avatar);
22 | fid.write('关注好友数目:%d\n'%self.follow);
23 | fid.write('粉丝数目:%d\n'%self.fans);
24 | fid.write('投稿数:%d\n'%self.article);
25 | fid.write('地点:%s\n'%self.place);
26 | fid.write('认证信息:%s\n'%self.description);
27 | fid.write('关注好友:\n');
28 | for fo in self.followlist:
29 | fid.write('\t%s\n'%fo);
30 | # 获取空间地址
31 | def GetSpace(self):
32 | return 'http://space.bilibili.tv/'+str(mid);
33 | mid = None;
34 | name = None;
35 | isApprove = False;#是否是认证账号
36 | spaceName = "";
37 | sex = ""
38 | rank = None;
39 | avatar = None;
40 | follow = 0;#关注好友数目
41 | fans = 0;#粉丝数目
42 | article = 0;#投稿数
43 | place = None;#所在地
44 | description = None;#认证用户为认证信息 普通用户为交友宣言
45 | followlist = None;#关注的好友列表
46 |
47 |
48 | class Video():
49 | def __init__(self,m_aid=None,m_title=None):
50 | if m_aid:
51 | self.aid = m_aid;
52 | if m_title:
53 | self.title = m_title;
54 | # 写到文件中
55 | def saveToFile(self,fid):
56 | fid.write('av号:%d\n'%self.aid);
57 | fid.write('标题:%s\n'%self.title);
58 | fid.write('观看:%d\n'%self.guankan);
59 | fid.write('收藏:%d\n'%self.shoucang);
60 | fid.write('弹幕:%d\n'%self.danmu);
61 | fid.write('日期:%s\n'%self.date);
62 | fid.write('封面地址:%s\n'%self.cover);
63 | fid.write('Up主:\n');
64 | self.po.saveToFile(fid);
65 | fid.write('\n');
66 | aid = None;
67 | title = None;
68 | guankan = None;
69 | shoucang = None;
70 | danmu = None;
71 | date = None;
72 | cover = None;
73 | po = None;
74 |
75 | class Comment():
76 | def __init__(self):
77 | self.post_user = User();
78 | lv = None;#楼层
79 | fbid = None;#评论id
80 | msg = None;
81 | ad_check = None;#状态 (0: 正常 1: UP主隐藏 2: 管理员删除 3: 因举报删除)
82 | post_user = None;
83 |
84 | class CommentList():
85 | def __init__(self):
86 | pass;
87 | comments = None;
88 | commentLen = None;
89 | page = None;
--------------------------------------------------------------------------------
/bilibili-po/bilibili-relation.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vespa314/bilibili-api/42b6b90aa7c141f5cfb0fdc754435518106f6966/bilibili-po/bilibili-relation.txt
--------------------------------------------------------------------------------
/bilibili-po/bilibili.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:42:03 2014
4 |
5 | @author: Administrator
6 | """
7 |
8 | import sys, time, os, re
9 | from support import *
10 |
11 | ############################常量定义
12 |
13 | #####排序方式
14 | #收藏
15 | TYPE_SHOUCANG = 'stow'
16 | #评论数
17 | TYPE_PINGLUN = 'review'
18 | #播放数
19 | TYPE_BOFANG = 'hot'
20 | #硬币数
21 | TYPE_YINGBI = 'promote'
22 | #用户评分
23 | TYPE_PINGFEN = 'comment'
24 | #弹幕数
25 | TYPE_DANMU = 'damku'
26 | #拼音
27 | TYPE_PINYIN = 'pinyin'
28 | #投稿时间
29 | TYPE_TOUGAO = 'default'
30 | ############################常量定义结束
31 |
32 | def GetPopularVideo(begintime,endtime,sortType=TYPE_BOFANG,zone=0,page=1,original=0):
33 | """
34 | 输入:
35 | begintime:起始时间,三元数组[year1,month1,day1]
36 | endtime:终止时间,三元数组[year2,month2,day2]
37 | sortType:字符串,排序方式,参照TYPE_开头的常量
38 | zone:整数,分区,参照api.md文档说明
39 | page:整数,页数
40 |
41 | 返回:
42 | 视频列表,包含AV号,标题,观看数,收藏数,弹幕数,投稿日期,封面,UP的id号和名字
43 | 备注:
44 | 待添加:保证时间小于三个月
45 | 待添加:TYPE_PINYIN模式后面要添加类似:TYPE_PINYIN-'A'
46 | 待添加:TYPE_PINYIN和TYPE_TOUGAO情况下zone不可以等于[0,1,3,4,5,36,11,13]
47 | """
48 | #判断是否原创
49 | if original:
50 | ori = '-original';
51 | else:
52 | ori = ''
53 | url = 'http://www.bilibili.tv/list/%s-%d-%d-%d-%d-%d~%d-%d-%d%s.html'%(sortType,zone,page,begintime[0],begintime[1],begintime[2],endtime[0],endtime[1],endtime[2],ori);
54 | content = getURLContent(url);
55 | return GetVideoFromRate(content);
56 |
57 | def GetUserInfo(url):
58 | """
59 | 由GetUserInfoBymid(mid)或者GetUserInfoByName(name)调用
60 | 返回:
61 | 用户信息
62 | 待添加:
63 | 如果用户不存在返回的是:{"code":-626,"message":"User is not exists."}
64 | """
65 | jsoninfo = FromJson(url);
66 | if not jsoninfo.has_key('mid'):
67 | return None;
68 | user = User(jsoninfo['mid'],jsoninfo['name'].encode('utf8'));
69 | user.isApprove = jsoninfo['approve'];
70 | user.spaceName = jsoninfo['spacename'].encode('utf8');
71 | user.sex = jsoninfo['sex'].encode('utf8');
72 | user.rank = jsoninfo['rank'];
73 | user.avatar = jsoninfo['face'];
74 | user.follow = jsoninfo['attention'];
75 | user.fans = jsoninfo['fans'];
76 | user.article = jsoninfo['article'];
77 | user.place = jsoninfo['place'];
78 | user.description = jsoninfo['description'];
79 | user.followlist = [];
80 | for fo in jsoninfo['attentions']:
81 | if jsoninfo['attentions'][fo] != 0:
82 | user.followlist.append(jsoninfo['attentions'][fo])
83 | return user;
84 |
85 | def GetUserInfoBymid(mid):
86 | """
87 | 输入:
88 | mid:查询的用户的id
89 | 返回:
90 | 查看GetUserInfo()函数
91 | """
92 | mid = GetString(mid);
93 | url = 'http://api.bilibili.cn/userinfo'+"?mid="+mid;
94 | return GetUserInfo(url)
95 |
96 | def GetUserInfoByName(name):
97 | """
98 | 输入:
99 | mid:查询的用户的昵称
100 | 返回:
101 | 查看GetUserInfo()函数
102 | """
103 | name = GetString(name);
104 | url = 'http://api.bilibili.cn/userinfo'+"?user="+name;
105 | print url
106 | return GetUserInfo(url)
107 |
108 | def GetVideoOfZhuanti(spid,season_id=None,bangumi=None):
109 | """
110 | 输入:
111 | spid:专题id
112 | season_id:分季ID
113 | bangumi:设置为1返回剧番,不设置或者设置为0返回相关视频
114 | 返回:
115 | 视频列表,包含av号,标题,封面和观看数
116 | """
117 | url = ' http://api.bilibili.cn/spview?spid='+GetString(spid);
118 | if season_id != None:
119 | url += '&season_id='+GetString(season_id);
120 | if bangumi != None:
121 | url += '&bangumi='+GetString(bangumi);
122 | jsoninfo = FromJson(url);
123 | videolist = [];
124 | for video_idx in jsoninfo['list']:
125 | video = Video(jsoninfo['list'][video_idx]['aid'],jsoninfo['list'][video_idx]['title']);
126 | video.cover = jsoninfo['list'][video_idx]['cover'];
127 | video.guankan = jsoninfo['list'][video_idx]['click'];
128 | videolist.append(video);
129 | return videolist
130 |
131 | def GetComment(aid,page = None,pagesize = None,ver=None,order = None):
132 | """
133 | 输入:
134 | aid:AV号
135 | page:页码
136 | pagesize:单页返回的记录条数,最大不超过300,默认为10。
137 | ver:API版本,最新是3
138 | order:排序方式 默认按发布时间倒序 可选:good 按点赞人数排序 hot 按热门回复排序
139 | 返回:
140 | 评论列表
141 | """
142 | url = 'http://api.bilibili.cn/feedback?aid='+GetString(aid);
143 | if page:
144 | url += '&page='+GetString(page)
145 | if pagesize:
146 | url += '&pagesize='+GetString(pagesize)
147 | if ver:
148 | url += '&ver='+GetString(ver)
149 | if order:
150 | url += '&order='+GetString(order)
151 | jsoninfo = FromJson(url);
152 | commentList = CommentList();
153 | commentList.comments = [];
154 | commentList.commentLen = jsoninfo['totalResult']
155 | commentList.page = jsoninfo['pages'];
156 | idx = 0;
157 | while jsoninfo.has_key(str(idx)):
158 | liuyan = Comment();
159 | liuyan.lv = jsoninfo[str(idx)]['lv']
160 | liuyan.fbid = jsoninfo[str(idx)]['fbid']
161 | liuyan.msg = jsoninfo[str(idx)]['msg']
162 | liuyan.ad_check = jsoninfo[str(idx)]['ad_check']
163 | liuyan.post_user.mid = jsoninfo[str(idx)]['mid'];
164 | liuyan.post_user.avatar = jsoninfo[str(idx)]['face'];
165 | liuyan.post_user.rank = jsoninfo[str(idx)]['rank']
166 | liuyan.post_user.name = jsoninfo[str(idx)]['nick']
167 | commentList.comments.append(liuyan);
168 | idx += 1;
169 | return commentList
170 |
171 | def GetAllComment(aid,ver=None,order = None):
172 | """
173 | 获取一个视频全部评论,有可能需要多次爬取,所以会有较大耗时
174 | 输入:
175 | aid:AV号
176 | ver:API版本,最新是3
177 | order:排序方式 默认按发布时间倒序 可选:good 按点赞人数排序 hot 按热门回复排序
178 | 返回:
179 | 评论列表
180 | """
181 | MaxPageSize = 300;
182 | commentList = GetComment(aid=aid,pagesize=MaxPageSize,ver=ver,order=order)
183 | if commentList.page == 1:
184 | return commentList;
185 | for p in range(2,commentList.page+1):
186 | #print '%d/%d'%(p*MaxPageSize,commentList.commentLen)
187 | t_commentlist = GetComment(aid=aid,pagesize=MaxPageSize,page=p,ver=ver,order=order)
188 | for liuyan in t_commentlist.comments:
189 | commentList.comments.append(liuyan)
190 | time.sleep(0.5)
191 | return commentList
192 |
193 |
194 |
195 | if __name__ == "__main__":
196 | # f = open('result.txt','w');
197 |
198 | # videoList = GetPopularVideo([2014,05,20],[2014,05,27],TYPE_BOFANG,0,1)
199 | # for video in videoList:
200 | # video.saveToFile(f);
201 |
202 | # user = GetUserInfoBymid('72960');
203 | # print user.name.decode('utf8','ignore').encode('gbk','ignore')
204 | # user = GetUserInfoByName('vespa')
205 | # print user.spaceName.decode('utf8','ignore').encode('gbk','ignore')
206 | ## user.saveToFile(f);
207 |
208 | # videolist = GetVideoOfZhuanti('6492',bangumi=0);
209 | # for video in videolist:
210 | # print video.title
211 |
212 | commentList = GetAllComment('55300');
213 | for liuyan in commentList.comments:
214 | print liuyan.lv,'-',liuyan.post_user.name,':',liuyan.msg.encode('gbk','ignore')
215 | # f.close();
--------------------------------------------------------------------------------
/bilibili-po/finished.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vespa314/bilibili-api/42b6b90aa7c141f5cfb0fdc754435518106f6966/bilibili-po/finished.txt
--------------------------------------------------------------------------------
/bilibili-po/main.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Thu May 29 02:14:57 2014
4 |
5 | @author: Administrator
6 | """
7 |
8 | from bilibili import *
9 |
10 | def readfile(filename):
11 | result = [];
12 | f = open(filename,'r')
13 | for line in f:
14 | result.append(int(line));
15 | f.close();
16 | return result
17 |
18 | def main():
19 | try:
20 | f = open('bilibili-relation.txt','a+')
21 | polist = readfile('polist.txt')
22 | finished = readfile('finished.txt');
23 | idx = 0;
24 | while polist != []:
25 | cur = polist.pop(0);
26 | print '\t',idx,len(polist),cur;
27 | finished.append(cur);
28 | user = GetUserInfoBymid(cur);
29 | if user == None:
30 | continue
31 | if user.article > 0:
32 | print time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()));
33 | f.write('Up:%s %d\n'%(user.name,user.mid));
34 | f.write('fans:%d\n'%user.fans)
35 | f.write('article:%d\n'%user.article)
36 | for follow in user.followlist:
37 | f.write('\t%d\n'%follow);
38 | if not follow in finished:
39 | if not follow in polist:
40 | polist.append(follow);
41 | f.write('\n')
42 | idx += 1;
43 | time.sleep(0.5);
44 | f.close();
45 | except e:
46 | print str(e)
47 | #出错的话保持现场
48 | pofile = open('polist.txt','w')
49 | for item in polist:
50 | pofile.write(str(item)+'\n');
51 | pofile.close();
52 | pofile = open('finished.txt','w')
53 | for item in finished:
54 | pofile.write(str(item)+'\n');
55 | pofile.close();
56 | f.close();
57 |
58 | if __name__ == "__main__":
59 | main();
60 |
--------------------------------------------------------------------------------
/bilibili-po/polist.txt:
--------------------------------------------------------------------------------
1 | 72960
--------------------------------------------------------------------------------
/bilibili-po/support.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:59:09 2014
4 |
5 | @author: Administrator
6 | """
7 | import urllib
8 | import urllib2
9 | import json
10 | import re
11 | from biclass import *
12 | def GetRE(content,regexp):
13 | return re.findall(regexp, content)
14 |
15 | def getURLContent(url):
16 | while True:
17 | flag = 1;
18 | try:
19 | headers = {'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
20 | req = urllib2.Request(url = url,headers = headers);
21 | content = urllib2.urlopen(req).read();
22 | except:
23 | flag = 0;
24 | time.sleep(5)
25 | if flag == 1:
26 | break;
27 | return content;
28 |
29 | def FromJson(url):
30 | return json.loads(getURLContent(url))
31 |
32 | def GetString(t):
33 | if type(t) == int:
34 | return str(t)
35 | return t
36 |
37 | #从视频源码获取视频信息
38 | def GetVideoFromRate(content):
39 | #av号和标题
40 | regular1 = r'([^/]+)';
41 | info1 = GetRE(content,regular1)
42 | #观看数
43 | regular2 = r'(\d+)';
44 | info2 = GetRE(content,regular2)
45 | #收藏
46 | regular3 = r'(\d+)';
47 | info3 = GetRE(content,regular3)
48 | #弹幕
49 | regular4 = r'(\d+)';
50 | info4 = GetRE(content,regular4)
51 | #日期
52 | regular5 = r'(\d+-\d+-\d+ \d+:\d+)';
53 | info5 = GetRE(content,regular5)
54 | #封面
55 | regular6 = r'
';
56 | info6 = GetRE(content,regular6)
57 | #Up的id和名字
58 | regular7 = r'(.+)'
59 | info7 = GetRE(content,regular7)
60 | #!!!!!!!!这里可以断言所有信息长度相等
61 | videoNum = len(info1);#视频长度
62 | videoList = [];
63 | for i in range(videoNum):
64 | video_t = Video();
65 | video_t.aid = int(info1[i][0]);
66 | video_t.title = info1[i][1];
67 | video_t.guankan = int(info2[i]);
68 | video_t.shoucang = int(info3[i]);
69 | video_t.danmu = int(info4[i]);
70 | video_t.date = info5[i];
71 | video_t.cover = info6[i];
72 | video_t.po = User(info7[i][0],info7[i][1])
73 | videoList.append(video_t);
74 | return videoList
75 |
--------------------------------------------------------------------------------
/bilibili-po/分析/po-analyse.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Thu May 29 21:29:38 2014
4 |
5 | @author: Administrator
6 | """
7 | import re
8 |
9 | filename = 'bilibili-relation.txt';
10 |
11 | def GetUpList():
12 | f = open(filename);
13 | uplist = [];
14 | for line in f:
15 | find = re.findall(r'^Up:.* (\d+)$',line)
16 | if find != []:
17 | uplist.append(int(find[0]));
18 | f.close();
19 | return uplist
20 |
21 | def CreateDictBetweenUp(uplist):
22 | uplist = set(uplist);
23 | f = open(filename);
24 | updict = {};
25 | for line in f:
26 | find = re.findall(r'^Up:.* (\d+)$',line)
27 | if find != []:
28 | cur = int(find[0]);
29 | updict[cur] = {};
30 | updict[cur]['follow'] = set();
31 | find = re.findall(r'^Up:(.*) \d+$',line)
32 | if find != []:
33 | updict[cur]['name'] = find[0];
34 | else:
35 | print cur
36 | continue;
37 | find = re.findall(r'^fans:(\d+)$',line)
38 | if find != []:
39 | fans = int(find[0]);
40 | updict[cur]['fans'] = fans;
41 | continue;
42 | find = re.findall(r'^article:(\d+)$',line)
43 | if find != []:
44 | article = int(find[0]);
45 | updict[cur]['article'] = article;
46 | continue;
47 | find = re.findall(r'\t(\d+)$',line)
48 | if find != []:
49 | follow = int(find[0]);
50 | if follow in uplist:
51 | updict[cur]['follow'].add(follow);
52 | f.close();
53 | return updict
54 |
55 | def GetNext(cor_fo,updict,ups):
56 | result = [];
57 | upNum = len(ups)
58 | for corfo in cor_fo:
59 | for i in xrange(upNum-1,-1,-1):
60 | if ups[i] <= corfo[-1]:
61 | break;
62 | flag = 1;
63 | for user in corfo:
64 | if ups[i] in updict[user]['follow'] and user in updict[ups[i]]['follow']:
65 | continue
66 | else:
67 | flag = 0;
68 | break
69 | if flag:
70 | result.append(corfo+[ups[i]])
71 | return result
72 |
73 | if __name__ == "__main__":
74 | uplist = GetUpList();
75 | updict = CreateDictBetweenUp(uplist);
76 | #保存每个Up的id,投稿数和粉丝数以便分析
77 | f = open('article-fans.txt','w');
78 | for up in updict:
79 | f.write("%d %d %d\n"%(up,updict[up]['article'],updict[up]['fans']))
80 | f.close();
81 | #保存每个Up和关注的关系
82 | f = open('up-follow.txt','w');
83 | for up in updict:
84 | for fo in updict[up]['follow']:
85 | if up in updict[fo]['follow'] and fo > up:
86 | f.write("%s %s 2\n"%(up,fo))
87 | else:
88 | f.write("%d %d 1\n"%(up,fo))
89 | f.close();
90 | #保存id-昵称:
91 | f = open('upinfo.txt','w');
92 | for up in updict:
93 | f.write('%d %s\n'%(up,updict[up]['name']))
94 | f.close();
95 | #查找最大关注圈
96 | ups = updict.keys();
97 | ups.sort();
98 | result = [[[i] for i in ups]];
99 | las = GetNext(result[-1],updict,ups);
100 | while las != []:
101 | result.append(las);
102 | las = GetNext(result[-1],updict,ups);
103 | # #关注关系保存成文件
104 | for i in range(len(result)):
105 | for j in range(len(result[i])):
106 | result[i][j] = set(result[i][j]);
107 | for i in range(0,len(result)):
108 | f = open(str(i+1)+'.txt','w');
109 | for pair in result[i]:
110 | flag = 1;
111 | if i != len(result)-1:
112 | for pairnext in result[i+1]:
113 | if pair.issubset(pairnext):
114 | flag = 0;
115 | break
116 | if flag == 1:
117 | for po in pair:
118 | f.write(updict[po]['name']);
119 | f.write('\t');
120 | f.write('\n')
121 | f.close()
122 | print 'Finished'
123 |
--------------------------------------------------------------------------------
/bilibili-po/分析/up-follow.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vespa314/bilibili-api/42b6b90aa7c141f5cfb0fdc754435518106f6966/bilibili-po/分析/up-follow.rar
--------------------------------------------------------------------------------
/bilibili-po/分析/关注圈/4.txt:
--------------------------------------------------------------------------------
1 | 水滴Kstone CC子 爱情上甘岭 白羽沉
2 | 某可牌橘子汽水 fontaine Magus 20024JoK
3 | 空气化的H音 fontaine Magus TSA
4 | 岚aya H.K.君 柴刀娘木木 平安夜的噩梦
5 | 正经战队 西方良目仙人掌 meiling 菊攻尽瘁
6 | 林即中 西方良目仙人掌 meiling 台风13号挑战者
7 | 河童子 ここにいるよ 96猫@141.2cm SuperBrother
8 | 河童子 Arpeggio 白white饭 SuperBrother
9 | 深海庞贝 糜酱 CJ木 破车车
10 | 深海庞贝 絶体延命 兰豆子 她
11 | 深海庞贝 她 溪桫 无敌水怪
12 | 深海庞贝 她 兰豆子 无敌水怪
13 | 枫梨雨花 好大一张大饼 黑礼帽 优花里
14 | 空气化的H音 Magus EPM TSA
15 | 亚月 kikou 妄想世界協會 师酱
16 | Tele 96猫@141.2cm 一条樂 SuperBrother
17 | Tele 96猫@141.2cm 【南】光太郎 SuperBrother
18 | Tele 96猫@141.2cm SuperBrother CSアーチャー
19 | Tele 白white饭 CSアーチャー SuperBrother
20 | 萌谋一 爱妻の忠犬斯大林 白white饭 三倍速法兰西
21 | 凉月奏 爱妻の忠犬斯大林 白white饭 三倍速法兰西
22 | 96猫@141.2cm SuperBrother fumo にししししー
23 | 96猫@141.2cm CSアーチャー fumo SuperBrother
24 | CSアーチャー 冰封的羲和 fumo SuperBrother
25 | 小辰 白海狸 Dove♪神痕灬 cnocoiate
26 | 小辰 白海狸 Dove♪神痕灬 Falling捏捏
27 | 小辰 Dove♪神痕灬 Falling捏捏 XD小东
28 | 小辰 Dove♪神痕灬 Falling捏捏 掌心の羁绊
29 | 小辰 Dove♪神痕灬 オルゴール cnocoiate
30 | 小辰 oneways 橘丶万里花酱 オルゴール
31 | 小辰 oneways 复仇女王 オルゴール
32 | 小辰 Z·DARK 小泽玛利亮 四方SR
33 | 小辰 Z·DARK Dove♪神痕灬 四方SR
34 | JUSF GhostFinal 哲学♂跳蝻 花之祭P
35 | Aru Gintoki_JF KarSa wearsky
36 | SonicoQ Dove♪神痕灬 wearsky 玛莎烈啤酒
37 | Aru SugerTAMA 东城绫的忧郁 wearsky
38 | wywzyx2 复仇女王 wearsky 病娇电波兔
39 | SonicoQ wearsky 天蓝梦境 玛莎烈啤酒
40 | SonicoQ wearsky 天蓝梦境 何满子
41 | 东城绫的忧郁 Dove♪神痕灬 wearsky 哈露ちゃん
42 | Aru oneways wearsky 复仇女王
43 | luckAMV oneways wearsky 复仇女王
44 | Aru oneways wearsky 天蓝梦境
45 | 复仇女王 oneways wearsky 哈露ちゃん
46 | 望天晓 Dove♪神痕灬 wearsky Magus
47 | ここにいるよ Pklala12 wearsky Magus
48 | 夢想風靡 mlsao_SF Q少 8⑩3·X·切糕
49 | 夢想風靡 mlsao_SF 8⑩3·X·切糕 kartoro
50 | SuperBrother CSアーチャー 冰封的羲和 三倍速法兰西
51 | 心情永远是晴天 圣光喵 弹簧 丧失神殿
52 | 深籣 luckAMV NOOB酱 桥西
53 | 深籣 ここにいるよ NOOB酱 luckAMV
54 | 留学の轮舞曲 比利.海林顿 meiling LF先辈
55 | 比利.海林顿 meiling 夜总会来的 Lucky好心情
56 | 比利.海林顿 LF先辈 meiling Lucky好心情
57 | chord枕头 蓝山 源冬 大智若⑨的kiyu
58 | 96猫@141.2cm 三倍速法兰西 CSアーチャー SuperBrother
59 | SuperBrother 白white饭 CSアーチャー 三倍速法兰西
60 | 凉月奏 白white饭 CSアーチャー 三倍速法兰西
61 | 白羽沉 Dove♪神痕灬 Magus Xmyz.G
62 | 望天晓 Dove♪神痕灬 Magus 绯色の尼禄
63 | 沁沁_Shiho Magus 白羽沉 谷亮子
64 | 96猫@141.2cm 沁沁_Shiho Magus 白羽沉
65 | KoKky 橘丶万里花酱 Magus 天蓝梦境
66 | 仓米丁 橘丶万里花酱 Magus 天蓝梦境
67 | SonicoQ 橘丶万里花酱 Magus 天蓝梦境
68 | luckAMV Magus 天蓝梦境 绯色の尼禄
69 | 此曲可待成追忆 Magus 白羽沉 她
70 | M.呜喵 Caaaaarrot Magus 掌心の羁绊
71 | luckAMV Caaaaarrot Magus 绯色の尼禄
72 | 96猫@141.2cm Caaaaarrot Magus 掌心の羁绊
73 | Aru 世界の敌 Caaaaarrot Magus
74 | 复仇女王 nobitanobi Magus 哈露ちゃん
75 | 橘丶万里花酱 Dove♪神痕灬 Magus 哈露ちゃん
76 | 96猫@141.2cm 掌心の羁绊 Magus にししししー
77 | luckAMV Hirasawa Yui Magus にししししー
78 | 96猫@141.2cm Hirasawa Yui Magus にししししー
79 | DigiCat ビリくん Magus にししししー
80 | 吃烧卖 luckAMV Magus にししししー
81 | 真鱼 ここにいるよ Magus 新建君
82 | 渣文 96猫@141.2cm Magus 掌心の羁绊
83 | ここにいるよ Black★Rock.Shooter Magus にししししー
84 | 96猫@141.2cm 沁沁_Shiho Magus 浅叶
85 | 萌谋一 热々 白white饭 三倍速法兰西
86 | kikou Lucky好心情 西行寺·爱多多姐 meiling
87 | 烤夜雀 Lucky好心情 meiling kikou
88 | Lucky好心情 西行寺·爱多多姐 meiling 20024JoK
89 | Lucky好心情 西行寺·爱多多姐 meiling LF先辈
90 | 烤夜雀 Lucky好心情 meiling LF先辈
91 | Lucky好心情 96猫@141.2cm 一条樂 SuperBrother
92 | 烤夜雀 Lucky好心情 meiling 常烦常乐
93 | Lendll 玉米姬 新华里业务员 春哥之印
94 | 烤夜雀 元素之觸 meiling LF先辈
95 | 堕落的小熊猫 700码 螃蟹 重生的囧
96 | DR_magnet 射命丸毅 阿燐酱 绯色蓝
97 | 绯想的长女大人 慕澐 射命丸毅 阿燐酱
98 | DR_magnet 人间地地 射命丸毅 阿燐酱
99 | 人间地地 绯想的长女大人 射命丸毅 阿燐酱
100 | 慕澐 绯想的长女大人 楚清魂 射命丸毅
101 | 人间地地 楚清魂 绯想的长女大人 射命丸毅
102 | 人生赢家小明 小透明BAKA 兰豆子 她
103 | A.Excalibur Coda 小透明BAKA 某可牌橘子汽水
104 | 杏花包子 潜移默化♀浅姨磨花 JUSF 哲学♂跳蝻
105 | 杏花包子 潜移默化♀浅姨磨花 哲学♂跳蝻 浓稠铅笔酱
106 | SOLOJD 宅幽灵 泽拉图道长 黑礼帽
107 | 赛亚♂sya JUSF 闪光少女考拉姬 麦当叔劳劳
108 | 赛亚♂sya JUSF 桐叶_tongye 闪光少女考拉姬
109 | 流动の黑暗 LenRinFuck 找到梦想的咩咩酱丶 月八
110 | baka風 何满子 オルゴール 月八
111 | Z·DARK lucifel 零崎壱识 Pklala12
112 | 四方SR Z·DARK 樱花6896 零崎壱识
113 | 十二雲 東風5型 c020109703 scl是个妹控
114 | 绿尾的嫉妒 豪俊影视 lubyyy 御剑怜侍
115 | 西行寺·爱多多姐 lubyyy 壮你妹硕 御剑怜侍
116 | 寅丸星☆大型にゃんこ 下一桁ひよ子 qatt 秋木荣
117 | oneways 啪嗒啪嗒EDR Falling捏捏 哈露ちゃん
118 | zhanghan603 小字辈 ICEwiimaker 伯楼斯
119 | 若虫 烤夜雀 妄想世界協會 Chokeslam
120 | 若虫 妄想世界協會 incub8or 不动乱岚
121 | 96猫@141.2cm DK★Blacat ﹎windrunner SuperBrother
122 | ここにいるよ DigiCat SuperBrother にししししー
123 | 96猫@141.2cm 【南】光太郎 ﹎windrunner SuperBrother
124 | 真鱼 96猫@141.2cm iddqd SuperBrother
125 | 深籣 KwaiMay 何满子 オルゴール
126 | 深籣 luckAMV Hirasawa Yui にししししー
127 | 深籣 96猫@141.2cm Hirasawa Yui にししししー
128 | 深籣 特莱嘻嘻嘻 オルゴール 雪丿下雪乃
129 | 深籣 オルゴール 何满子 lucifel
130 | 正经战队 チャージマン研! meiling 蓝志
131 | 运营 豪俊影视 BISHI8 meiling
132 | 豪俊影视 IP用户222893450 BISHI8 meiling
133 | 豪俊影视 IP用户222893450 meiling 某路易斯
134 | 豪俊影视 BISHI8 meiling 06御前
135 | 台风13号挑战者 浪花Renka meiling 雷武P
136 | 运营 恋之八卦炉 BISHI8 meiling
137 | 运营 incub8or BISHI8 meiling
138 | incub8or 23夜 meiling Dale Yuan
139 | incub8or IP用户222893450 BISHI8 meiling
140 | incub8or BISHI8 meiling 06御前
141 | 烤夜雀 妄想世界協會 meiling 大石碎睾丸
142 | 正经战队 チャージマン研! 泉研 meiling
143 | チャージマン研! 泉研 meiling Lendll
144 | 豪俊影视 林即中 meiling 某路易斯
145 | 林即中 meiling 台风13号挑战者 雷武P
146 | 正经战队 林即中 meiling 雷武P
147 | 林即中 チャージマン研! meiling Lendll
148 | incub8or 林即中 meiling 夜总会来的
149 | LF先辈 萌郁 西行寺·爱多多姐 meiling
150 | Z·DARK bellicose小殇 Dove♪神痕灬 SonicoQ
151 | Z·DARK baka風 オルゴール 复仇女王
152 | Z·DARK Aru 找到梦想的咩咩酱丶 天蓝梦境
153 | 折翼の天启 Z·DARK 何满子 オルゴール
154 | Z·DARK baka風 何满子 オルゴール
155 | Z·DARK Aru Caaaaarrot オルゴール
156 | Z·DARK Caaaaarrot オルゴール 流动の黑暗
157 | Z·DARK 破碎の杯子 Caaaaarrot Aru
158 | Z·DARK 无聊啊啊啊啊 何满子 寂寞的足迹
159 | Z·DARK 找到梦想的咩咩酱丶 lucifel 孤月十寒
160 | Z·DARK 找到梦想的咩咩酱丶 lucifel Pklala12
161 | 四方SR Z·DARK 樱花6896 夏蝶幽影
162 | Dove♪神痕灬 Z·DARK TIMMADteam 复仇女王
163 | Z·DARK TIMMADteam 复仇女王 lucifel
164 | GyuYi小板 Yumeko梦子 渗透系UP病毒 neko幽音♪
165 | -infinity. oneways Falling捏捏 毛毛菌殿下
166 | Aru oneways 特莱嘻嘻嘻 オルゴール
167 | Aru oneways 复仇女王 オルゴール
168 | luckAMV oneways 复仇女王 オルゴール
169 | 民主 luckAMV oneways 天蓝梦境
170 | oneways 橘丶万里花酱 オルゴール 天蓝梦境
171 | Aru oneways オルゴール 天蓝梦境
172 | oneways 何满子 毛毛菌殿下 Falling捏捏
173 | 民主 oneways 何满子 天蓝梦境
174 | 真鱼 96猫@141.2cm 莫非命 她
175 | Pklala12 复仇女王 lucifel 哔哔哔哩哔哩
176 | 小shin BD播放器 一個點 lucifel
177 | Pklala12 小shin 复仇女王 lucifel
178 | 小shin 一個點 起起 lucifel
179 | 晓美の焰 オルゴール lucifel 复仇女王
180 | ねこさんぜん 一個點 BD播放器 lucifel
181 | ねこさんぜん Gintoki_JF lucifel 哔哔哔哩哔哩
182 | ねこさんぜん BD播放器 オルゴール lucifel
183 | 杏本詩歌 小shin 一個點 lucifel
184 | オルゴール 何满子 lucifel 恋の镇魂曲
185 | 杂菌 火焰之洲 以太 小白Pikiyo
186 | _高能君_ 火焰之洲 以太 小白Pikiyo
187 | 渣渣≥ω≤ 杂菌 以太 爆刀帝
188 | 妄想世界協會 西行寺·爱多多姐 恋之八卦炉 紅次yake
189 | 妄想世界協會 西行寺·爱多多姐 incub8or 紅次yake
190 | 梨斗渣 特莱嘻嘻嘻 ECH渣剪组 雪丿下雪乃
191 | Aru 特莱嘻嘻嘻 Xmyz.G 雪丿下雪乃
192 | Aru -infinity. Dove♪神痕灬 雪丿下雪乃
193 | Aru 特莱嘻嘻嘻 オルゴール 雪丿下雪乃
194 | luckAMV オルゴール 雪丿下雪乃 复仇女王
195 | 寂寞的狂热 无聊啊啊啊啊 オルゴール 雪丿下雪乃
196 | 特莱嘻嘻嘻 -infinity. 雪丿下雪乃 哈露ちゃん
197 | -infinity. Dove♪神痕灬 雪丿下雪乃 哈露ちゃん
198 | 寂寞的足迹 无聊啊啊啊啊 黯夜影殇 何满子
199 | 超节能の黑猫君 96猫@141.2cm DK★Blacat ﹎windrunner
200 | 黄博美不美 恋之八卦炉 西行寺·爱多多姐 20024JoK
201 | 黄博美不美 incub8or 西行寺·爱多多姐 20024JoK
202 | 电波银河 incub8or 古明地lzh 20024JoK
203 | 此时夜至 Retoruto全力应援字幕组 炭酱 abu实况搬运组
204 | ☆玉玉子 傲娇麒儿 废柴の琉璃酱 xkd青鱼
205 | ☆玉玉子 亦澄 傲娇麒儿 coco milk
206 | ☆玉玉子 ☆来来子 小受C零酱 流川菌
207 | ☆玉玉子 ☆来来子 ☆SORA子 请叫我菊哥
208 | ☆玉玉子 ☆来来子 xkd青鱼 请叫我菊哥
209 | ☆玉玉子 小伞一把 肥皂菌丨珉珉的猫咪丨 黑化零度
210 | ☆玉玉子 ☆来来子 黑化零度 流川菌
211 | ☆玉玉子 doraiba 珠峰喵 杂菌
212 | ☆玉玉子 肥皂菌丨珉珉的猫咪丨 黑化零度 天国的兔纸
213 | ☆玉玉子 血意小枫 xkd青鱼 疾風醬
214 | slayerszero SgenL 逝梦 ECH渣剪组
215 | 东城绫的忧郁 蓝羽天梦 Dove♪神痕灬 哈露ちゃん
216 | 二米明子 Dove♪神痕灬 Falling捏捏 哈露ちゃん
217 | 二米明子 Dove♪神痕灬 复仇女王 哈露ちゃん
218 | -infinity. Dove♪神痕灬 Falling捏捏 哈露ちゃん
219 | Dove♪神痕灬 LenRinFuck 找到梦想的咩咩酱丶 哈露ちゃん
220 | 特莱嘻嘻嘻 橘丶万里花酱 Entice 哈露ちゃん
221 | 橘丶万里花酱 Dove♪神痕灬 Entice 哈露ちゃん
222 | 烤夜雀 妄想世界協會 绝顶油条 大石碎睾丸
223 | mlsao_SF 珠峰喵 8⑩3·X·切糕 kartoro
224 | mlsao_SF 珠峰喵 丶苹果 kartoro
225 | CC子 世界の敌 Caaaaarrot 毛酱·现实坠落
226 | 无聊啊啊啊啊 何满子 オルゴール 恋の镇魂曲
227 | baka風 何满子 オルゴール 恋の镇魂曲
228 | 时连 牧场鬼太郎 登校拒否 舞切响子
229 | 被千人斩的小火柴 三渣白发 露卡酱 胖次上面有我的孩子们
230 | 被千人斩的小火柴 胖次上面有我的孩子们 露卡酱 YOOOOO夢
231 | 作死的吧唧 被千人斩的小火柴 露卡酱 胖次上面有我的孩子们
232 | 绝望是梦想的初章 Chokeslam 绝顶油条 鬼魅妖魄
233 | 妄想世界協會 从侧面上www Chokeslam 绝顶油条
234 | 烤夜雀 菜死你不偿命 绝望是梦想的初章 绝顶油条
235 | SonicoQ Dove♪神痕灬 Entice 橘丶万里花酱
236 | SonicoQ Aru Dove♪神痕灬 Entice
237 | 留学の轮舞曲 黄博美不美 incub8or 西行寺·爱多多姐
238 | 带队冲塔送 incub8or 妹が大好き 灵乌路河童
239 | live-evil 小一二P Z.Y.L 一個點
240 | AdamXL07 粒粒梦想 冻酸奶泡芙 幻剑之子
241 | 火雨の妖精 AKA冰丽酱 发癫的四叶草 游戏基×
242 | 清水湾大酒店 生ネギ 千亚酱 yuruice
243 | ねこさんぜん Gintoki_JF 真红琉璃 哔哔哔哩哔哩
244 | ねこさんぜん 空蝉与诗 Gintoki_JF 哔哔哔哩哔哩
245 | ねこさんぜん Gintoki_JF Dove♪神痕灬 哔哔哔哩哔哩
246 | ねこさんぜん Dove♪神痕灬 オルゴール cnocoiate
247 | FATE零零七 Aru Caaaaarrot 绯色の尼禄
248 | 橘丶万里花酱 Caaaaarrot 掌心の羁绊 オルゴール
249 | Mの葱头 Caaaaarrot 掌心の羁绊 結城音無
250 | 南屋 这只是一个CJ的腐女 CHS. (* ̄▽ ̄)
251 | _羊毛w 圣炎、黑曜石 灯笼QB 这里是又又
252 | 寂寞的狂热 AB强强YOUNG 小然参上 bili炮爷
253 | 赛亚♂sya JUSF 哲学♂跳蝻 麦当叔劳劳
254 | 赛亚♂sya GhostFinal 哲学♂跳蝻 打牌的初音
255 | 陆连清 三渣白发 露卡酱 胖次上面有我的孩子们
256 | 陆连清 胖次上面有我的孩子们 细雨游风 露卡酱
257 | 96猫@141.2cm 莫非命 兰豆子 她
258 | 破碎の杯子 特莱嘻嘻嘻 掌心の羁绊 Xmyz.G
259 | 破碎の杯子 Gintoki_JF KarSa Aru
260 | 破碎の杯子 Gintoki_JF Dove♪神痕灬 毛毛菌殿下
261 | 破碎の杯子 小shin Aru Gintoki_JF
262 | yuruice 生ネギ 千亚酱 星阳天
263 | 毛毛菌殿下 Dove♪神痕灬 何满子 Falling捏捏
264 | Smile灬乖乖 流动の黑暗 Dove♪神痕灬 何满子
265 | 民主 SonicoQ 何满子 天蓝梦境
266 | オルゴール 何满子 天蓝梦境 SolexL1
267 | Pklala12 FATE零零七 七夜听雪 SonicoQ
268 | Pklala12 复仇女王 七夜听雪 SonicoQ
269 | nobitanobi 复仇女王 七夜听雪 LenRinFuck
270 | SonicoQ 复仇女王 七夜听雪 LenRinFuck
271 | SonicoQ FATE零零七 天蓝梦境 otaku90
272 | 民主 SonicoQ 绯色の尼禄 天蓝梦境
273 | 民主 luckAMV 绯色の尼禄 天蓝梦境
274 | FATE零零七 Aru 找到梦想的咩咩酱丶 天蓝梦境
275 | SonicoQ 橘丶万里花酱 オルゴール 天蓝梦境
276 | SonicoQ オルゴール 天蓝梦境 玛莎烈啤酒
277 | DigiCat オルゴール 天蓝梦境 SolexL1
278 | CJ木 糜酱 日進月步 柚小悶
279 | 美味的篮子酱 feverX 烦烦烦烦帆‘ 碳了个酸
280 | 章鱼丸子 ai菓子の小琦 烦烦烦烦帆‘ crystalbobosky
281 | 章鱼丸子 狐丝酱 烦烦烦烦帆‘ ai菓子の小琦
282 | 美味的篮子酱 feverX 烦烦烦烦帆‘ 莲莉大表哥
283 | 潜移默化♀浅姨磨花 JUSF 松江府人 桐叶_tongye
284 | 妄想世界協會 Chokeslam 被厌恶者的哲♂学 水纹与熏风
285 | 穆索尔司机 Chokeslam 水纹与熏风 ttbt
286 | Aru 请输入姓名: Tsuki_神夜 結城音無
287 | FATE零零七 洛洛碳丶桑⑨ 掌心の羁绊 結城音無
288 | FATE零零七 Aru 洛洛碳丶桑⑨ 結城音無
289 | nobitanobi 复仇女王 オルゴール XD小东
290 | Aru nobitanobi 复仇女王 オルゴール
291 | 望天晓 Dove♪神痕灬 オルゴール XD小东
292 | 橘丶万里花酱 望天晓 Dove♪神痕灬 オルゴール
293 | SonicoQ Dove♪神痕灬 玛莎烈啤酒 オルゴール
294 | Aru 小shin 复仇女王 オルゴール
295 | Aru 小shin 起起 オルゴール
296 | 晓美の焰 复仇女王 オルゴール 掌心の羁绊
297 | 小然参上 发癫的四叶草 掌心の羁绊 彼岸花开成海
298 | U2一美是绝配 小然参上 掌心の羁绊 彼岸花开成海
299 | 留学の轮舞曲 黄博美不美 恋之八卦炉 西行寺·爱多多姐
300 | 头顶小胖次 西草KusA洛洛味 维C含片 夏夏·很夏流
301 | 头顶小胖次 西草KusA洛洛味 夏洛洛特西草味 维C含片
302 | 眼镜狂魔纯叶酱 西草KusA洛洛味 夏洛洛特西草味 头顶小胖次
303 | 二米明子 新堂爱卖萌 lunacherry Mr甜点
304 | 二米明子 lunacherry Mr甜点 言叶おわた
305 | Mr甜点 lunacherry 歼灭小天使 言叶おわた
306 | Mell君 AA8 lunacherry KingOfHarem
307 | 洒家就是逃子 这里是又又 _羊毛w A酱笑笑不说话
308 | 蔓越莓莓莓 Aru 小shin Gintoki_JF
309 | Pklala12 Aru 小shin 复仇女王
310 | 斯卡蕾特丶红衣 暴走の龙猫 发癫的四叶草 惜夏
311 | 狼獬君 缄默白雷 Suntik 冰狼酱
312 | 疯子mAple 気晴らしする 节操の灵灵梦 AME_AOI
313 | bellicose小殇 Dove♪神痕灬 Gintoki_JF 哔哔哔哩哔哩
314 | Pklala12 Dove♪神痕灬 复仇女王 哔哔哔哩哔哩
315 | 一方羊咩 ☆萝卜糕☆ ☆Siesta 純潔的鬼畜姬
316 | 三查口十 一方羊咩 ☆萝卜糕☆ ☆Siesta
317 | 爱的学长六道二落 一方羊咩 ☆Siesta 純潔的鬼畜姬
318 | 上条妹红 Nic酱Inthis Mr甜点 新堂爱卖萌
319 | 上条妹红 Nic酱Inthis Mr甜点 毒舌小猫萝
320 | 上条妹红 Nic酱Inthis onlyboy 栁道Seto
321 | 上条妹红 海带J SliowJoker 新堂爱卖萌
322 | 上条妹红 Nic酱Inthis 毒舌小猫萝 金闪闪のInori
323 | 上条妹红 Nic酱Inthis 栁道Seto 金闪闪のInori
324 | 上条妹红 灬由歌 栁道Seto 金闪闪のInori
325 | 上条妹红 Jack君 栁道Seto 金闪闪のInori
326 | 夏夜の行方 运营 某坑爹的4S君 古明地lzh
327 | NorviNS松鼠 Cee酱 WXPPt. 肥鸭DUCK
328 | SonicoQ 复仇女王 756酱紫 LenRinFuck
329 | Angel_Accelerator Dove♪神痕灬 复仇女王 LenRinFuck
330 | SonicoQ Shoklos Dove♪神痕灬 LenRinFuck
331 | 冥界の亡靈 Dove♪神痕灬 冰水地缚灵 蓝羽天梦
332 | 东城绫的忧郁 Dove♪神痕灬 冰水地缚灵 蓝羽天梦
333 | 羊姐 梨斗渣 冰水地缚灵 蓝羽天梦
334 | 羊姐 小呆君 冰水地缚灵 樱庭紫月
335 | 羊姐 冥界の亡靈 冰水地缚灵 蓝羽天梦
336 | 羊姐 东城绫的忧郁 冰水地缚灵 蓝羽天梦
337 | 羊姐 蓝羽天梦 冰水地缚灵 逝梦
338 | 粽子Timaki _高能君_ 受小兔 小白Pikiyo
339 | 粽子Timaki _高能君_ 火焰之洲 小白Pikiyo
340 | ntmarie adgnn 珠峰喵 乐子酱丢节操
341 | Guhan ntmarie adgnn 乐子酱丢节操
342 | ntmarie adgnn 珠峰喵 Epic16
343 | Guhan ntmarie adgnn Epic16
344 | a17大帝 Guhan ntmarie 玛丽之神004
345 | ntmarie 珠峰喵 小帅喵 8⑩3·X·切糕
346 | ntmarie 小帅喵 8⑩3·X·切糕 玛丽之神004
347 | 卖萌的由乃酱 AKA冰丽酱 肥鸭DUCK 南云霞丶
348 | Gintoki_JF AKA冰丽酱 肥鸭DUCK 发癫的四叶草
349 | Gintoki_JF AKA冰丽酱 肥鸭DUCK 南云霞丶
350 | NorviNS松鼠 Cee酱 肥鸭DUCK U2一美是绝配
351 | Gintoki_JF Dove♪神痕灬 肥鸭DUCK 南云霞丶
352 | Aru -infinity. Dove♪神痕灬 Falling捏捏
353 | 从侧面上www 西行寺·爱多多姐 神秘基佬 清蒸秘制油条
354 | 水箱 润大爷 奥田紅茶子 天然纯种受
355 | 愈雨 蓝受 樱鸠十六夜 大芋子
356 | cherryff 愈雨 樱鸠十六夜 大芋子
357 | cherryff 愈雨 时间分秒都是钱 大芋子
358 | 小虚☆ 时间分秒都是钱 相葉忍 大芋子
359 | luckAMV Tsuki-bito-牛牛 ァKatherine 桥西
360 | Shepherd小牧 doraiba 珠峰喵 杂菌
361 | 杂菌 doraiba 小帅喵 小白Pikiyo
362 | 米酒酱 小受C零酱 小帅喵 珠峰喵
363 | 暮色TOP 小受C零酱 小帅喵 珠峰喵
364 | 米娜丶 珠峰喵 小帅喵 8⑩3·X·切糕
365 | 珠峰喵 小帅喵 不会起名的狂虎 8⑩3·X·切糕
366 | 冰瞳魔羽 残音·X·慕斯 小帅喵 珠峰喵
367 | 8⑩3·X·切糕 Q少 小帅喵 玛丽之神004
368 | Alessa0 米酒酱 小帅喵 杂菌
369 | 米酒酱 珠峰喵 小帅喵 杂菌
370 | 番外篇 草渲木染 方瓜努力向前中 郁の周周
371 | 番外篇 kensei酱 二米明子 郁の周周
372 | Dove♪神痕灬 慕子羽 复仇女王 掌心の羁绊
373 | 阿鲁巴♂SHiNoo 尼尔Minori 全废の胤蛇君 vertigo
374 | 声优界第一美腿 Imiyu 不明物丶 夜靖
375 | Mell君 AA8 Dove♪神痕灬 KingOfHarem
376 | littledango 望天晓 Dove♪神痕灬 撒加木
377 | AA8 Gintoki_JF Dove♪神痕灬 南云霞丶
378 | 蓝羽天梦 Gintoki_JF Dove♪神痕灬 VoIceQ
379 | 郁闷de月影 Nic酱Inthis VoIceQ Dove♪神痕灬
380 | 郁闷de月影 Dove♪神痕灬 一条平行线。 伪信徒
381 | 东城绫的忧郁 Gintoki_JF Dove♪神痕灬 蓝羽天梦
382 | 橘丶万里花酱 东城绫的忧郁 Dove♪神痕灬 Xmyz.G
383 | 郁闷de月影 FATE零零七 Dove♪神痕灬 橘丶万里花酱
384 | 橘丶万里花酱 SymPny Dove♪神痕灬 掌心の羁绊
385 | 白夜轨迹 望天晓 Dove♪神痕灬 Falling捏捏
386 | Raito_喵君 望天晓 Dove♪神痕灬 Falling捏捏
387 | 望天晓 Dove♪神痕灬 Falling捏捏 VoIceQ
388 | Gintoki_JF Dove♪神痕灬 Falling捏捏 毛毛菌殿下
389 | Dove♪神痕灬 Falling捏捏 Xmyz.G 掌心の羁绊
390 | 二米明子 毛毛菌殿下 Dove♪神痕灬 复仇女王
391 | littledango 毛毛菌殿下 Dove♪神痕灬 复仇女王
392 | 毛毛菌殿下 Dove♪神痕灬 复仇女王 XD小东
393 | 冥界の亡靈 Dove♪神痕灬 复仇女王 毛毛菌殿下
394 | 毛毛菌殿下 Dove♪神痕灬 复仇女王 掌心の羁绊
395 | SymPny Dove♪神痕灬 复仇女王 掌心の羁绊
396 | FATE零零七 凤凰院喵喵 Dove♪神痕灬 伪信徒
397 | FATE零零七 凤凰院喵喵 Dove♪神痕灬 Xmyz.G
398 | 郁闷de月影 Aru VoIceQ Dove♪神痕灬
399 | Aru 鑚石星痕 Dove♪神痕灬 伪信徒
400 | Aru Gintoki_JF Dove♪神痕灬 请输入姓名:
401 | 郁闷de月影 Aru Dove♪神痕灬 请输入姓名:
402 | Raito_喵君 Aru Dove♪神痕灬 Falling捏捏
403 | 流动の黑暗 SymPny Dove♪神痕灬 复仇女王
404 | SonicoQ FATE零零七 Dove♪神痕灬 otaku90
405 | SonicoQ 鑚石星痕 Dove♪神痕灬 otaku90
406 | SonicoQ 鑚石星痕 Dove♪神痕灬 玛莎烈啤酒
407 | SonicoQ 复仇女王 756酱紫 XD小东
408 | SonicoQ Aru 请输入姓名: 听云谪夜雨
409 | Q小君 星天飞舞 要小心有毒的橙汁 既阔且卡
410 | 俞景明 欧洲核子研究组织 CmosVoc暴走F AME_AOI
411 | GirlsMadClub 蔓越莓莓莓 Aru VoIceQ
412 | Aru Gintoki_JF 忘卿 发癫的四叶草
413 | Aru Gintoki_JF KarSa 桥西
414 | Aru SgenL 深海中的原石君 Xmyz.G
415 | FATE零零七 Aru 伪信徒 Mirai MAD Team
416 | RN、 Aru SgenL Mirai MAD Team
417 | Aru nobitanobi Falling捏捏 Xmyz.G
418 | Aru 特莱嘻嘻嘻 Falling捏捏 Xmyz.G
419 | 伪信徒 Aru 磕睡熊 Mirai MAD Team
420 | Aru 磕睡熊 Xmyz.G Mirai MAD Team
421 | SgenL FATE零零七 凤凰院喵喵 Xmyz.G
422 | TUNO桐音 Ceekyo Ddickky ZOMiG
423 | chacha 小猫Append ZOMiG 阿紫紫爱世界
424 | 小然参上 小小☆精灵 YF君 Fr4y
425 | 小然参上 小小☆精灵 新堂爱卖萌 Anthony☆
426 | 新堂爱卖萌 小然参上 小小☆精灵 谈情不说爱
427 | 小然参上 小小☆精灵 YF君 魔王之兵
428 | 影轮S 小小☆精灵 新堂爱卖萌 喵团酱
429 | Monday丶M 小然参上 小小☆精灵 Ajay殿下
430 | Monday丶M 小然参上 小小☆精灵 Anthony☆
431 | Monday丶M 小然参上 小小☆精灵 魔王之兵
432 | Monday丶M 小然参上 小小☆精灵 喵团酱
433 | 小伞一把 肥皂菌丨珉珉的猫咪丨 黑化零度 Shepherd小牧
434 | ☆来来子 黑化零度 冷释 Shepherd小牧
435 | ☆来来子 黑化零度 流川菌 Shepherd小牧
436 | 涵晴 小伞一把 ☆来来子 黑化零度
437 | 傲娇麒儿 维希桑 ☆来来子 黑化零度
438 | 涵晴 小伞一把 黑化零度 杂菌
439 | 潜移默化♀浅姨磨花 JUSF GhostFinal 松江府人
440 | nobitanobi 复仇女王 毛毛菌殿下 XD小东
441 | o织田o -花花- -yuuji- 摸
442 | 爱索隆的南酱 晋玄 ☆Siesta 純潔的鬼畜姬
443 | Fin5aL 晋玄 棠雪儿 ☆Siesta
444 | 椛祭 晋玄 棠雪儿 ☆Siesta
445 | 隣る人 晋玄 棠雪儿 大叔球
446 | 野の穹妹 我是笨蛋么 我是白痴么 萌樱の醉生梦死
447 | 胧月の舞 喵炭 潜行的晚月 纵横四海の梵
448 | nobitanobi Falling捏捏 毛毛菌殿下 XD小东
449 | 蔓越莓莓莓 望天晓 Falling捏捏 VoIceQ
450 | 9·Volt Gintoki_JF Falling捏捏 暴走の龙猫
451 | 9·Volt 特莱嘻嘻嘻 Gintoki_JF Falling捏捏
452 | 特莱嘻嘻嘻 9·Volt Falling捏捏 Xmyz.G
453 | 蔓越莓莓莓 空蝉与诗 望天晓 Falling捏捏
454 | Raito_喵君 空蝉与诗 望天晓 Falling捏捏
455 | 特莱嘻嘻嘻 空蝉与诗 Falling捏捏 Xmyz.G
456 | 特莱嘻嘻嘻 发癫的四叶草 Falling捏捏 掌心の羁绊
457 | 特莱嘻嘻嘻 Falling捏捏 Xmyz.G 掌心の羁绊
458 | CJ木 糜酱 柚小悶 世界の終わり
459 | 二咩www 可爱鱼摆摆 Shepherd小牧 杂菌
460 | 涵晴 xkd青鱼 小伞一把 杂菌
461 | 米酒酱 珠峰喵 無小豆 杂菌
462 | xkd青鱼 珠峰喵 無小豆 杂菌
463 | AdamXL07 随便点进来就注册了 粒粒梦想 冻酸奶泡芙
464 | Gintoki_JF AKA冰丽酱 发癫的四叶草 游戏基×
465 | Gintoki_JF AKA冰丽酱 南云霞丶 游戏基×
466 | 七海爱衣 东城绫的忧郁 AKA冰丽酱 卖萌的由乃酱
467 | SliowJoker 海带J Chitanda·Eru 新堂爱卖萌
468 | 海带J Chitanda·Eru 新堂爱卖萌 谈情不说爱
469 | 三查口十 西泠 小倩不干正事 胖哒哒卜
470 | 幻Se初半 小倩不干正事 西泠 胖哒哒卜
471 | 枫踏岚 子墨散人 皮皮桑 雨云。
472 | 三查口十 棠雪儿 Soichanan ☆Siesta
473 | 蛟龙Tomy 鬼王陆行 皮w蛋 某工口的图书馆
474 | 蛟龙Tomy 一飞 皮w蛋 某工口的图书馆
475 | 蛟龙Tomy 一飞 野游侠 某工口的图书馆
476 | 二米明子 溺水金鱼 Mr甜点 Bili的非日常
477 | 章鱼阿廿 左拥髭右抱眉的淫家 Arthur°墨 吃榴莲の楔子
478 | 润大爷 奥田紅茶子 天然纯种受 汉堡肉
479 | 小然参上 掌心の羁绊 毛毛菌殿下 发癫的四叶草
480 | FATE零零七 橘丶万里花酱 掌心の羁绊 代号T
481 | Levi羽狐 夏目キキ 不明物丶 夜靖
482 | GirlsMadClub 空蝉与诗 King_doll 忘卿
483 | 空蝉与诗 King_doll 忘卿 Gintoki_JF
484 | 东城绫的忧郁 空蝉与诗 King_doll Gintoki_JF
485 | 东城绫的忧郁 空蝉与诗 特莱嘻嘻嘻 Xmyz.G
486 | 东城绫的忧郁 空蝉与诗 King_doll Xmyz.G
487 | 涵晴 ☆来来子 小伞一把 xkd青鱼
488 | ☆来来子 某幻君 珠峰喵 吉原凉子
489 | ☆来来子 小受C零酱 珠峰喵 吉原凉子
490 | 番外篇 風雪黄昏 草渲木染 方瓜努力向前中
491 | 番外篇 草渲木染 Fake丶Wings 谈情不说爱
492 | 破车车 糜酱 柚小悶 CJ木
493 | lyle司 喵Melon LOKO&洛可 苏筱晗
494 | 某工口的图书馆 一飞 楼桀 皮w蛋
495 | mlsao_SF Q少 珠峰喵 8⑩3·X·切糕
496 | mlsao_SF Q少 珠峰喵 丶苹果
497 | mlsao_SF 腰小果 珠峰喵 丶苹果
498 | 莫烟云 宿の魔·鬼鬼 windszhen 希卡木蛋蛋
499 | 宿の魔·鬼鬼 夜靖 windszhen 希卡木蛋蛋
500 | 胯下 腹黑混血攻 天然纯种受 汉堡肉
501 | 小伞一把 8⑩3·X·切糕 Q少 玛丽之神004
502 | Suntik 缄默白雷 饥渴狂魔池才君 冰狼酱
503 | 野の穹妹 我是白痴么 shinn杏仁 萌樱の醉生梦死
504 | 小泽玛利亮 望天晓 橘丶万里花酱 毛毛菌殿下
505 | ☆Siesta 水寒君 软萌萌阿滩滩 棠雪儿
506 | 阿卡凌 孔明酱 轩渊 音羽KARAS夜
507 | 梨斗渣 钱妹.mp4 ECH渣剪组 Ripper.J
508 | 某工口的图书馆 楼桀 鬼王陆行 皮w蛋
509 | 爱的学长六道二落 隣る人 棠雪儿 大叔球
510 | 二米明子 某科学的cc君 新堂爱卖萌 黑雪之姬
511 | 二米明子 biu点 某科学的cc君 黑雪之姬
512 | Floating·Dream biu点 某科学的cc君 黑雪之姬
513 | 凡人G 某科学的cc君 新堂爱卖萌 黑雪之姬
514 | 伍同学_ 南云霞丶 节操の灵灵梦 新手魔理沙
515 | AA8 南云霞丶 节操の灵灵梦 新手魔理沙
516 | 伍同学_ 斯卡蕾特丶红衣 南云霞丶 新手魔理沙
517 | ☆Siesta 柒月一日菌 软萌萌阿滩滩 棠雪儿
518 | 隣る人 软萌萌阿滩滩 妹子处对象不 棠雪儿
519 | Mr甜点 KingOfHarem 歼灭小天使 路过的飒之天使
520 | yCsVFX AA8 MrMIKI 路过的飒之天使
521 | Gintoki_JF 发癫的四叶草 游戏基× 暴走の龙猫
522 | Gintoki_JF 南云霞丶 游戏基× 暴走の龙猫
523 | 伍同学_ 斯卡蕾特丶红衣 南云霞丶 暴走の龙猫
524 | 万人迷の暖姐姐 Guhan 冰瞳魔羽 G4⑨
525 | 万人迷の暖姐姐 Guhan adgnn 冰瞳魔羽
526 | 万人迷の暖姐姐 Guhan adgnn Epic16
527 | 亦澄 傲娇麒儿 karin的幸福理论 Shepherd小牧
528 | 椛祭 爱的学长六道二落 棠雪儿 ☆Siesta
529 | 傲娇麒儿 LOVENIKI 可爱鱼摆摆 Shepherd小牧
530 | 傲娇麒儿 LOVENIKI Shepherd小牧 xkd青鱼
531 | 雨泪飘零 南云霞丶 気晴らしする AME_AOI
532 | 雨泪飘零 南云霞丶 谈情不说爱 気晴らしする
533 | 明哥酱 末路人十香 Sean式 阿浓酱
534 | AB强强YOUNG 小然参上 bili炮爷 柠檬肉酱
535 | 二米明子 小然参上 新堂爱卖萌 风の缘
536 | AB强强YOUNG 胖子stan 小然参上 柠檬肉酱
537 | 胯下 腹黑混血攻 爱翼 天然纯种受
538 | 胯下 腹黑混血攻 爱翼 思月如故
539 | 胯下 爱拔のちくび 小馒头恰恰 天然纯种受
540 | 小伞一把 Q少 珠峰喵 8⑩3·X·切糕
541 | 世界破坏时 xiaotuji 里维无ID 高尾桑
542 | 宿の魔·鬼鬼 xiaotuji 里维无ID 高尾桑
543 | Marioマリオ 俺酱 洛萱 RaJor
544 | 愈雨 栗子酥 蓝受 久嘉
545 | cherryff 栗子酥 时间分秒都是钱 病娇的软软琦
546 | 栗子酥 小虚☆ 时间分秒都是钱 久嘉
547 | 久嘉 时间分秒都是钱 相葉忍 黑旁白
548 | Floating·Dream 本多二代二代TF ied丶Knife 谈情不说爱
549 | 小伞一把 米酒酱 小受C零酱 珠峰喵
550 | 久嘉 小虚☆ 时间分秒都是钱 相葉忍
551 | 木小尘0823 久嘉 小虚☆ 时间分秒都是钱
552 | 暮色TOP 某幻君 珠峰喵 聪明机智榴莲子
553 | 冰瞳魔羽 zxctcsx 珠峰喵 雨藤
554 | 小伞一把 米酒酱 Mc丶节操君 珠峰喵
555 | XO-清花 以天为名的NANA 夜夜酱丶 优子酱
556 | 笨蛋诗人 Mr甜点 biu点 Phantom诺
557 | 笨蛋诗人 Mr甜点 某科学的cc君 biu点
558 | 笨蛋诗人 Mr甜点 biu点 言叶おわた
559 | 笨蛋诗人 Mr甜点 某不科学的旺星人 某科学的cc君
560 | 笨蛋诗人 Mr甜点 某不科学的旺星人 言叶おわた
561 | CJ木 77323xd43 糜酱 柚小悶
562 | kensei酱 明哥酱 新堂爱卖萌 纯洛
563 | SliowJoker 新堂爱卖萌 オレンジ☆ 纯洛
564 | 海带J SliowJoker 新堂爱卖萌 オレンジ☆
565 | 伍同学_ 游戏基× 南云霞丶 暴走の龙猫
566 | 卖萌的由乃酱 游戏基× 南云霞丶 暴走の龙猫
567 | 伍同学_ 南云霞丶 节操の灵灵梦 暴走の龙猫
568 | 卖萌的由乃酱 暴走の龙猫 南云霞丶 AME_AOI
569 | 気晴らしする 南云霞丶 节操の灵灵梦 AME_AOI
570 | 暴走の龙猫 南云霞丶 节操の灵灵梦 AME_AOI
571 | 愈雨 久嘉 时间分秒都是钱 木小尘0823
572 | 木小尘0823 久嘉 时间分秒都是钱 bktszy
573 | 岁钥丶锍哖 気晴らしする 节操の灵灵梦 AME_AOI
574 | 岁钥丶锍哖 暴走の龙猫 节操の灵灵梦 AME_AOI
575 | 二米明子 某不科学的旺星人 Mr甜点 言叶おわた
576 | Mr甜点 某不科学的旺星人 歼灭小天使 言叶おわた
577 | BTM 茶米(dav) 鳴櫻 yoyo幫尼
578 | 宿の魔·鬼鬼 摸鱼的柠檬籽 windszhen 夜靖
579 | 宿の魔·鬼鬼 Shoka゛ 不明物丶 Phoenixql
580 | 宿の魔·鬼鬼 xiaotuji Shoka゛ 不明物丶
581 | 白桃子烟 南宫骅 爱翼 kay1640
582 | 摸鱼的柠檬籽 射命肉丸QCNZ6J windszhen 凌骸LEVI
583 | 请叫我学长sama XO-清花 以天为名的NANA 夜夜酱丶
584 | LAM1992 流川菌 白卡纸ShiroHana 大好人k紫
585 | 玉米是只大脸怪 爱拔のちくび 天然纯种受 豆沙包子酱
586 | Mr甜点 凡人G 溺水金鱼 新堂爱卖萌
587 | Mr甜点 凡人G 新堂爱卖萌 纯洛
588 | 凡人G 丶Almost 新堂爱卖萌 纯洛
589 | Mr甜点 凡人G 某科学的cc君 新堂爱卖萌
590 | 二米明子 风の缘 Mr甜点 言叶おわた
591 | Mr甜点 风の缘 歼灭小天使 言叶おわた
592 | 静音喵 Mr甜点 风の缘 言叶おわた
593 | Mr甜点 不笑の猫猫 溺水金鱼 言叶おわた
594 | 俺酱 洛萱 云呆 RaJor
595 | Mr甜点 鳥T使 某科学的cc君 新堂爱卖萌
596 | 潇潇Lisa Shepherd小牧 白泽小羽 xkd青鱼
597 | 律音 潇潇Lisa 白泽小羽 xkd青鱼
598 | 傲娇麒儿 废柴の琉璃酱 Shepherd小牧 xkd青鱼
599 | 魅喵喵 xiaotuji 不明物丶 夜靖
600 | 傲娇麒儿 废柴の琉璃酱 可爱鱼摆摆 Shepherd小牧
601 | iki木木 里维无ID 不明物丶 夜靖
602 | iki木木 Imiyu 不明物丶 夜靖
603 | 二米明子 辣手 Mr甜点 溺水金鱼
604 | 世界破坏时 伪善的予言 windszhen 鱼娘YY
605 | Imiyu 世界破坏时 伪善的予言 windszhen
606 | 二米明子 某科学的cc君 Mr甜点 biu点
607 | 静音喵 Mr甜点 某科学的cc君 风の缘
608 | Floating·Dream 某科学的cc君 Mr甜点 biu点
609 | Floating·Dream 溺水金鱼 Mr甜点 biu点
610 | 楠依墨 Floating·Dream 本多二代二代TF 黑月の宅男
611 | 摸鱼的柠檬籽 windszhen 壳子丨想被兵长踢脸 夜靖
612 | Mr甜点 新堂爱卖萌 歼灭小天使 风の缘
613 | 二米明子 Mr甜点 新堂爱卖萌 溺水金鱼
614 |
--------------------------------------------------------------------------------
/bilibili-po/分析/关注圈/5.txt:
--------------------------------------------------------------------------------
1 | 西行寺·爱多多姐 傘閣 西方良目仙人掌 meiling 20024JoK
2 | 正经战队 林即中 チャージマン研! 西方良目仙人掌 meiling
3 | abcdjx LF先辈 傘閣 西方良目仙人掌 meiling
4 | 深海庞贝 77323xd43 糜酱 噗通酱 CJ木
5 | 深海庞贝 77323xd43 糜酱 CJ木 她
6 | 深海庞贝 世界の終わり 西兰花的观测者 兰豆子 她
7 | 小透明BAKA Lendll Magus EPM にししししー
8 | 小透明BAKA Caaaaarrot Magus EPM TSA
9 | 小透明BAKA にししししー Magus EPM TSA
10 | 新华里业务员 Lendll SDRES EPM Vicks
11 | 神尾光临 新华里业务员 SDRES EPM Vicks
12 | 亚月 kikou 妄想世界協會 Chokeslam 卷不起树叶的妖怪
13 | 玉米姬 Lendll SDRES 新华里业务员 Vicks
14 | Aru Gintoki_JF Dove♪神痕灬 wearsky 东城绫的忧郁
15 | SonicoQ wywzyx2 Dove♪神痕灬 wearsky 复仇女王
16 | SonicoQ 复仇女王 Dove♪神痕灬 wearsky LenRinFuck
17 | 玛莎烈啤酒 luckAMV wearsky 天蓝梦境 Satori旅人
18 | SonicoQ wywzyx2 Dove♪神痕灬 wearsky 何满子
19 | SonicoQ LenRinFuck Dove♪神痕灬 wearsky 何满子
20 | Aru 世界の敌 wearsky 天蓝梦境 Satori旅人
21 | luckAMV 世界の敌 wearsky 天蓝梦境 Satori旅人
22 | 复仇女王 LenRinFuck Dove♪神痕灬 wearsky 哈露ちゃん
23 | SonicoQ wywzyx2 wearsky lucifel 复仇女王
24 | SonicoQ wywzyx2 wearsky lucifel 何满子
25 | ここにいるよ luckAMV oneways wearsky 天蓝梦境
26 | ここにいるよ oneways wearsky 天蓝梦境 何满子
27 | 宿命传说 luckAMV KoKky wearsky Magus
28 | SonicoQ Aru wearsky 天蓝梦境 Magus
29 | Aru 世界の敌 wearsky 天蓝梦境 Magus
30 | 复仇女王 哈露ちゃん Dove♪神痕灬 wearsky Magus
31 | にししししー Dove♪神痕灬 wearsky 白羽沉 Magus
32 | 复仇女王 にししししー Dove♪神痕灬 wearsky Magus
33 | 复仇女王 luckAMV にししししー wearsky Magus
34 | 傘閣 比利.海林顿 林即中 meiling 夜总会来的
35 | Aru nobitanobi Magus Xmyz.G 复仇女王
36 | 橘丶万里花酱 Dove♪神痕灬 Magus Xmyz.G 掌心の羁绊
37 | 橘丶万里花酱 鑚石星痕 Dove♪神痕灬 Magus Xmyz.G
38 | 请输入姓名: Aru Dove♪神痕灬 Magus Xmyz.G
39 | 仓米丁 橘丶万里花酱 望天晓 Dove♪神痕灬 Magus
40 | 仓米丁 橘丶万里花酱 Dove♪神痕灬 Magus 掌心の羁绊
41 | SonicoQ Dove♪神痕灬 Magus 橘丶万里花酱 掌心の羁绊
42 | SonicoQ 鑚石星痕 Dove♪神痕灬 Magus 橘丶万里花酱
43 | 请输入姓名: SonicoQ Aru Dove♪神痕灬 Magus
44 | 兰豆子 白羽沉 Magus 面了了了条 她
45 | 兰豆子 西兰花的观测者 Magus 白羽沉 她
46 | 橘丶万里花酱 Caaaaarrot Magus Xmyz.G 掌心の羁绊
47 | 橘丶万里花酱 鑚石星痕 Caaaaarrot Magus Xmyz.G
48 | Aru 鑚石星痕 Caaaaarrot Magus Xmyz.G
49 | 悠々閑々 ビリくん Magus 白羽沉 兰豆子
50 | 絶体延命 ビリくん Magus 白羽沉 谷亮子
51 | ここにいるよ luckAMV DigiCat Caaaaarrot Magus
52 | 宿命传说 luckAMV 世界の敌 Magus ⑨⑨酱
53 | 宿命传说 luckAMV 世界の敌 Caaaaarrot Magus
54 | ここにいるよ luckAMV 世界の敌 Caaaaarrot Magus
55 | 复仇女王 Dove♪神痕灬 Magus 掌心の羁绊 にししししー
56 | Z·DARK Aru 鑚石星痕 Caaaaarrot Magus
57 | Z·DARK Aru Caaaaarrot Magus 绯色の尼禄
58 | Z·DARK SonicoQ Magus lucifel 起起
59 | ここにいるよ 茕茕(up主≠作者) 小透明BAKA 世界の敌 にししししー
60 | 真鱼 ここにいるよ 小透明BAKA 茕茕(up主≠作者) にししししー
61 | 豪俊影视 06御前 黄特首 lubyyy 御剑怜侍
62 | Dove♪神痕灬 望天晓 啪嗒啪嗒EDR Falling捏捏 白海狸
63 | Dove♪神痕灬 望天晓 啪嗒啪嗒EDR オルゴール littledango
64 | Dove♪神痕灬 白海狸 啪嗒啪嗒EDR Falling捏捏 哈露ちゃん
65 | oneways 啪嗒啪嗒EDR 复仇女王 オルゴール 哈露ちゃん
66 | 烤夜雀 kikou 绝望是梦想的初章 妄想世界協會 师酱
67 | kikou 绝望是梦想的初章 incub8or 妄想世界協會 师酱
68 | P_ch_WH zhanghan603 小字辈 ICEwiimaker DickLi
69 | Zumn zhanghan603 小字辈 ICEwiimaker DickLi
70 | 若虫 妄想世界協會 切肉君 Chokeslam 水纹与熏风
71 | ここにいるよ 96猫@141.2cm 世界の敌 SuperBrother にししししー
72 | 真鱼 96猫@141.2cm 白羽沉 SuperBrother にししししー
73 | 真鱼 ここにいるよ 96猫@141.2cm SuperBrother にししししー
74 | 深籣 ここにいるよ オルゴール 何满子 天蓝梦境
75 | 深籣 ここにいるよ 96猫@141.2cm 世界の敌 にししししー
76 | 深籣 ここにいるよ オルゴール 雪丿下雪乃 luckAMV
77 | 深籣 ここにいるよ オルゴール 何满子 雪丿下雪乃
78 | lubyyy 23夜 西行寺·爱多多姐 meiling 古明地lzh
79 | 夏夜の行方 lubyyy 23夜 meiling 古明地lzh
80 | 恋之八卦炉 lubyyy 23夜 meiling Dale Yuan
81 | 运营 恋之八卦炉 23夜 西行寺·爱多多姐 meiling
82 | 夏夜の行方 运营 恋之八卦炉 23夜 meiling
83 | 夏夜の行方 恋之八卦炉 lubyyy 23夜 meiling
84 | 烤夜雀 妄想世界協會 恋之八卦炉 893姐贵 meiling
85 | 傘閣 恋之八卦炉 西行寺·爱多多姐 meiling 20024JoK
86 | 穆索尔司机 恋之八卦炉 西行寺·爱多多姐 meiling 20024JoK
87 | 穆索尔司机 incub8or 西行寺·爱多多姐 meiling 20024JoK
88 | incub8or 西行寺·爱多多姐 meiling 古明地lzh 20024JoK
89 | 傘閣 LF先辈 林即中 meiling 豪俊影视
90 | LF先辈 林即中 incub8or 西行寺·爱多多姐 meiling
91 | Dove♪神痕灬 Z·DARK 流动の黑暗 找到梦想的咩咩酱丶 孤月十寒
92 | Dove♪神痕灬 Z·DARK Aru 找到梦想的咩咩酱丶 Pklala12
93 | Dove♪神痕灬 Z·DARK 流动の黑暗 找到梦想的咩咩酱丶 LenRinFuck
94 | Z·DARK Aru オルゴール 天蓝梦境 SonicoQ
95 | Z·DARK オルゴール 何满子 天蓝梦境 SonicoQ
96 | Z·DARK 破碎の杯子 Dove♪神痕灬 Aru SonicoQ
97 | 寂寞的狂热 Z·DARK 无聊啊啊啊啊 オルゴール LenRinFuck
98 | Z·DARK オルゴール 何满子 lucifel SonicoQ
99 | 四方SR Z·DARK Aru Dove♪神痕灬 起起
100 | Aru oneways 特莱嘻嘻嘻 Falling捏捏 桥西
101 | -infinity. oneways 特莱嘻嘻嘻 Aru Falling捏捏
102 | ここにいるよ oneways オルゴール 何满子 天蓝梦境
103 | -infinity. oneways 特莱嘻嘻嘻 Falling捏捏 哈露ちゃん
104 | 特莱嘻嘻嘻 oneways 橘丶万里花酱 オルゴール 哈露ちゃん
105 | SonicoQ wywzyx2 オルゴール lucifel 复仇女王
106 | 小shin BD播放器 オルゴール lucifel 复仇女王
107 | SonicoQ wywzyx2 オルゴール 何满子 lucifel
108 | 小shin 起起 オルゴール lucifel 恋の镇魂曲
109 | 梨斗渣 特莱嘻嘻嘻 橘丶万里花酱 Xmyz.G 雪丿下雪乃
110 | 特莱嘻嘻嘻 橘丶万里花酱 掌心の羁绊 雪丿下雪乃 Xmyz.G
111 | Xmyz.G Dove♪神痕灬 复仇女王 雪丿下雪乃 掌心の羁绊
112 | FATE零零七 Aru Dove♪神痕灬 Xmyz.G 雪丿下雪乃
113 | Aru Dove♪神痕灬 复仇女王 雪丿下雪乃 Xmyz.G
114 | Aru -infinity. 特莱嘻嘻嘻 SugerTAMA 雪丿下雪乃
115 | 特莱嘻嘻嘻 橘丶万里花酱 オルゴール 雪丿下雪乃 掌心の羁绊
116 | 橘丶万里花酱 Dove♪神痕灬 オルゴール 雪丿下雪乃 掌心の羁绊
117 | 掌心の羁绊 Dove♪神痕灬 オルゴール 雪丿下雪乃 复仇女王
118 | Aru Dove♪神痕灬 オルゴール 雪丿下雪乃 复仇女王
119 | 特莱嘻嘻嘻 橘丶万里花酱 オルゴール 雪丿下雪乃 哈露ちゃん
120 | 橘丶万里花酱 Dove♪神痕灬 オルゴール 雪丿下雪乃 哈露ちゃん
121 | 复仇女王 Dove♪神痕灬 オルゴール 雪丿下雪乃 哈露ちゃん
122 | 某可牌橘子汽水 96猫@141.2cm なの名乃 Lendll にししししー
123 | ☆玉玉子 小伞一把 暮色TOP Mc丶节操君 珠峰喵
124 | ☆玉玉子 某幻君 暮色TOP Mc丶节操君 珠峰喵
125 | ☆玉玉子 ☆来来子 小伞一把 珠峰喵 xkd青鱼
126 | ☆玉玉子 傲娇麒儿 ☆来来子 珠峰喵 xkd青鱼
127 | ☆玉玉子 亦澄 ☆来来子 ☆SORA子 傲娇麒儿
128 | ☆玉玉子 亦澄 ☆来来子 傲娇麒儿 xkd青鱼
129 | ☆玉玉子 xkd青鱼 小伞一把 珠峰喵 杂菌
130 | ☆玉玉子 傲娇麒儿 xkd青鱼 珠峰喵 杂菌
131 | ☆玉玉子 亦澄 傲娇麒儿 xkd青鱼 杂菌
132 | ☆玉玉子 小伞一把 ☆来来子 黑化零度 珠峰喵
133 | ☆玉玉子 傲娇麒儿 ☆来来子 黑化零度 珠峰喵
134 | ☆玉玉子 小伞一把 黑化零度 珠峰喵 杂菌
135 | ☆玉玉子 傲娇麒儿 黑化零度 珠峰喵 杂菌
136 | ☆玉玉子 xkd青鱼 小伞一把 珠峰喵 疾風醬
137 | 东城绫的忧郁 橘丶万里花酱 特莱嘻嘻嘻 オルゴール 哈露ちゃん
138 | 橘丶万里花酱 东城绫的忧郁 Dove♪神痕灬 オルゴール 哈露ちゃん
139 | LenRinFuck nobitanobi 复仇女王 オルゴール 哈露ちゃん
140 | LenRinFuck Dove♪神痕灬 复仇女王 オルゴール 哈露ちゃん
141 | 烤夜雀 绝望是梦想的初章 万景幕 Chokeslam 绝顶油条
142 | ここにいるよ luckAMV DigiCat Caaaaarrot オルゴール
143 | 妄想世界協會 穆索尔司机 incub8or 西行寺·爱多多姐 切肉君
144 | 绝望是梦想的初章 清蒸秘制油条 incub8or 西行寺·爱多多姐 神秘基佬
145 | 水滴Kstone CC子 96猫@141.2cm ビリくん 白羽沉
146 | 火雨の妖精 卖萌的由乃酱 AKA冰丽酱 南云霞丶 游戏基×
147 | 白海狸 你看见我的id了 望天晓 Falling捏捏 毛毛菌殿下
148 | 你看见我的id了 毛毛菌殿下 发癫的四叶草 Falling捏捏 掌心の羁绊
149 | 你看见我的id了 -infinity. Falling捏捏 毛毛菌殿下 发癫的四叶草
150 | 你看见我的id了 -infinity. 望天晓 Falling捏捏 毛毛菌殿下
151 | FATE零零七 Caaaaarrot 掌心の羁绊 Xmyz.G 橘丶万里花酱
152 | Aru 鑚石星痕 Caaaaarrot Xmyz.G 結城音無
153 | 赛亚♂sya 潜移默化♀浅姨磨花 GhostFinal JUSF 哲学♂跳蝻
154 | 赛亚♂sya 潜移默化♀浅姨磨花 JUSF 哲学♂跳蝻 桐叶_tongye
155 | 妄想世界協會 恋之八卦炉 穆索尔司机 卷不起树叶的妖怪 不和谐音
156 | 妄想世界協會 恋之八卦炉 穆索尔司机 水纹与熏风 不和谐音
157 | 世界の終わり 西兰花的观测者 兰豆子 白羽沉 她
158 | 96猫@141.2cm 世界の終わり 兰豆子 白羽沉 她
159 | 特莱嘻嘻嘻 破碎の杯子 Gintoki_JF 东城绫的忧郁 ECH渣剪组
160 | 特莱嘻嘻嘻 破碎の杯子 Gintoki_JF 东城绫的忧郁 Aru
161 | 特莱嘻嘻嘻 破碎の杯子 东城绫的忧郁 Aru Xmyz.G
162 | 破碎の杯子 小然参上 Dove♪神痕灬 掌心の羁绊 毛毛菌殿下
163 | 破碎の杯子 Gintoki_JF Dove♪神痕灬 Aru VoIceQ
164 | 破碎の杯子 Gintoki_JF Dove♪神痕灬 Aru 东城绫的忧郁
165 | 破碎の杯子 Dove♪神痕灬 Aru Xmyz.G 东城绫的忧郁
166 | 特莱嘻嘻嘻 破碎の杯子 SugerTAMA 东城绫的忧郁 Aru
167 | 流动の黑暗 qi75847 Dove♪神痕灬 何满子 LenRinFuck
168 | SonicoQ wywzyx2 Dove♪神痕灬 何满子 オルゴール
169 | SonicoQ 橘丶万里花酱 天蓝梦境 七夜听雪 FATE零零七
170 | SonicoQ Aru 绯色の尼禄 天蓝梦境 FATE零零七
171 | luckAMV DigiCat オルゴール 天蓝梦境 玛莎烈啤酒
172 | 妄想世界協會 从侧面上www 西行寺·爱多多姐 Chokeslam 水纹与熏风
173 | Aru Mirai MAD Team 请输入姓名: Xmyz.G 結城音無
174 | SonicoQ Aru Mirai MAD Team 请输入姓名: 結城音無
175 | FATE零零七 HijackThis洋子 Dove♪神痕灬 掌心の羁绊 結城音無
176 | FATE零零七 Aru Dove♪神痕灬 HijackThis洋子 結城音無
177 | Aru 鑚石星痕 Dove♪神痕灬 HijackThis洋子 結城音無
178 | Aru Dove♪神痕灬 请输入姓名: Xmyz.G 結城音無
179 | SonicoQ Aru Dove♪神痕灬 请输入姓名: 結城音無
180 | Pklala12 Aru 鑚石星痕 Tsuki_神夜 結城音無
181 | SonicoQ wywzyx2 Dove♪神痕灬 复仇女王 オルゴール
182 | 特莱嘻嘻嘻 Aru 东城绫的忧郁 起起 オルゴール
183 | Aru Dove♪神痕灬 起起 オルゴール 东城绫的忧郁
184 | 绝望是梦想的初章 恋之八卦炉 小跪 Chokeslam 神秘基佬
185 | Dove♪神痕灬 Pklala12 Aru 找到梦想的咩咩酱丶 FATE零零七
186 | Mell君 新堂爱卖萌 lunacherry 歼灭小天使 KingOfHarem
187 | Mr甜点 新堂爱卖萌 lunacherry 歼灭小天使 KingOfHarem
188 | KingOfHarem Lok。 lunacherry 歼灭小天使 金闪闪のInori
189 | AA8 KingOfHarem Lok。 lunacherry 金闪闪のInori
190 | 巨大的腿毛 一只大幽灵 零九零九 华尔裘蕾 尼禄·克劳狄乌丝
191 | SonicoQ Aru SgenL 起起 冰水地缚灵
192 | Aru Dove♪神痕灬 起起 东城绫的忧郁 冰水地缚灵
193 | SonicoQ Aru Dove♪神痕灬 起起 冰水地缚灵
194 | Aru Dove♪神痕灬 冰水地缚灵 Xmyz.G 东城绫的忧郁
195 | 羊姐 梨斗渣 特莱嘻嘻嘻 冰水地缚灵 ECH渣剪组
196 | 羊姐 冥界の亡靈 SgenL 冰水地缚灵 小呆君
197 | 羊姐 小呆君 SgenL 冰水地缚灵 逝梦
198 | 羊姐 梨斗渣 特莱嘻嘻嘻 冰水地缚灵 Xmyz.G
199 | Aru -infinity. 特莱嘻嘻嘻 Falling捏捏 发癫的四叶草
200 | 望天晓 -infinity. Dove♪神痕灬 Falling捏捏 撒加木
201 | 望天晓 -infinity. Dove♪神痕灬 Falling捏捏 毛毛菌殿下
202 | 胯下 Scor aisnd 爱翼 千秋月光
203 | 玉米是只大脸怪 aisnd 爱翼 天然纯种受 千秋月光
204 | 胯下 aisnd 爱翼 天然纯种受 千秋月光
205 | 天然纯种受 胯下 爱翼 小馒头恰恰 千秋月光
206 | 绝望是梦想的初章 清蒸秘制油条 西行寺·爱多多姐 海洋AGUL 白河琴美
207 | 绝望是梦想的初章 清蒸秘制油条 西行寺·爱多多姐 神秘基佬 海洋AGUL
208 | 妄想世界協會 从侧面上www 西行寺·爱多多姐 Chokeslam 卷不起树叶的妖怪
209 | Chokeslam 从侧面上www 西行寺·爱多多姐 卷不起树叶的妖怪 神秘基佬
210 | 潜移默化♀浅姨磨花 冰镇豆豆浆 GhostFinal 哲学♂跳蝻 耶Aya叁
211 | Pklala12 Aru 绯色の尼禄 Tsuki_神夜 FATE零零七
212 | tykuyh doraiba 小帅喵 珠峰喵 杂菌
213 | Q少 冰瞳魔羽 珠峰喵 小帅喵 8⑩3·X·切糕
214 | 羊姐 梨斗渣 特莱嘻嘻嘻 橘丶万里花酱 Xmyz.G
215 | 羊姐 东城绫的忧郁 橘丶万里花酱 特莱嘻嘻嘻 Xmyz.G
216 | SonicoQ Aru 磕睡熊 绯色の尼禄 Mirai MAD Team
217 | 番外篇 kensei酱 草渲木染 Fake丶Wings 郁の周周
218 | 天晾 阿鲁巴♂SHiNoo 尼尔Minori vertigo 云彩君
219 | 毛毛菌殿下 小然参上 Dove♪神痕灬 二米明子 鸢尽苍穹
220 | littledango 毛毛菌殿下 望天晓 Dove♪神痕灬 鸢尽苍穹
221 | 白海狸 毛毛菌殿下 望天晓 Dove♪神痕灬 鸢尽苍穹
222 | 白海狸 望天晓 Dove♪神痕灬 Falling捏捏 撒加木
223 | 白海狸 望天晓 Dove♪神痕灬 Falling捏捏 毛毛菌殿下
224 | 望天晓 Dove♪神痕灬 Falling捏捏 毛毛菌殿下 XD小东
225 | 郁闷de月影 FATE零零七 Aru Dove♪神痕灬 伪信徒
226 | Aru Gintoki_JF Dove♪神痕灬 Falling捏捏 VoIceQ
227 | Aru 鑚石星痕 Dove♪神痕灬 Falling捏捏 Xmyz.G
228 | 仓米丁 橘丶万里花酱 望天晓 Dove♪神痕灬 毛毛菌殿下
229 | 仓米丁 橘丶万里花酱 毛毛菌殿下 Dove♪神痕灬 掌心の羁绊
230 | 仓米丁 二米明子 毛毛菌殿下 Dove♪神痕灬 Falling捏捏
231 | 仓米丁 望天晓 Dove♪神痕灬 Falling捏捏 毛毛菌殿下
232 | 仓米丁 毛毛菌殿下 Dove♪神痕灬 Falling捏捏 掌心の羁绊
233 | SonicoQ Dove♪神痕灬 掌心の羁绊 橘丶万里花酱 FATE零零七
234 | SonicoQ 最后之歌 Dove♪神痕灬 掌心の羁绊 橘丶万里花酱
235 | SonicoQ 最后之歌 鑚石星痕 Dove♪神痕灬 橘丶万里花酱
236 | 蔓越莓莓莓 Aru Gintoki_JF 东城绫的忧郁 桥西
237 | Aru Gintoki_JF 特莱嘻嘻嘻 东城绫的忧郁 桥西
238 | Aru Gintoki_JF 发癫的四叶草 Falling捏捏 VoIceQ
239 | Aru Gintoki_JF 特莱嘻嘻嘻 Falling捏捏 发癫的四叶草
240 | Aru Gintoki_JF 特莱嘻嘻嘻 Falling捏捏 桥西
241 | 纯洛 SliowJoker 小小☆精灵 新堂爱卖萌 喵团酱
242 | 小然参上 Fr4y 小小☆精灵 新堂爱卖萌 喵团酱
243 | 小伞一把 ☆来来子 黑化零度 珠峰喵 Shepherd小牧
244 | 傲娇麒儿 ☆来来子 黑化零度 珠峰喵 Shepherd小牧
245 | Alessa0 小伞一把 米酒酱 黑化零度 杂菌
246 | 小伞一把 Shepherd小牧 黑化零度 珠峰喵 杂菌
247 | 傲娇麒儿 Shepherd小牧 黑化零度 珠峰喵 杂菌
248 | 小伞一把 米酒酱 黑化零度 珠峰喵 杂菌
249 | 傲娇麒儿 米酒酱 黑化零度 珠峰喵 杂菌
250 | ☆Siesta 純潔的鬼畜姬 晋玄 棠雪儿 大叔球
251 | ☆Siesta 柒月一日菌 晋玄 棠雪儿 大叔球
252 | 凡人G SliowJoker 三咪线 新堂爱卖萌 纯洛
253 | 中二丶 灬羽殇 我是笨蛋么 鹿女 萌樱の醉生梦死
254 | Gintoki_JF 暴走の龙猫 Falling捏捏 毛毛菌殿下 发癫的四叶草
255 | 蔓越莓莓莓 空蝉与诗 Falling捏捏 Gintoki_JF 桥西
256 | 特莱嘻嘻嘻 空蝉与诗 Falling捏捏 Gintoki_JF 桥西
257 | 傲娇麒儿 潇潇Lisa 可爱鱼摆摆 Shepherd小牧 杂菌
258 | xkd青鱼 小伞一把 珠峰喵 Shepherd小牧 杂菌
259 | 傲娇麒儿 xkd青鱼 珠峰喵 Shepherd小牧 杂菌
260 | 亦澄 二咩www xkd青鱼 Shepherd小牧 杂菌
261 | 伍同学_ 游戏基× AKA冰丽酱 南云霞丶 新手魔理沙
262 | 卖萌的由乃酱 游戏基× AKA冰丽酱 南云霞丶 新手魔理沙
263 | 豆沙包子酱 爱拔のちくび 小馒头恰恰 幺七 天然纯种受
264 | 貓爪區區 windszhen 夏目キキ 不明物丶 夜靖
265 | Phoenixql Imiyu 夏目キキ 不明物丶 windszhen
266 | 宿の魔·鬼鬼 Phoenixql 夏目キキ 不明物丶 windszhen
267 | 蔓越莓莓莓 东城绫的忧郁 空蝉与诗 桥西 Gintoki_JF
268 | 东城绫的忧郁 空蝉与诗 特莱嘻嘻嘻 桥西 Gintoki_JF
269 | 东城绫的忧郁 空蝉与诗 特莱嘻嘻嘻 ECH渣剪组 Gintoki_JF
270 | 绝望是梦想的初章 清蒸秘制油条 小跪 海洋AGUL 神秘基佬
271 | ☆来来子 Shepherd小牧 小伞一把 珠峰喵 xkd青鱼
272 | 傲娇麒儿 ☆来来子 Shepherd小牧 珠峰喵 xkd青鱼
273 | 亦澄 ☆来来子 Shepherd小牧 二咩www xkd青鱼
274 | 亦澄 傲娇麒儿 ☆来来子 Shepherd小牧 xkd青鱼
275 | 番外篇 kensei酱 草渲木染 Fake丶Wings 風雪黄昏
276 | 番外篇 毛毛菌殿下 小然参上 二米明子 鸢尽苍穹
277 | 卷了一个大包 南澈先生 优梨酱 LOKO&洛可 水莽君。
278 | 卷了一个大包 下肢 优梨酱 LOKO&洛可 水莽君。
279 | 纯洛 明哥酱 SliowJoker 新堂爱卖萌 喵团酱
280 | ☆Siesta 純潔的鬼畜姬 水寒君 棠雪儿 大叔球
281 | 冰瞳魔羽 燃冰柚 珠峰喵 丶苹果 zxctcsx
282 | 冰瞳魔羽 Q少 珠峰喵 丶苹果 zxctcsx
283 | 爱的学长六道二落 ☆Siesta 純潔的鬼畜姬 棠雪儿 大叔球
284 | 爱的学长六道二落 ☆Siesta 柒月一日菌 棠雪儿 大叔球
285 | 冰瞳魔羽 zxctcsx 残音·X·慕斯 珠峰喵 乐子酱丢节操
286 | 冰瞳魔羽 zxctcsx adgnn 珠峰喵 乐子酱丢节操
287 | Guhan zxctcsx adgnn 冰瞳魔羽 乐子酱丢节操
288 | 染血の才二 明哥酱 末路人十香 墙角里的呵呵酱 阿浓酱
289 | 海带J 新堂爱卖萌 小然参上 オレンジ☆ 谈情不说爱
290 | cherryff 栗子酥 时间分秒都是钱 久嘉 愈雨
291 | 冰瞳魔羽 zxctcsx Q少 珠峰喵 乐子酱丢节操
292 | 二米明子 新堂爱卖萌 某不科学的旺星人 某科学的cc君 Mr甜点
293 | Mr甜点 某不科学的旺星人 新堂爱卖萌 歼灭小天使 KingOfHarem
294 | 凡人G SliowJoker 新堂爱卖萌 明哥酱 纯洛
295 | 二米明子 biu点 Mr甜点 溺水金鱼 言叶おわた
296 | iki木木 Imiyu Shoka゛ 不明物丶 Phoenixql
297 | 二米明子 新堂爱卖萌 某科学的cc君 Mr甜点 风の缘
298 | ⑦惟安诺 Floating·Dream 本多二代二代TF ied丶Knife 黑月の宅男
299 |
--------------------------------------------------------------------------------
/bilibili-po/分析/关注圈/6.txt:
--------------------------------------------------------------------------------
1 | LF先辈 西方良目仙人掌 meiling 傘閣 林即中 西行寺·爱多多姐
2 | LF先辈 西方良目仙人掌 meiling 傘閣 比利.海林顿 林即中
3 | LF先辈 西方良目仙人掌 meiling 正经战队 比利.海林顿 林即中
4 | CJ木 她 深海庞贝 糜酱 氺木子 SWINGNIM
5 | 她 深海庞贝 糜酱 氺木子 SWINGNIM 乌弋
6 | CJ木 世界の終わり 深海庞贝 糜酱 氺木子 她
7 | 兰豆子 CJ木 世界の終わり 深海庞贝 氺木子 她
8 | 亚月 飞翔的桑尼 Chokeslam kikou 妄想世界協會 绝顶油条
9 | SonicoQ オルゴール 小辰 Dove♪神痕灬 掌心の羁绊 橘丶万里花酱
10 | SonicoQ オルゴール XD小东 小辰 Dove♪神痕灬 复仇女王
11 | SonicoQ オルゴール 小辰 Dove♪神痕灬 掌心の羁绊 复仇女王
12 | SonicoQ オルゴール 小辰 Dove♪神痕灬 Z·DARK 复仇女王
13 | ここにいるよ wearsky luckAMV KoKky 天蓝梦境 Magus
14 | wearsky 宿命传说 luckAMV 世界の敌 Magus にししししー
15 | Pklala12 wearsky lucifel SonicoQ 复仇女王 Magus
16 | wearsky 白羽沉 宿命传说 CC子 小透明BAKA Magus
17 | wearsky 白羽沉 96猫@141.2cm CC子 小透明BAKA Magus
18 | 小鸟游信吾 96猫@141.2cm CC子 小透明BAKA Magus wearsky
19 | wearsky 宿命传说 世界の敌 CC子 小透明BAKA Magus
20 | wearsky 96猫@141.2cm 世界の敌 CC子 小透明BAKA Magus
21 | wearsky 白羽沉 宿命传说 小透明BAKA Magus にししししー
22 | wearsky 白羽沉 96猫@141.2cm 小透明BAKA Magus にししししー
23 | Magus 96猫@141.2cm CC子 小透明BAKA 寂寞的傲娇 小鸟游信吾
24 | Pklala12 Magus Xmyz.G Dove♪神痕灬 掌心の羁绊 复仇女王
25 | Pklala12 Magus Xmyz.G Aru Dove♪神痕灬 鑚石星痕
26 | Pklala12 Magus Xmyz.G Aru Dove♪神痕灬 复仇女王
27 | Pklala12 Magus SonicoQ Dove♪神痕灬 掌心の羁绊 复仇女王
28 | ここにいるよ Magus DigiCat luckAMV 天蓝梦境 にししししー
29 | SonicoQ Magus Aru Dove♪神痕灬 起起 Z·DARK
30 | SonicoQ Magus Aru 绯色の尼禄 Z·DARK 天蓝梦境
31 | SonicoQ Magus lucifel Pklala12 Z·DARK 复仇女王
32 | Magus 宿命传说 世界の敌 ⑨⑨酱 CC子 小透明BAKA
33 | Magus 96猫@141.2cm 世界の敌 ⑨⑨酱 CC子 小透明BAKA
34 | Magus 宿命传说 世界の敌 CC子 小透明BAKA Caaaaarrot
35 | 某可牌橘子汽水 Magus 96猫@141.2cm Lendll 小透明BAKA にししししー
36 | Magus 真鱼 白羽沉 宿命传说 CC子 小透明BAKA
37 | Magus 真鱼 宿命传说 ⑨⑨酱 CC子 小透明BAKA
38 | Magus 真鱼 96猫@141.2cm ⑨⑨酱 CC子 小透明BAKA
39 | Magus 真鱼 白羽沉 宿命传说 小透明BAKA にししししー
40 | Magus 新房坑杀之 96猫@141.2cm 小透明BAKA Caaaaarrot 小鸟游信吾
41 | 宿命传说 Magus 新房坑杀之 世界の敌 小透明BAKA Caaaaarrot
42 | Magus 真鱼 白羽沉 96猫@141.2cm 师酱 小透明BAKA
43 | Magus 真鱼 师酱 96猫@141.2cm ⑨⑨酱 小透明BAKA
44 | オルゴール LenRinFuck 何满子 流动の黑暗 月八 无聊啊啊啊啊
45 | 留学の轮舞曲 lubyyy 06御前 御剑怜侍 23夜 西行寺·爱多多姐
46 | 啪嗒啪嗒EDR オルゴール Dove♪神痕灬 哈露ちゃん littledango 复仇女王
47 | 若虫 incub8or 妄想世界協會 杯具桑 节操炖威严 切肉君
48 | ここにいるよ オルゴール DigiCat luckAMV 深籣 天蓝梦境
49 | ここにいるよ DigiCat luckAMV 深籣 天蓝梦境 にししししー
50 | ここにいるよ luckAMV 世界の敌 深籣 天蓝梦境 にししししー
51 | lubyyy meiling 06御前 傘閣 23夜 西行寺·爱多多姐
52 | 留学の轮舞曲 lubyyy meiling 06御前 23夜 西行寺·爱多多姐
53 | 恋之八卦炉 meiling 傘閣 lubyyy 23夜 西行寺·爱多多姐
54 | 恋之八卦炉 穆索尔司机 meiling 妄想世界協會 西行寺·爱多多姐 893姐贵
55 | 留学の轮舞曲 恋之八卦炉 meiling lubyyy 23夜 西行寺·爱多多姐
56 | lubyyy meiling 06御前 傘閣 黄特首 豪俊影视
57 | incub8or 穆索尔司机 meiling 绝望是梦想的初章 妄想世界協會 西行寺·爱多多姐
58 | incub8or meiling 古明地lzh 23夜 西行寺·爱多多姐 运营
59 | incub8or meiling kikou 妄想世界協會 绝望是梦想的初章 西行寺·爱多多姐
60 | incub8or meiling 古明地lzh 23夜 夏夜の行方 运营
61 | LF先辈 abcdjx meiling 06御前 傘閣 23夜
62 | LF先辈 abcdjx meiling 06御前 傘閣 豪俊影视
63 | LF先辈 meiling 06御前 傘閣 23夜 西行寺·爱多多姐
64 | SonicoQ オルゴール Aru Dove♪神痕灬 Z·DARK 复仇女王
65 | オルゴール 孤月十寒 流动の黑暗 Dove♪神痕灬 Z·DARK 复仇女王
66 | SonicoQ オルゴール 孤月十寒 Dove♪神痕灬 Z·DARK 复仇女王
67 | SonicoQ オルゴール Aru Dove♪神痕灬 起起 Z·DARK
68 | SonicoQ オルゴール 孤月十寒 Dove♪神痕灬 起起 Z·DARK
69 | SonicoQ BD播放器 オルゴール LenRinFuck Z·DARK 复仇女王
70 | SonicoQ BD播放器 lucifel オルゴール Z·DARK 复仇女王
71 | SonicoQ lucifel オルゴール 孤月十寒 Z·DARK 复仇女王
72 | SonicoQ lucifel オルゴール 孤月十寒 起起 Z·DARK
73 | ここにいるよ オルゴール DigiCat luckAMV oneways 天蓝梦境
74 | FATE零零七 Xmyz.G 雪丿下雪乃 Dove♪神痕灬 掌心の羁绊 橘丶万里花酱
75 | 雪丿下雪乃 オルゴール 流动の黑暗 Dove♪神痕灬 无聊啊啊啊啊 复仇女王
76 | 雪丿下雪乃 オルゴール 何满子 流动の黑暗 Dove♪神痕灬 无聊啊啊啊啊
77 | 小伞一把 珠峰喵 ☆玉玉子 ☆来来子 暮色TOP ☆SORA子
78 | 傲娇麒儿 珠峰喵 ☆玉玉子 ☆来来子 暮色TOP ☆SORA子
79 | 傲娇麒儿 珠峰喵 某幻君 ☆玉玉子 ☆来来子 暮色TOP
80 | 小伞一把 珠峰喵 ☆玉玉子 ☆来来子 暮色TOP 小受C零酱
81 | 飞翔的桑尼 Chokeslam kikou 妄想世界協會 绝顶油条 烤夜雀
82 | Chokeslam kikou 妄想世界協會 绝望是梦想的初章 绝顶油条 烤夜雀
83 | 神秘之死 兰豆子 白羽沉 她 96猫@141.2cm ビリくん
84 | FATE零零七 Xmyz.G 破碎の杯子 掌心の羁绊 結城音無 Caaaaarrot
85 | FATE零零七 Xmyz.G Aru 破碎の杯子 結城音無 Caaaaarrot
86 | 赛亚♂sya 潜移默化♀浅姨磨花 浓稠铅笔酱 GhostFinal 哲学♂跳蝻 耶Aya叁
87 | FATE零零七 Xmyz.G Mirai MAD Team Aru 破碎の杯子 結城音無
88 | SonicoQ FATE零零七 Mirai MAD Team Aru 破碎の杯子 結城音無
89 | FATE零零七 Xmyz.G 破碎の杯子 Dove♪神痕灬 掌心の羁绊 結城音無
90 | FATE零零七 Xmyz.G Aru 破碎の杯子 Dove♪神痕灬 結城音無
91 | SonicoQ FATE零零七 破碎の杯子 Dove♪神痕灬 掌心の羁绊 結城音無
92 | SonicoQ FATE零零七 Aru 破碎の杯子 Dove♪神痕灬 結城音無
93 | FATE零零七 SonicoQ huhu桑 Pklala12 掌心の羁绊 結城音無
94 | Pklala12 Xmyz.G FATE零零七 Dove♪神痕灬 掌心の羁绊 結城音無
95 | Pklala12 Xmyz.G FATE零零七 Aru Dove♪神痕灬 結城音無
96 | Pklala12 Xmyz.G Aru Dove♪神痕灬 結城音無 鑚石星痕
97 | FATE零零七 SonicoQ Pklala12 Dove♪神痕灬 掌心の羁绊 結城音無
98 | FATE零零七 SonicoQ Pklala12 Aru Dove♪神痕灬 結城音無
99 | Pklala12 SonicoQ Aru Dove♪神痕灬 結城音無 鑚石星痕
100 | Pklala12 SgenL FATE零零七 Tsuki_神夜 Aru 結城音無
101 | SonicoQ オルゴール LenRinFuck Dove♪神痕灬 掌心の羁绊 复仇女王
102 | 恋之八卦炉 飞翔的桑尼 Chokeslam kikou 妄想世界協會 烤夜雀
103 | 恋之八卦炉 飞翔的桑尼 Chokeslam 妄想世界協會 穆索尔司机 切肉君
104 | 恋之八卦炉 Chokeslam 绝望是梦想的初章 西行寺·爱多多姐 卷不起树叶的妖怪 神秘基佬
105 | 特莱嘻嘻嘻 SgenL 东城绫的忧郁 Aru 起起 冰水地缚灵
106 | 特莱嘻嘻嘻 SgenL Xmyz.G 东城绫的忧郁 Aru 冰水地缚灵
107 | 特莱嘻嘻嘻 SgenL ECH渣剪组 羊姐 东城绫的忧郁 冰水地缚灵
108 | 特莱嘻嘻嘻 SgenL ECH渣剪组 逝梦 羊姐 冰水地缚灵
109 | 特莱嘻嘻嘻 SgenL Xmyz.G 羊姐 东城绫的忧郁 冰水地缚灵
110 | 特莱嘻嘻嘻 SgenL ECH渣剪组 Maius酱 羊姐 冰水地缚灵
111 | 特莱嘻嘻嘻 SgenL Xmyz.G Maius酱 羊姐 冰水地缚灵
112 | Pklala12 FATE零零七 Mirai MAD Team SonicoQ Aru 绯色の尼禄
113 | Pklala12 SonicoQ FATE零零七 Aru Dove♪神痕灬 绯色の尼禄
114 | 蔓越莓莓莓 Gintoki_JF VoIceQ 桥西 Aru Falling捏捏
115 | 傲娇麒儿 xkd青鱼 潇潇Lisa 亦澄 杂菌 Shepherd小牧
116 | 世界破坏时 windszhen 不明物丶 Imiyu 夏目キキ 夜靖
117 | 世界破坏时 不明物丶 xiaotuji 夏目キキ 里维无ID 夜靖
118 | 世界破坏时 windszhen 不明物丶 xiaotuji 夏目キキ 夜靖
119 | xiaotuji 不明物丶 宿の魔·鬼鬼 夏目キキ 里维无ID 夜靖
120 | xiaotuji windszhen 不明物丶 宿の魔·鬼鬼 夏目キキ 夜靖
121 |
--------------------------------------------------------------------------------
/bilibili-po/分析/关注圈/7.txt:
--------------------------------------------------------------------------------
1 | 某可牌橘子汽水 Magus fontaine 白羽沉 96猫@141.2cm 小透明BAKA にししししー
2 | Magus fontaine 白羽沉 96猫@141.2cm ビリくん 小透明BAKA にししししー
3 | Magus fontaine 新房坑杀之 96猫@141.2cm 世界の敌 小透明BAKA Caaaaarrot
4 | Magus fontaine 新房坑杀之 96猫@141.2cm 世界の敌 小透明BAKA にししししー
5 | 小鸟游信吾 TSA 96猫@141.2cm CC子 小透明BAKA Caaaaarrot Magus
6 | ここにいるよ Magus TSA 96猫@141.2cm 小透明BAKA Caaaaarrot 小鸟游信吾
7 | Magus TSA 96猫@141.2cm 世界の敌 CC子 小透明BAKA Caaaaarrot
8 | Magus TSA 真鱼 白羽沉 96猫@141.2cm CC子 小透明BAKA
9 | 小鸟游信吾 TSA 真鱼 96猫@141.2cm CC子 小透明BAKA Magus
10 | Pklala12 wearsky SonicoQ Aru Dove♪神痕灬 复仇女王 Magus
11 | ここにいるよ wearsky luckAMV 世界の敌 Magus 天蓝梦境 にししししー
12 | ここにいるよ wearsky 96猫@141.2cm 小透明BAKA Magus 小鸟游信吾 にししししー
13 | ここにいるよ wearsky 96猫@141.2cm 世界の敌 小透明BAKA Magus にししししー
14 | ここにいるよ wearsky 世界の敌 小透明BAKA Magus 天蓝梦境 にししししー
15 | wearsky 新房坑杀之 96猫@141.2cm 小透明BAKA Magus 小鸟游信吾 にししししー
16 | 宿命传说 wearsky 新房坑杀之 世界の敌 小透明BAKA Magus にししししー
17 | wearsky 新房坑杀之 96猫@141.2cm 世界の敌 小透明BAKA Magus にししししー
18 | SonicoQ Magus Pklala12 Aru Dove♪神痕灬 Z·DARK 鑚石星痕
19 | SonicoQ Magus Pklala12 Aru Dove♪神痕灬 Z·DARK 复仇女王
20 | SonicoQ Magus Pklala12 Aru Dove♪神痕灬 绯色の尼禄 Z·DARK
21 | Magus 浅叶 她 96猫@141.2cm ビリくん CC子 兰豆子
22 | 某可牌橘子汽水 Magus 96猫@141.2cm CC子 小透明BAKA Caaaaarrot 小鸟游信吾
23 | ここにいるよ 某可牌橘子汽水 Magus 96猫@141.2cm 小透明BAKA Caaaaarrot 小鸟游信吾
24 | 某可牌橘子汽水 Magus 96猫@141.2cm 世界の敌 CC子 小透明BAKA Caaaaarrot
25 | ここにいるよ 某可牌橘子汽水 Magus 96猫@141.2cm 小透明BAKA 小鸟游信吾 にししししー
26 | Magus 真鱼 白羽沉 她 96猫@141.2cm CC子 小透明BAKA
27 | 恋之八卦炉 穆索尔司机 meiling Chokeslam 绝望是梦想的初章 妄想世界協會 西行寺·爱多多姐
28 | 恋之八卦炉 meiling Chokeslam kikou 妄想世界協會 绝望是梦想的初章 西行寺·爱多多姐
29 | 恋之八卦炉 meiling Chokeslam kikou 妄想世界協會 绝望是梦想的初章 烤夜雀
30 | 留学の轮舞曲 LF先辈 incub8or meiling 06御前 23夜 西行寺·爱多多姐
31 | オルゴール LenRinFuck 流动の黑暗 Dove♪神痕灬 Z·DARK 无聊啊啊啊啊 复仇女王
32 | SonicoQ オルゴール LenRinFuck Dove♪神痕灬 Z·DARK 无聊啊啊啊啊 复仇女王
33 | オルゴール LenRinFuck 何满子 流动の黑暗 Dove♪神痕灬 Z·DARK 无聊啊啊啊啊
34 | SonicoQ オルゴール LenRinFuck 何满子 Dove♪神痕灬 Z·DARK 无聊啊啊啊啊
35 | 恋之八卦炉 穆索尔司机 Chokeslam 妄想世界協會 西行寺·爱多多姐 水纹与熏风 切肉君
36 | Pklala12 SgenL Xmyz.G FATE零零七 Mirai MAD Team Aru 結城音無
37 | FATE零零七 SonicoQ Pklala12 Mirai MAD Team Aru SgenL 結城音無
38 | 恋之八卦炉 Chokeslam kikou 妄想世界協會 绝望是梦想的初章 卷不起树叶的妖怪 烤夜雀
39 | 恋之八卦炉 穆索尔司机 Chokeslam 绝望是梦想的初章 妄想世界協會 西行寺·爱多多姐 卷不起树叶的妖怪
40 | 恋之八卦炉 Chokeslam kikou 妄想世界協會 绝望是梦想的初章 西行寺·爱多多姐 卷不起树叶的妖怪
41 |
--------------------------------------------------------------------------------
/bilibili-po/分析/关注圈/8.txt:
--------------------------------------------------------------------------------
1 | ここにいるよ 某可牌橘子汽水 Magus fontaine 96猫@141.2cm 世界の敌 小透明BAKA Caaaaarrot
2 | ここにいるよ 某可牌橘子汽水 Magus fontaine 96猫@141.2cm 世界の敌 小透明BAKA にししししー
3 | ここにいるよ Magus TSA fontaine 96猫@141.2cm 世界の敌 小透明BAKA Caaaaarrot
4 | ここにいるよ Magus TSA fontaine 96猫@141.2cm 世界の敌 小透明BAKA にししししー
5 | Magus TSA 真鱼 fontaine 白羽沉 96猫@141.2cm 小透明BAKA にししししー
6 | ここにいるよ Magus TSA 真鱼 fontaine 96猫@141.2cm 小透明BAKA にししししー
7 | ここにいるよ Magus TSA 真鱼 96猫@141.2cm 小透明BAKA 小鸟游信吾 にししししー
8 | Magus 白羽沉 她 96猫@141.2cm ビリくん 絶体延命 寂寞的傲娇 兰豆子
9 | 某可牌橘子汽水 Magus 白羽沉 她 96猫@141.2cm CC子 小透明BAKA 兰豆子
10 |
--------------------------------------------------------------------------------
/bilibili-po/分析/关注圈/9.txt:
--------------------------------------------------------------------------------
1 | 寂寞的傲娇 Magus 小透明BAKA ビリくん 她 96猫@141.2cm CC子 兰豆子 白羽沉
2 |
--------------------------------------------------------------------------------
/bilibili-po/分析/分析.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vespa314/bilibili-api/42b6b90aa7c141f5cfb0fdc754435518106f6966/bilibili-po/分析/分析.rar
--------------------------------------------------------------------------------
/bilibili-po/爬取结果/bilibili-relation.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vespa314/bilibili-api/42b6b90aa7c141f5cfb0fdc754435518106f6966/bilibili-po/爬取结果/bilibili-relation.rar
--------------------------------------------------------------------------------
/bilibili-video/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 |
--------------------------------------------------------------------------------
/bilibili-video/biclass.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Wed May 28 01:22:20 2014
4 |
5 | @author: Vespa
6 | """
7 |
8 | class User():
9 | def __init__(self,m_mid=None,m_name=None):
10 | if m_mid:
11 | self.mid = m_mid
12 | if m_name:
13 | if isinstance(m_name,unicode):
14 | m_name = m_name.encode('utf8')
15 | self.name = m_name
16 | # 获取空间地址
17 | def GetSpace(self):
18 | return 'http://space.bilibili.tv/'+str(self.mid)
19 | mid = None
20 | name = None
21 | isApprove = None#是否是认证账号
22 | spaceName = None
23 | sex = None
24 | rank = None
25 | avatar = None
26 | follow = None#关注好友数目
27 | fans = None#粉丝数目
28 | article = None#投稿数
29 | place = None#所在地
30 | description = None#认证用户为认证信息 普通用户为交友宣言
31 | followlist = None#关注的好友列表
32 | friend = None
33 | DisplayRank = None
34 |
35 |
36 | class Video():
37 | def __init__(self,m_aid=None,m_title=None):
38 | if m_aid:
39 | self.aid = m_aid
40 | if m_title:
41 | if isinstance(m_title,unicode):
42 | m_title = m_title.encode('utf8')
43 | self.title = m_title
44 | aid = None
45 | title = None
46 | guankan = None
47 | shoucang = None
48 | danmu = None
49 | date = None
50 | cover = None
51 | commentNumber = None
52 | description = None
53 | tag = None
54 | author = None
55 | page = None
56 | credit = None
57 | coin = None
58 | spid = None
59 | cid = None
60 | offsite = None#Flash播放调用地址
61 | Iscopy = None
62 | subtitle = None
63 | duration = None
64 | episode = None
65 | arcurl = None#网页地址
66 | arcrank = None#不明
67 | tid = None
68 | typename = None
69 | #不明:
70 | instant_server = None
71 | src = None
72 | partname = None
73 | allow_bp = None
74 | allow_feed = None
75 | created = None
76 | #播放信息:
77 | play_site = None
78 | play_forward = None
79 | play_mobile = None
80 |
81 | class Bangumi():
82 | def __init__(self):
83 | pass
84 | typeid = None
85 | lastupdate = None
86 | areaid = None
87 | bgmcount = None#番剧当前总集数
88 | title = None
89 | lastupdate_at = None
90 | attention = None #订阅数
91 | cover = None
92 | priority = None
93 | area = None
94 | weekday = None
95 | spid = None
96 | new = None
97 | scover = None
98 | mcover = None
99 | click = None
100 | season_id = None
101 | click = None # 浏览数
102 | video_view = None
103 |
104 | class Comment():
105 | def __init__(self):
106 | self.post_user = User()
107 | lv = None#楼层
108 | fbid = None#评论id
109 | msg = None
110 | ad_check = None#状态 (0: 正常 1: UP主隐藏 2: 管理员删除 3: 因举报删除)
111 | post_user = None
112 |
113 | class CommentList():
114 | def __init__(self):
115 | pass
116 | comments = None
117 | commentLen = None
118 | page = None
119 |
120 | class ZhuantiInfo():
121 | def __init__(self, m_spid,m_title):
122 | self.spid = m_spid
123 | if isinstance(m_title,unicode):
124 | m_title = m_title.encode('utf8')
125 | self.title = m_title
126 | spid = None
127 | title = None
128 | author = None
129 | cover = None
130 | thumb = None
131 | ischeck = None #不明
132 | typeurl = None #总是"http://www.bilibili.com"
133 | tag = None
134 | description = None
135 | pubdate = None # 不明
136 | postdate = None
137 | lastupdate = None
138 | click = None
139 | favourite = None
140 | attention = None
141 | count = None
142 | bgmcount = None
143 | spcount = None
144 | season_id = None
145 | is_bangumi = None
146 | arcurl = None
147 |
148 | class Danmu():
149 | def __init__(self):
150 | pass
151 | t_video = None
152 | t_stamp = None
153 | mid_crc = None # 值为:hex(binascii.crc32(mid))
154 | danmu_type = None # 1:滚动弹幕 5:顶端弹幕 4:底部弹幕
155 | content = None
156 | danmu_color = None
157 | danmu_fontsize = None
--------------------------------------------------------------------------------
/bilibili-video/main.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Thu Jun 05 00:00:22 2014
4 |
5 | @author: Administrator
6 | """
7 | from bilibili import *
8 | import os
9 | import zipfile
10 |
11 | def videowrite(f,video):
12 | if video.title:
13 | f.write('Aid:%s\nTitle:%s\n'%(video.aid,video.title))
14 | else:
15 | f.write('Aid:%s\nTitle:NULL\n'%(video.aid))
16 | f.write('copyright:%s\n'%(video.Iscopy))
17 | f.write('Click:%s\nDanmu:%s\n'%(video.guankan,video.danmu))
18 | f.write('comment:%s\n'%(video.commentNumber))
19 | f.write('credit:%s\n'%(video.credit))
20 | f.write('coin:%s\n'%(video.coin))
21 | f.write('favorite:%s\n'%(video.shoucang))
22 | if video.author.name:
23 | f.write('author:%s %s\n'%(video.author.name,video.author.mid))
24 | else:
25 | f.write('author:%s %s\n'%('NULL',video.author.mid))
26 | f.write('date:%s\n'%(video.date))
27 | f.write('duration:%s\n'%(video.duration))
28 | f.write('play_site:%s\n'%(video.play_site))
29 | f.write('play_forward:%s\n'%(video.play_forward))
30 | f.write('play_mobile:%s\n'%(video.play_mobile))
31 | f.write('description:%s\n'%(video.description))
32 | f.write('pic:%s\n'%(video.cover))
33 | f.write('\n')
34 |
35 | def linecount_2(filename):
36 | count = -1 #让空文件的行号显示0
37 | for count,line in enumerate(open(filename,'r')):
38 | pass
39 | return count+1
40 |
41 | def GetAllVideo(year,month):
42 | appkey = '*******'
43 | begin = [year,month,1]
44 | end = [year,month,31]
45 |
46 | path = '/root/tmp/bilibili/%d-%d/'%(year,month)
47 | print '%d-%d'%(year,month)
48 | if not os.path.exists(path):
49 | os.mkdir(path)
50 |
51 | fid_dict = {}
52 | tid_set = set([])
53 |
54 | illegalSymble = list('/:?|<>*')
55 |
56 | for page in xrange(1,9999999):
57 | total_page = -1
58 | stay_time = 5
59 | while total_page == -1:
60 | [total_page,_name,videolist] = GetRank(appkey,tid=0,order='hot',pagesize = 100,page=page,begin=begin,end=end,click_detail='true')
61 | if total_page == -1:
62 | time.sleep(stay_time)
63 | stay_time += 5
64 | print '\t%s:page %d/%d'%(time.strftime('%H:%M:%S',time.localtime(time.time())),page,total_page)
65 | for video in videolist:
66 | if not video.tid in tid_set:
67 | for sym in illegalSymble:
68 | video.typename = video.typename.replace(sym,'')
69 | fid_dict[video.tid] = open('%s%d-%s.txt'%(path,video.tid,video.typename),'w')
70 | tid_set.add(video.tid)
71 | videowrite(fid_dict[video.tid],video)
72 |
73 | if page == total_page:
74 | break
75 | time.sleep(3)
76 | for fid in fid_dict:
77 | fid_dict[fid].close()
78 | z = zipfile.ZipFile('/root/Dropbox/bili_video/video/%s.zip'%('%d-%d'%(year,month)), 'w')
79 | for d in os.listdir(path):
80 | z.write(path+os.sep+d)
81 | z.close()
82 | __import__('shutil').rmtree(path)
83 |
84 | if __name__ == "__main__":
85 | for year in range(2009,2017):
86 | for month in range(1,13):
87 | if year == 2016 and month >= 1:
88 | continue;
89 | if year == 2009 and month < 6:
90 | continue
91 | if os.path.isfile('/root/Dropbox/bili_video/video/%s.zip'%('%d-%d'%(year,month))):
92 | print year,'/',month," existed"
93 | continue
94 | GetAllVideo(year,month)
95 | print 'finished'
96 |
--------------------------------------------------------------------------------
/bilibili-video/support.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:59:09 2014
4 |
5 | @author: Vespa
6 | """
7 | import urllib2
8 | import urllib
9 | import re
10 | import json
11 | import zlib
12 | import gzip
13 | import xml.dom.minidom
14 | import hashlib
15 | from biclass import *
16 | import time
17 | import sys
18 | import os
19 | from GetAssDanmaku import *
20 | def GetRE(content,regexp):
21 | return re.findall(regexp, content)
22 |
23 | def getURLContent(url):
24 | while True:
25 | flag = 1
26 | try:
27 | headers = {'User-Agent':'Mozilla/5.0 (Windows U Windows NT 6.1 en-US rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
28 | req = urllib2.Request(url = url,headers = headers)
29 | content = urllib2.urlopen(req).read()
30 | except:
31 | flag = 0
32 | time.sleep(5)
33 | if flag == 1:
34 | break
35 | return content
36 |
37 | class JsonInfo():
38 | def __init__(self,url):
39 | self.info = json.loads(getURLContent(url))
40 | if self.info.has_key('code') and self.info['code'] != 0:
41 | if self.info.has_key('message'):
42 | print "【Error】code=%d, msg=%s, url=%s"%(self.info['code'],self.Getvalue('message'),url)
43 | self.ERROR_MSG = self.Getvalue('message')
44 | elif self.info.has_key('error'):
45 | print "【Error】code=%d, msg=%s, url=%s"%(self.info['code'],self.Getvalue('error'),url)
46 | self.ERROR_MSG = self.Getvalue('error')
47 | self.error = True
48 | def Getvalue(self,*keys):
49 | if len(keys) == 0:
50 | return None
51 | if self.info.has_key(keys[0]):
52 | temp = self.info[keys[0]]
53 | else:
54 | return None
55 | if len(keys) > 1:
56 | for key in keys[1:]:
57 | if temp.has_key(key):
58 | temp = temp[key]
59 | else:
60 | return None
61 | if isinstance(temp,unicode):
62 | temp = temp.encode('utf8')
63 | return temp
64 | info = None
65 | error = False
66 | ERROR_MSG = ""
67 |
68 | def GetString(t):
69 | if type(t) == int:
70 | return str(t)
71 | return t
72 |
73 | def getint(string):
74 | try:
75 | i = int(string)
76 | except:
77 | i = 0
78 | return i
79 |
80 | def DictDecode2UTF8(dict):
81 | for keys in dict:
82 | if isinstance(dict[keys],unicode):
83 | dict[keys] = dict[keys].encode('utf8')
84 | return dict
85 |
86 | def GetVideoFromRate(content):
87 | """
88 | 从视频搜索源码页面提取视频信息
89 | """
90 | #av号和标题
91 | regular1 = r']*>(.*)'
92 | info1 = GetRE(content,regular1)
93 | #观看数
94 | regular2 = r'\1'
95 | info2 = GetRE(content,regular2)
96 | #收藏
97 | regular3 = r'\1'
98 | info3 = GetRE(content,regular3)
99 | #弹幕
100 | regular4 = r'\1'
101 | info4 = GetRE(content,regular4)
102 | #日期
103 | regular5 = r'(.+)'
104 | info5 = GetRE(content,regular5)
105 | #封面
106 | regular6 = r'
]*>'
107 | info6 = GetRE(content,regular6)
108 | #Up的id和名字
109 | regular7 = r'(.+)'
110 | info7 = GetRE(content,regular7)
111 | #!!!!!!!!这里可以断言所有信息长度相等
112 | videoNum = len(info1)#视频长度
113 | videoList = []
114 |
115 | for i in range(videoNum):
116 | video_t = Video()
117 | video_t.aid = getint(info1[i][0])
118 | video_t.title = info1[i][1]
119 | video_t.guankan = getint(info2[i])
120 | video_t.shoucang = getint(info3[i])
121 | video_t.danmu = getint(info4[i])
122 | video_t.date = info5[i]
123 | video_t.cover = info6[i]
124 | video_t.author = User(info7[i][0],info7[i][1])
125 | videoList.append(video_t)
126 | return videoList
127 |
128 | def GetSign(params, appkey, AppSecret=None):
129 | """
130 | 获取新版API的签名,不然会返回-3错误
131 | """
132 | params['appkey']=appkey
133 | data = ""
134 | paras = params.keys()
135 | paras.sort()
136 | for para in paras:
137 | if data != "":
138 | data += "&"
139 | data += para + "=" + str(urllib.quote(GetString(params[para])))
140 | if AppSecret == None:
141 | return data
142 | m = hashlib.md5()
143 | m.update(data+AppSecret)
144 | return data+'&sign='+m.hexdigest()
145 |
146 | def ParseComment(danmu):
147 | dom = xml.dom.minidom.parseString(danmu)
148 | comment_element = dom.getElementsByTagName('d')
149 | for i, comment in enumerate(comment_element):
150 | p = str(comment.getAttribute('p')).split(',')
151 | danmu = Danmu()
152 | danmu.t_video = float(p[0])
153 | danmu.danmu_type = int(p[1])
154 | danmu.t_stamp = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(p[4])))
155 | danmu.mid_crc = p[6]
156 | danmu.danmu_color = ConvertColor(int(p[3]))
157 | danmu_fontsize = int(p[2])
158 | if len(comment.childNodes) != 0:
159 | danmu.content = str(comment.childNodes[0].wholeText).replace('/n', '\n')
160 | else:
161 | danmu.content = ""
162 | yield danmu
--------------------------------------------------------------------------------
/danmu-Delay/README.md:
--------------------------------------------------------------------------------
1 | 对ass弹幕文件进行延时。。。
2 |
3 | 为什么会有这个需求呢?因为妈蛋ffmpeg剪切ts视频失败啊!!
4 | 只好弹幕来配合了。。。
5 | 如果以后经常遇到。。再整理得好用一些。。。
6 | 酱~
--------------------------------------------------------------------------------
/danmu-Delay/danmu_delay.py:
--------------------------------------------------------------------------------
1 | # 对ass弹幕文件进行延时。。。
2 | # 为什么会有这个需求呢?因为妈蛋ffmpeg剪切ts视频失败啊!!
3 | # 只好弹幕来配合了。。。
4 | # 如果以后经常遇到。。再整理得好用一些。。。
5 | # 酱~
6 |
7 | import re
8 |
9 | def t_delay(h,m,s,delay):
10 | s += delay;
11 | if s >= 60:
12 | s -= 60
13 | m += 1
14 | if m >= 60:
15 | m -= 60
16 | h += 1
17 | return [h,m,s]
18 |
19 | filename = r'in.ass'
20 | delay = 30;
21 | fid = open('out.ass','w')
22 | for line in open(filename):
23 | t = re.findall(r'^(Dialogue: 2,)(\d+):(\d+):(\d+)\.(\d+),(\d+):(\d+):(\d+)\.(.*)$',line)
24 | if len(t) == 0:
25 | fid.write(line)
26 | else:
27 | t = t[0]
28 | [h,m,s] = t_delay(int(t[1]),int(t[2]),int(t[3]),delay)
29 | fid.write('%s%d:%.2d:%.2d.%s,'%(t[0],h,m,s,t[4]))
30 | [h,m,s] = t_delay(int(t[5]),int(t[6]),int(t[7]),delay)
31 | fid.write('%d:%.2d:%.2d.%s\n'%(h,m,s,t[8]))
32 |
33 | fid.close();
34 | print "finished!!"
35 |
36 |
37 |
--------------------------------------------------------------------------------
/python API/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
--------------------------------------------------------------------------------
/python API/GetAssDanmaku.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:42:03 2014
4 |
5 | @author: Administrator
6 | """
7 |
8 |
9 | from support import *
10 | import hashlib
11 | import io
12 | import xml.dom.minidom
13 | import random
14 | import math
15 | import os
16 | import sys
17 |
18 | default_encoding = 'utf-8'
19 | if sys.getdefaultencoding() != default_encoding:
20 | reload(sys)
21 | sys.setdefaultencoding(default_encoding)
22 |
23 | class safe_list(list):
24 | def get(self, index, default=None):
25 | try:
26 | return self[index]
27 | except IndexError:
28 | return default
29 |
30 | # Calculation is based on https://github.com/jabbany/CommentCoreLibrary/issues/5#issuecomment-40087282
31 | # and https://github.com/m13253/danmaku2ass/issues/7#issuecomment-41489422
32 | # ASS FOV = width*4/3.0
33 | # But Flash FOV = width/math.tan(100*math.pi/360.0)/2 will be used instead
34 | # Result: (transX, transY, rotX, rotY, rotZ, scaleX, scaleY)
35 | def ConvertFlashRotation(rotY, rotZ, X, Y, width, height):
36 | def WrapAngle(deg):
37 | return 180-((180-deg) % 360)
38 | rotY = WrapAngle(rotY)
39 | rotZ = WrapAngle(rotZ)
40 | if rotY in (90, -90):
41 | rotY -= 1
42 | if rotY == 0 or rotZ == 0:
43 | outX = 0
44 | outY = -rotY # Positive value means clockwise in Flash
45 | outZ = -rotZ
46 | rotY *= math.pi/180.0
47 | rotZ *= math.pi/180.0
48 | else:
49 | rotY *= math.pi/180.0
50 | rotZ *= math.pi/180.0
51 | outY = math.atan2(-math.sin(rotY)*math.cos(rotZ), math.cos(rotY))*180/math.pi
52 | outZ = math.atan2(-math.cos(rotY)*math.sin(rotZ), math.cos(rotZ))*180/math.pi
53 | outX = math.asin(math.sin(rotY)*math.sin(rotZ))*180/math.pi
54 | trX = (X*math.cos(rotZ)+Y*math.sin(rotZ))/math.cos(rotY)+(1-math.cos(rotZ)/math.cos(rotY))*width/2-math.sin(rotZ)/math.cos(rotY)*height/2
55 | trY = Y*math.cos(rotZ)-X*math.sin(rotZ)+math.sin(rotZ)*width/2+(1-math.cos(rotZ))*height/2
56 | trZ = (trX-width/2)*math.sin(rotY)
57 | FOV = width*math.tan(2*math.pi/9.0)/2
58 | try:
59 | scaleXY = FOV/(FOV+trZ)
60 | except ZeroDivisionError:
61 | logging.error('Rotation makes object behind the camera: trZ == %.0f' % trZ)
62 | scaleXY = 1
63 | trX = (trX-width/2)*scaleXY+width/2
64 | trY = (trY-height/2)*scaleXY+height/2
65 | if scaleXY < 0:
66 | scaleXY = -scaleXY
67 | outX += 180
68 | outY += 180
69 | logging.error('Rotation makes object behind the camera: trZ == %.0f < %.0f' % (trZ, FOV))
70 | return (trX, trY, WrapAngle(outX), WrapAngle(outY), WrapAngle(outZ), scaleXY*100, scaleXY*100)
71 |
72 |
73 | def WriteCommentBilibiliPositioned(f, c, width, height, styleid):
74 | #BiliPlayerSize = (512, 384) # Bilibili player version 2010
75 | #BiliPlayerSize = (540, 384) # Bilibili player version 2012
76 | BiliPlayerSize = (672, 438) # Bilibili player version 2014
77 | ZoomFactor = GetZoomFactor(BiliPlayerSize, (width, height))
78 |
79 | def GetPosition(InputPos, isHeight):
80 | isHeight = int(isHeight) # True -> 1
81 | if isinstance(InputPos, int):
82 | return ZoomFactor[0]*InputPos+ZoomFactor[isHeight+1]
83 | elif isinstance(InputPos, float):
84 | if InputPos > 1:
85 | return ZoomFactor[0]*InputPos+ZoomFactor[isHeight+1]
86 | else:
87 | return BiliPlayerSize[isHeight]*ZoomFactor[0]*InputPos+ZoomFactor[isHeight+1]
88 | else:
89 | try:
90 | InputPos = int(InputPos)
91 | except ValueError:
92 | InputPos = float(InputPos)
93 | return GetPosition(InputPos, isHeight)
94 |
95 | try:
96 | comment_args = safe_list(json.loads(c[3]))
97 | text = ASSEscape(str(comment_args[4]).replace('/n', '\n'))
98 | from_x = comment_args.get(0, 0)
99 | from_y = comment_args.get(1, 0)
100 | to_x = comment_args.get(7, from_x)
101 | to_y = comment_args.get(8, from_y)
102 | from_x = GetPosition(from_x, False)
103 | from_y = GetPosition(from_y, True)
104 | to_x = GetPosition(to_x, False)
105 | to_y = GetPosition(to_y, True)
106 | alpha = safe_list(str(comment_args.get(2, '1')).split('-'))
107 | from_alpha = float(alpha.get(0, 1))
108 | to_alpha = float(alpha.get(1, from_alpha))
109 | from_alpha = 255-round(from_alpha*255)
110 | to_alpha = 255-round(to_alpha*255)
111 | rotate_z = int(comment_args.get(5, 0))
112 | rotate_y = int(comment_args.get(6, 0))
113 | lifetime = float(comment_args.get(3, 4500))
114 | duration = int(comment_args.get(9, lifetime*1000))
115 | delay = int(comment_args.get(10, 0))
116 | fontface = comment_args.get(12)
117 | isborder = comment_args.get(11, 'true')
118 | from_rotarg = ConvertFlashRotation(rotate_y, rotate_z, from_x, from_y, width, height)
119 | to_rotarg = ConvertFlashRotation(rotate_y, rotate_z, to_x, to_y, width, height)
120 | styles = ['\\org(%d, %d)' % (width/2, height/2)]
121 | if from_rotarg[0:2] == to_rotarg[0:2]:
122 | styles.append('\\pos(%.0f, %.0f)' % (from_rotarg[0:2]))
123 | else:
124 | styles.append('\\move(%.0f, %.0f, %.0f, %.0f, %.0f, %.0f)' % (from_rotarg[0:2]+to_rotarg[0:2]+(delay, delay+duration)))
125 | styles.append('\\frx%.0f\\fry%.0f\\frz%.0f\\fscx%.0f\\fscy%.0f' % (from_rotarg[2:7]))
126 | if (from_x, from_y) != (to_x, to_y):
127 | styles.append('\\t(%d, %d, ' % (delay, delay+duration))
128 | styles.append('\\frx%.0f\\fry%.0f\\frz%.0f\\fscx%.0f\\fscy%.0f' % (to_rotarg[2:7]))
129 | styles.append(')')
130 | if fontface:
131 | styles.append('\\fn%s' % ASSEscape(fontface))
132 | styles.append('\\fs%.0f' % (c[6]*ZoomFactor[0]))
133 | if c[5] != 0xffffff:
134 | styles.append('\\c&H%s&' % ConvertColor(c[5]))
135 | if c[5] == 0x000000:
136 | styles.append('\\3c&HFFFFFF&')
137 | if from_alpha == to_alpha:
138 | styles.append('\\alpha&H%02X' % from_alpha)
139 | elif (from_alpha, to_alpha) == (255, 0):
140 | styles.append('\\fad(%.0f,0)' % (lifetime*1000))
141 | elif (from_alpha, to_alpha) == (0, 255):
142 | styles.append('\\fad(0, %.0f)' % (lifetime*1000))
143 | else:
144 | styles.append('\\fade(%(from_alpha)d, %(to_alpha)d, %(to_alpha)d, 0, %(end_time).0f, %(end_time).0f, %(end_time).0f)' % {'from_alpha': from_alpha, 'to_alpha': to_alpha, 'end_time': lifetime*1000})
145 | if isborder == 'false':
146 | styles.append('\\bord0')
147 | f.write('Dialogue: -1,%(start)s,%(end)s,%(styleid)s,,0,0,0,,{%(styles)s}%(text)s\n' % {'start': ConvertTimestamp(c[0]), 'end': ConvertTimestamp(c[0]+lifetime), 'styles': ''.join(styles), 'text': text, 'styleid': styleid})
148 | except (IndexError, ValueError) as e:
149 | try:
150 | logging.warning(_('Invalid comment: %r') % c[3])
151 | except IndexError:
152 | logging.warning(_('Invalid comment: %r') % c)
153 |
154 | # Result: (f, dx, dy)
155 | # To convert: NewX = f*x+dx, NewY = f*y+dy
156 | def GetZoomFactor(SourceSize, TargetSize):
157 | try:
158 | if (SourceSize, TargetSize) == GetZoomFactor.Cached_Size:
159 | return GetZoomFactor.Cached_Result
160 | except AttributeError:
161 | pass
162 | GetZoomFactor.Cached_Size = (SourceSize, TargetSize)
163 | try:
164 | SourceAspect = SourceSize[0]/SourceSize[1]
165 | TargetAspect = TargetSize[0]/TargetSize[1]
166 | if TargetAspect < SourceAspect: # narrower
167 | ScaleFactor = TargetSize[0]/SourceSize[0]
168 | GetZoomFactor.Cached_Result = (ScaleFactor, 0, (TargetSize[1]-TargetSize[0]/SourceAspect)/2)
169 | elif TargetAspect > SourceAspect: # wider
170 | ScaleFactor = TargetSize[1]/SourceSize[1]
171 | GetZoomFactor.Cached_Result = (ScaleFactor, (TargetSize[0]-TargetSize[1]*SourceAspect)/2, 0)
172 | else:
173 | GetZoomFactor.Cached_Result = (TargetSize[0]/SourceSize[0], 0, 0)
174 | return GetZoomFactor.Cached_Result
175 | except ZeroDivisionError:
176 | GetZoomFactor.Cached_Result = (1, 0, 0)
177 | return GetZoomFactor.Cached_Result
178 |
179 |
180 | def WriteASSHead(f, width, height, fontface, fontsize, alpha, styleid):
181 | f.write(
182 | '''
183 | [Script Info]
184 | ; Script generated by Danmaku2ASS
185 | ; https://github.com/m13253/danmaku2ass
186 | Script Updated By: Danmaku2ASS (https://github.com/m13253/danmaku2ass)
187 | ScriptType: v4.00+
188 | PlayResX: %(width)d
189 | PlayResY: %(height)d
190 | Aspect Ratio: %(width)d:%(height)d
191 | Collisions: Normal
192 | WrapStyle: 2
193 | ScaledBorderAndShadow: yes
194 | YCbCr Matrix: TV.601
195 |
196 | [V4+ Styles]
197 | Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
198 | Style: %(styleid)s, %(fontface)s, %(fontsize).0f, &H%(alpha)02XFFFFFF, &H%(alpha)02XFFFFFF, &H%(alpha)02X000000, &H%(alpha)02X000000, 0, 0, 0, 0, 100, 100, 0.00, 0.00, 1, %(outline).0f, 0, 7, 0, 0, 0, 0
199 |
200 | [Events]
201 | Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
202 | ''' % {'width': width, 'height': height, 'fontface': fontface, 'fontsize': fontsize, 'alpha': 255-round(alpha*255), 'outline': max(fontsize/25.0, 1), 'styleid': styleid}
203 | )
204 |
205 | def TestFreeRows(rows, c, row, width, height, bottomReserved, lifetime):
206 | res = 0
207 | rowmax = height-bottomReserved
208 | targetRow = None
209 | if c[4] in (1, 2):
210 | while row < rowmax and res < c[7]:
211 | if targetRow != rows[c[4]][row]:
212 | targetRow = rows[c[4]][row]
213 | if targetRow and targetRow[0]+lifetime > c[0]:
214 | break
215 | row += 1
216 | res += 1
217 | else:
218 | try:
219 | thresholdTime = c[0]-lifetime*(1-width/(c[8]+width))
220 | except ZeroDivisionError:
221 | thresholdTime = c[0]-lifetime
222 | while row < rowmax and res < c[7]:
223 | if targetRow != rows[c[4]][row]:
224 | targetRow = rows[c[4]][row]
225 | try:
226 | if targetRow and (targetRow[0] > thresholdTime or targetRow[0]+targetRow[8]*lifetime/(targetRow[8]+width) > c[0]):
227 | break
228 | except ZeroDivisionError:
229 | pass
230 | row += 1
231 | res += 1
232 | return res
233 |
234 | def MarkCommentRow(rows, c, row):
235 | row = int(row)
236 | try:
237 | for i in range(row, int(row+math.ceil(c[7]))):
238 | rows[c[4]][i] = c
239 | except IndexError:
240 | pass
241 |
242 | def ASSEscape(s):
243 | def ReplaceLeadingSpace(s):
244 | sstrip = s.strip(' ')
245 | slen = len(s)
246 | if slen == len(sstrip):
247 | return s
248 | else:
249 | llen = slen-len(s.lstrip(' '))
250 | rlen = slen-len(s.rstrip(' '))
251 | return ''.join(('\u2007'*llen, sstrip, '\u2007'*rlen))
252 | return '\\N'.join((ReplaceLeadingSpace(i) or ' ' for i in str(s).replace('\\', '\\\\').replace('{', '\\{').replace('}', '\\}').split('\n')))
253 |
254 | def ConvertTimestamp(timestamp):
255 | timestamp = round(timestamp*100.0)
256 | hour, minute = divmod(timestamp, 360000)
257 | minute, second = divmod(minute, 6000)
258 | second, centsecond = divmod(second, 100)
259 | return '%d:%02d:%02d.%02d' % (int(hour), int(minute), int(second), int(centsecond))
260 |
261 | def ConvertType2(row, height, bottomReserved):
262 | return height-bottomReserved-row
263 |
264 | def FindAlternativeRow(rows, c, height, bottomReserved):
265 | res = 0
266 | for row in range(int(height-bottomReserved-math.ceil(c[7]))):
267 | if not rows[c[4]][row]:
268 | return row
269 | elif rows[c[4]][row][0] < rows[c[4]][res][0]:
270 | res = row
271 | return res
272 |
273 | def ConvertColor(RGB, width=1280, height=576):
274 | if RGB == 0x000000:
275 | return '000000'
276 | elif RGB == 0xffffff:
277 | return 'FFFFFF'
278 | R = (RGB >> 16) & 0xff
279 | G = (RGB >> 8) & 0xff
280 | B = RGB & 0xff
281 | if width < 1280 and height < 576:
282 | return '%02X%02X%02X' % (B, G, R)
283 | else: # VobSub always uses BT.601 colorspace, convert to BT.709
284 | ClipByte = lambda x: 255 if x > 255 else 0 if x < 0 else round(x)
285 | return '%02X%02X%02X' % (
286 | ClipByte(R*0.00956384088080656+G*0.03217254540203729+B*0.95826361371715607),
287 | ClipByte(R*-0.10493933142075390+G*1.17231478191855154+B*-0.06737545049779757),
288 | ClipByte(R*0.91348912373987645+G*0.07858536372532510+B*0.00792551253479842)
289 | )
290 |
291 | def WriteComment(f, c, row, width, height, bottomReserved, fontsize, lifetime, styleid):
292 | text = ASSEscape(c[3])
293 | styles = []
294 | if c[4] == 1:
295 | styles.append('\\an8\\pos(%(halfwidth)d, %(row)d)' % {'halfwidth': width/2, 'row': row})
296 | elif c[4] == 2:
297 | styles.append('\\an2\\pos(%(halfwidth)d, %(row)d)' % {'halfwidth': width/2, 'row': ConvertType2(row, height, bottomReserved)})
298 | elif c[4] == 3:
299 | styles.append('\\move(%(neglen)d, %(row)d, %(width)d, %(row)d)' % {'width': width, 'row': row, 'neglen': -math.ceil(c[8])})
300 | else:
301 | styles.append('\\move(%(width)d, %(row)d, %(neglen)d, %(row)d)' % {'width': width, 'row': row, 'neglen': -math.ceil(c[8])})
302 | if not (-1 < c[6]-fontsize < 1):
303 | styles.append('\\fs%.0f' % c[6])
304 | if c[5] != 0xffffff:
305 | styles.append('\\c&H%s&' % ConvertColor(c[5]))
306 | if c[5] == 0x000000:
307 | styles.append('\\3c&HFFFFFF&')
308 | ## 替换空格
309 | text = text.replace('\u2007',' ')
310 | f.write('Dialogue: 2,%(start)s,%(end)s,%(styleid)s,,0000,0000,0000,,{%(styles)s}%(text)s\n' % {'start': ConvertTimestamp(c[0]), 'end': ConvertTimestamp(c[0]+lifetime), 'styles': ''.join(styles), 'text': text, 'styleid': styleid})
311 |
312 |
313 | def CalculateLength(s):
314 | return max(map(len, s.split('\n'))) # May not be accurate
315 |
316 | def GetVideoInfo(aid,appkey,page = 1,AppSecret=None,fav = None):
317 | paras = {'id': GetString(aid),'page': GetString(page)}
318 | if fav != None:
319 | paras['fav'] = fav
320 | url = 'http://api.bilibili.cn/view?'+GetSign(paras,appkey,AppSecret)
321 | jsoninfo = JsonInfo(url)
322 | video = Video(aid,jsoninfo.Getvalue('title'))
323 | video.guankan = jsoninfo.Getvalue('play')
324 | video.commentNumber = jsoninfo.Getvalue('review')
325 | video.danmu = jsoninfo.Getvalue('video_review')
326 | video.shoucang = jsoninfo.Getvalue('favorites')
327 | video.description = jsoninfo.Getvalue('description')
328 | video.tag = []
329 | taglist = jsoninfo.Getvalue('tag')
330 | if taglist != None:
331 | for tag in taglist.split(','):
332 | video.tag.append(tag)
333 | video.cover = jsoninfo.Getvalue('pic')
334 | video.author = User(jsoninfo.Getvalue('mid'),jsoninfo.Getvalue('author'))
335 | video.page = jsoninfo.Getvalue('pages')
336 | video.date = jsoninfo.Getvalue('created_at')
337 | video.credit = jsoninfo.Getvalue('credit')
338 | video.coin = jsoninfo.Getvalue('coins')
339 | video.spid = jsoninfo.Getvalue('spid')
340 | video.cid = jsoninfo.Getvalue('cid')
341 | video.offsite = jsoninfo.Getvalue('offsite')
342 | video.partname = jsoninfo.Getvalue('partname')
343 | video.src = jsoninfo.Getvalue('src')
344 | video.tid = jsoninfo.Getvalue('tid')
345 | video.typename = jsoninfo.Getvalue('typename')
346 | video.instant_server = jsoninfo.Getvalue('instant_server')
347 | return video
348 |
349 | def GetSign(params,appkey,AppSecret=None):
350 | """
351 | 获取新版API的签名,不然会返回-3错误
352 | 待添加:【重要!】
353 | 需要做URL编码并保证字母都是大写,如 %2F
354 | """
355 | params['appkey']=appkey
356 | data = ""
357 | paras = params.keys()
358 | paras.sort()
359 | for para in paras:
360 | if data != "":
361 | data += "&"
362 | data += para + "=" + params[para]
363 | if AppSecret == None:
364 | return data
365 | m = hashlib.md5()
366 | m.update(data+AppSecret)
367 | return data+'&sign='+m.hexdigest()
368 |
369 |
370 |
371 |
372 | def GetDanmuku(cid):
373 | cid = getint(cid)
374 | url = "http://comment.bilibili.cn/%d.xml"%(cid)
375 | content = zlib.decompressobj(-zlib.MAX_WBITS).decompress(getURLContent(url))
376 | # content = GetRE(content,r']*>([^<]*)<')
377 | return content
378 |
379 |
380 | #def FilterBadChars(f):
381 | # s = f.read()
382 | # s = re.sub('[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]', '\ufffd', s)
383 | # return io.StringIO(s)
384 |
385 | def ReadCommentsBilibili(f, fontsize):
386 | dom = xml.dom.minidom.parseString(f)
387 | comment_element = dom.getElementsByTagName('d')
388 | for i, comment in enumerate(comment_element):
389 | try:
390 | p = str(comment.getAttribute('p')).split(',')
391 | assert len(p) >= 5
392 | assert p[1] in ('1', '4', '5', '6', '7')
393 | if p[1] != '7':
394 | c = str(comment.childNodes[0].wholeText).replace('/n', '\n')
395 | size = int(p[2])*fontsize/25.0
396 | yield (float(p[0]), int(p[4]), i, c, {'1': 0, '4': 2, '5': 1, '6': 3}[p[1]], int(p[3]), size, (c.count('\n')+1)*size, CalculateLength(c)*size)
397 | else: # positioned comment
398 | c = str(comment.childNodes[0].wholeText)
399 | yield (float(p[0]), int(p[4]), i, c, 'bilipos', int(p[3]), int(p[2]), 0, 0)
400 | except (AssertionError, AttributeError, IndexError, TypeError, ValueError):
401 | continue
402 |
403 | def ConvertToFile(filename_or_file, *args, **kwargs):
404 | return open(filename_or_file, *args, **kwargs)
405 |
406 |
407 | def ProcessComments(comments, f, width, height, bottomReserved, fontface, fontsize, alpha, lifetime, reduced, progress_callback):
408 | styleid = 'Danmaku2ASS_%04x' % random.randint(0, 0xffff)
409 | WriteASSHead(f, width, height, fontface, fontsize, alpha, styleid)
410 | rows = [[None]*(height-bottomReserved+1) for i in range(4)]
411 | for idx, i in enumerate(comments):
412 | if progress_callback and idx % 1000 == 0:
413 | progress_callback(idx, len(comments))
414 | if isinstance(i[4], int):
415 | row = 0
416 | rowmax = height-bottomReserved-i[7]
417 | while row <= rowmax:
418 | freerows = TestFreeRows(rows, i, row, width, height, bottomReserved, lifetime)
419 | if freerows >= i[7]:
420 | MarkCommentRow(rows, i, row)
421 | WriteComment(f, i, row, width, height, bottomReserved, fontsize, lifetime, styleid)
422 | break
423 | else:
424 | row += freerows or 1
425 | else:
426 | if not reduced:
427 | row = FindAlternativeRow(rows, i, height, bottomReserved)
428 | MarkCommentRow(rows, i, row)
429 | WriteComment(f, i, row, width, height, bottomReserved, fontsize, lifetime, styleid)
430 | elif i[4] == 'bilipos':
431 | WriteCommentBilibiliPositioned(f, i, width, height, styleid)
432 | elif i[4] == 'acfunpos':
433 | WriteCommentAcfunPositioned(f, i, width, height, styleid)
434 | elif i[4] == 'sH5Vpos':
435 | WriteCommentSH5VPositioned(f, i, width, height, styleid)
436 | else:
437 | logging.warning(_('Invalid comment: %r') % i[3])
438 | if progress_callback:
439 | progress_callback(len(comments), len(comments))
440 |
441 | def ReadComments(input_files, font_size=25.0):
442 | comments = []
443 | comments.extend(ReadCommentsBilibili(input_files, font_size))
444 | comments.sort()
445 | return comments
446 |
447 |
--------------------------------------------------------------------------------
/python API/biclass.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Wed May 28 01:22:20 2014
4 |
5 | @author: Vespa
6 | """
7 |
8 | class User():
9 | def __init__(self,m_mid=None,m_name=None):
10 | if m_mid:
11 | self.mid = m_mid
12 | if m_name:
13 | if isinstance(m_name,unicode):
14 | m_name = m_name.encode('utf8')
15 | self.name = m_name
16 | self.isApprove = None#是否是认证账号
17 | self.spaceName = None
18 | self.sex = None
19 | self.rank = None
20 | self.avatar = None
21 | self.follow = None#关注好友数目
22 | self.fans = None#粉丝数目
23 | self.article = None#投稿数
24 | self.place = None#所在地
25 | self.description = None#认证用户为认证信息 普通用户为交友宣言
26 | self.followlist = None#关注的好友列表
27 | self.friend = None
28 | self.DisplayRank = None
29 | self.message = None # 承包时会返回的承保信息
30 | # 获取空间地址
31 | def GetSpace(self):
32 | return 'http://space.bilibili.tv/'+str(self.mid)
33 |
34 |
35 |
36 | class Video():
37 | def __init__(self,m_aid=None,m_title=None):
38 | if m_aid:
39 | self.aid = m_aid
40 | if m_title:
41 | if isinstance(m_title,unicode):
42 | m_title = m_title.encode('utf8')
43 | self.title = m_title
44 | self.guankan = None
45 | self.shoucang = None
46 | self.danmu = None
47 | self.date = None
48 | self.cover = None
49 | self.commentNumber = None
50 | self.description = None
51 | self.tag = None
52 | self.author = None
53 | self.page = None
54 | self.credit = None
55 | self.coin = None
56 | self.spid = None
57 | self.cid = None
58 | self.offsite = None#Flash播放调用地址
59 | self.Iscopy = None
60 | self.subtitle = None
61 | self.duration = None
62 | self.episode = None
63 | self.arcurl = None#网页地址
64 | self.arcrank = None#不明
65 | self.tid = None
66 | self.index = None#剧番中的集数
67 | self.episode_id = None
68 | self.typename = None
69 | self.online_user = None # 当前在线观看人数
70 | self.partition_index = None # 属于分P视频的索引
71 | #不明:
72 | self.instant_server = None
73 | self.src = None
74 | self.partname = None
75 | self.allow_bp = None
76 | self.allow_feed = None
77 | self.created = None
78 | #播放信息:
79 | self.play_site = None
80 | self.play_forward = None
81 | self.play_mobile = None
82 |
83 | class Bangumi():
84 | def __init__(self):
85 | self.typeid = None
86 | self.lastupdate = None
87 | self.area = None
88 | self.bgmcount = None#番剧当前总集数
89 | self.title = None
90 | self.lastupdate_at = None
91 | self.attention = None #订阅数
92 | self.cover = None
93 | self.priority = None
94 | self.area = None
95 | self.weekday = None
96 | self.spid = None
97 | self.new = None
98 | self.scover = None
99 | self.mcover = None
100 | self.click = None
101 | self.coin = None
102 | self.season_id = None
103 | self.season_title = None
104 | self.click = None # 浏览数
105 | self.video_view = None
106 | self.episode_list = []
107 | self.tags = []
108 | self.isFinished = None
109 | self.newest_ep_id = None
110 | self.newest_ep_index = None
111 |
112 | class Comment():
113 | def __init__(self):
114 | self.post_user = User()
115 | self.lv = None#楼层
116 | self.fbid = None#评论id
117 | self.parent_id = None #被回复留言ID
118 | self.msg = None
119 | self.ad_check = None#状态 (0: 正常 1: UP主隐藏 2: 管理员删除 3: 因举报删除)
120 | self.post_user = None
121 | self.like = None
122 |
123 | class CommentList():
124 | def __init__(self):
125 | self.comments = None
126 | self.commentLen = None
127 | self.page = None
128 |
129 | class ZhuantiInfo():
130 | def __init__(self, m_spid,m_title):
131 | self.spid = m_spid
132 | if isinstance(m_title,unicode):
133 | m_title = m_title.encode('utf8')
134 | self.title = None
135 | self.author = None
136 | self.cover = None
137 | self.thumb = None
138 | self.ischeck = None #不明
139 | self.typeurl = None #总是"http://www.bilibili.com"
140 | self.tag = None
141 | self.description = None
142 | self.pubdate = None # 不明
143 | self.postdate = None
144 | self.lastupdate = None
145 | self.click = None
146 | self.favourite = None
147 | self.attention = None
148 | self.count = None
149 | self.bgmcount = None
150 | self.spcount = None
151 | self.season_id = None
152 | self.is_bangumi = None
153 | self.arcurl = None
154 | self.is_bangumi_end = None
155 |
156 | class Danmu():
157 | def __init__(self):
158 | self.t_video = None
159 | self.t_stamp = None
160 | self.mid_crc = None # 值为:hex(binascii.crc32(mid))
161 | self.danmu_type = None # 1:滚动弹幕 5:顶端弹幕 4:底部弹幕
162 | self.content = None
163 | self.danmu_color = None
164 | self.danmu_fontsize = None
165 |
166 | class SponsorInfo():
167 | def __init__(self):
168 | self.bp = None ## 剧番总B币
169 | self.percent = None #承包总比例,不知道什么鬼
170 | self.ep_bp = None ## 该话的B币
171 | self.ep_percent = None ## 该话的承包占比(估计指单话与整体的占比)
172 | self.sponsor_num = None ## 承包人数
173 | self.sponsor_user = None ## 承包人列表
174 |
175 | class LivingInfo():
176 | def __init__(self):
177 | self.url = None
178 | self.title = None
179 | self.cover = None
180 | self.mid = None
181 |
--------------------------------------------------------------------------------
/python API/support.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon May 26 23:59:09 2014
4 |
5 | @author: Vespa
6 | """
7 | import urllib2
8 | import urllib
9 | import re
10 | import json
11 | import zlib
12 | import gzip
13 | import xml.dom.minidom
14 | import hashlib
15 | from biclass import *
16 | import time
17 | import sys
18 | import os
19 | from GetAssDanmaku import *
20 | def GetRE(content,regexp):
21 | return re.findall(regexp, content)
22 |
23 | def getURLContent(url):
24 | while True:
25 | flag = 1
26 | try:
27 | headers = {'User-Agent':'Mozilla/5.0 (Windows U Windows NT 6.1 en-US rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
28 | req = urllib2.Request(url = url,headers = headers)
29 | page = urllib2.urlopen(req)
30 | content = page.read()
31 | except urllib2.HTTPError,e:
32 | if e.code == 404:
33 | return ""
34 | flag = 0
35 | time.sleep(5)
36 | if flag == 1:
37 | break
38 | if page.info().get('Content-Encoding') == 'gzip':
39 | content = zlib.decompress(content, 16+zlib.MAX_WBITS)
40 | return content
41 |
42 | class JsonInfo():
43 | def __init__(self,url,pre_deal=lambda x:x):
44 | self.info = json.loads(pre_deal(getURLContent(url)))
45 | if self.info.has_key('code') and self.info['code'] != 0:
46 | if self.info.has_key('message'):
47 | print "【Error】code=%d, msg=%s, url=%s"%(self.info['code'],self.Getvalue('message'),url)
48 | self.ERROR_MSG = self.Getvalue('message')
49 | elif self.info.has_key('error'):
50 | print "【Error】code=%d, msg=%s, url=%s"%(self.info['code'],self.Getvalue('error'),url)
51 | self.ERROR_MSG = self.Getvalue('error')
52 | self.error = True
53 | def Getvalue(self,*keys):
54 | if len(keys) == 0:
55 | return None
56 | if self.info.has_key(keys[0]):
57 | temp = self.info[keys[0]]
58 | else:
59 | return None
60 | if len(keys) > 1:
61 | for key in keys[1:]:
62 | if type(temp) == dict and temp.has_key(key):
63 | temp = temp[key]
64 | else:
65 | return None
66 | if isinstance(temp,unicode):
67 | temp = temp.encode('utf8')
68 | return temp
69 | info = None
70 | error = False
71 | ERROR_MSG = ""
72 |
73 | def GetString(t):
74 | if type(t) == int:
75 | return str(t)
76 | return t
77 |
78 | def getint(string):
79 | try:
80 | i = int(string)
81 | except:
82 | i = 0
83 | return i
84 |
85 | def DictDecode2UTF8(dict):
86 | for keys in dict:
87 | if isinstance(dict[keys],unicode):
88 | dict[keys] = dict[keys].encode('utf8')
89 | return dict
90 |
91 | def GetVideoFromRate(content):
92 | """
93 | 从视频搜索源码页面提取视频信息
94 | """
95 | #av号和标题
96 | regular1 = r']*>(.*)'
97 | info1 = GetRE(content,regular1)
98 | #观看数
99 | regular2 = r'\1'
100 | info2 = GetRE(content,regular2)
101 | #收藏
102 | regular3 = r'\1'
103 | info3 = GetRE(content,regular3)
104 | #弹幕
105 | regular4 = r'\1'
106 | info4 = GetRE(content,regular4)
107 | #日期
108 | regular5 = r'(.+)'
109 | info5 = GetRE(content,regular5)
110 | #封面
111 | regular6 = r'
]*>'
112 | info6 = GetRE(content,regular6)
113 | #Up的id和名字
114 | regular7 = r'(.+)'
115 | info7 = GetRE(content,regular7)
116 | #!!!!!!!!这里可以断言所有信息长度相等
117 | videoNum = len(info1)#视频长度
118 | videoList = []
119 |
120 | for i in range(videoNum):
121 | video_t = Video()
122 | video_t.aid = getint(info1[i][0])
123 | video_t.title = info1[i][1]
124 | video_t.guankan = getint(info2[i])
125 | video_t.shoucang = getint(info3[i])
126 | video_t.danmu = getint(info4[i])
127 | video_t.date = info5[i]
128 | video_t.cover = info6[i]
129 | video_t.author = User(info7[i][0],info7[i][1])
130 | videoList.append(video_t)
131 | return videoList
132 |
133 | def GetSign(params, appkey, AppSecret=None):
134 | """
135 | 获取新版API的签名,不然会返回-3错误
136 | """
137 | params['appkey']=appkey
138 | data = ""
139 | paras = params.keys()
140 | paras.sort()
141 | for para in paras:
142 | if data != "":
143 | data += "&"
144 | data += para + "=" + str(urllib.quote(GetString(params[para])))
145 | if AppSecret == None:
146 | return data
147 | m = hashlib.md5()
148 | m.update(data+AppSecret)
149 | return data+'&sign='+m.hexdigest()
150 |
151 | def ParseComment(danmu):
152 | dom = xml.dom.minidom.parseString(danmu)
153 | comment_element = dom.getElementsByTagName('d')
154 | for i, comment in enumerate(comment_element):
155 | p = str(comment.getAttribute('p')).split(',')
156 | danmu = Danmu()
157 | danmu.t_video = float(p[0])
158 | danmu.danmu_type = int(p[1])
159 | danmu.t_stamp = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(p[4])))
160 | danmu.mid_crc = p[6]
161 | danmu.danmu_color = ConvertColor(int(p[3]))
162 | danmu_fontsize = int(p[2])
163 | if len(comment.childNodes) != 0:
164 | danmu.content = str(comment.childNodes[0].wholeText).replace('/n', '\n')
165 | else:
166 | danmu.content = ""
167 | yield danmu
--------------------------------------------------------------------------------