├── 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 --------------------------------------------------------------------------------