精华内容
下载资源
问答
  • 直播间自动发言软件测试版beta版本
  • 就是一个简单的弹幕发送功能 弹幕区的页面: <div class=textLeft></div> <p class=text aon v-if=item.display v-for=(item,index) in doommData :key=index :id=item.id :style={'animation-duration':...
  • android弹幕评论demo

    千次下载 热门讨论 2015-07-28 09:29:10
    http://blog.csdn.net/ddovetlose/article/details/47098959 纯粹按照自己的想法仿照b站的弹幕写的一个demo,不知道正确的姿势怎么样的。
  • 常用右下角评论弹幕展示效果jQuery特效代码
  • bili弹幕评论爬取.py

    2021-04-09 17:42:35
    爬取bilibili.com视频评论弹幕
  • B站弹幕评论抓取

    2021-04-28 21:18:16
    B站弹幕评论抓取 #!/usr/bin/env python # -*- coding:utf-8 -*- # @Author: Minions # @Date: 2021-04-28 10:59:25 # @Last Modified by: Minions # @Last Modified time: 2021-04-28 21:15:36 import requests ...

    B站弹幕评论抓取

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # @Author: Minions
    # @Date: 2021-04-28 10:59:25
    # @Last Modified by:  Minions
    # @Last Modified time: 2021-04-28 21:15:36
    
    import requests
    from lxml import etree
    import re
    import json
    import time
    import xmltodict
    
    HEADERS = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
    }
    
    
    class Bili(object):
        def __init__(self, keyword):
            self.film_id = self.get_film_id(keyword)
            if self.film_id is None:
                exit()
            self.film_oid, self.film_cid = self.get_film_oid_cid()
            self.first_level_rpids = [] # 存储一级评论的rpid,方便抓取回复的评论
    
    
        def get_film_id(self, keyword):
            """
                func: 获取搜索电影的详情页面的id,可用于查找评论所需的oid
    
                args
                    keyword: 搜索关键字(目前只能输入电影名称)
    
                return: str:film_id
            """
            search_url = "https://search.bilibili.com/all?keyword=" + keyword
            resp = requests.get(search_url, headers=HEADERS)
            html = etree.HTML(resp.text)
            search_film_detail_url = html.xpath("//div["
                                                "@class='pgc-item-wrap']/a/@href")
            # print(film_detail_url)
            # 如果匹配不成功,即找不到该电影len(film_detail_url)=0
            if len(search_film_detail_url):
                file_id = re.findall('\d+', search_film_detail_url[0])[0]
                return file_id
            else:
                print("!请检查输入的电影名称!")
    
    
        def get_film_oid_cid(self):
            """
                func: 获取电影的oid和cid,oid在评论中用到,cid在弹幕中用到
    
                return: str:film_oid str:film_cid
            """
            film_detail_url = "https://www.bilibili.com/bangumi/play/ss" + \
                           self.film_id + "/?from=search"
            resp = requests.get(film_detail_url, headers=HEADERS)
            # print(resp.text)
            aid = re.findall('"episodes":\[\{"aid":(\d+),', resp.text)[0]
            film_cid = re.findall('"cid":(\d+),"cover"', resp.text)[0]
            film_oid = aid
            return film_oid, film_cid
    
    
        def get_film_detail_info(self):
            """
                func: 获取电影的详情信息(如投币数,弹幕数...)
    
                return: 返回电影详情信息
            """
            film_detail_url = "https://www.bilibili.com/bangumi/play/ss" + \
                              self.film_id + "/?from=search"
    
            resp = requests.get(film_detail_url, headers=HEADERS)
            json_text = re.findall('__INITIAL_STATE__=(.*?),"sponsor"',
                                   resp.text)[0] + '}'
            print(json_text)
            film_info_dict = json.loads(json_text)
            mediaInfo = film_info_dict["mediaInfo"]
            cover = mediaInfo["cover"]  # 视频封面
            evaluate = mediaInfo["evaluate"]  # 视频简介
            desc = mediaInfo["new_ep"]["desc"]  # 上映时间
            pub_time = mediaInfo["publish"]["pub_time"]  # 上映到b站时间
            score = mediaInfo["rating"]["score"]  # 评分
            count = mediaInfo["rating"]["count"]  # 评分人的个数
            coins = mediaInfo["stat"]["coins"]  # 投币次数
            danmakus = mediaInfo["stat"]["danmakus"]  # 弹幕总数
            favorites = mediaInfo["stat"]["favorites"]  # 追剧总数
            share = mediaInfo["stat"]["share"]  # 分享总数
            views = mediaInfo["stat"]["views"]  # 观看总数(播放量)
            aid = mediaInfo["episodes"][0]["aid"]  # aid=oid在评论和许多地方要用到
            cid = mediaInfo["episodes"][0]["cid"]  # cid用于弹幕抓取
            print(cover, evaluate, desc, pub_time, score, count, coins, danmakus,
                  favorites, share, views, aid, cid)
    
    
        def get_first_level_comments(self):
            """
                func: 获取电影下面的一级评论以及评论有关信息
    
                return: 返回一级评论的详情信息
            """
            for i in range(1, 10):
                print("-" * 30 + str(i) + "-" * 30)
                comment_url = "https://api.bilibili.com/x/v2/reply/main?&next" \
                              "=%d&type=1&oid="%i + self.film_oid
                resp = requests.get(comment_url, headers=HEADERS)
                comments_json_text = json.loads(resp.text)
                replies = comments_json_text["data"]["replies"]
                for reply in replies:
                    message = reply["content"]["message"]   # 评论内容
                    rcount = reply["rcount"]    # 评论回复人数
                    like = reply["like"]    # 评论点赞人数
                    ctime = reply["ctime"]    # 评论时间戳
                    mid = reply["member"]["mid"]    # 评论用户的ID
                    current_level = reply["member"]["level_info"]["current_level"]  #
                    #  用户等级
                    root = reply["rpid"]    # 二级评论及以下需要父集的rpid
                    self.first_level_rpids.append(root)
                    # print(message)
                    # print(message, rcount, like, ctime, mid, current_level)
    
                time.sleep(2.0)
    
    
        def get_not_first_level_comments(self):
            """
                func: 获取电影下面的非一级评论以及评论有关信息
    
            """
            # 获取非一级评论需先把一级评论下的rpid拿到
            self.get_first_level_comments()
            for rpid in self.first_level_rpids:
                print("-"*30 + "当前rpid为%s"%rpid + "-"*30)
                for i in range(1, 15):
                    print("-" * 30 + "第%s页"%str(i) + "-" * 30)
                    comment_url = "https://api.bilibili.com/x/v2/reply/reply?&pn=" \
                                  + str(i) +"&type=1&oid="+ str(self.film_oid) \
                                  +"&root=" + str(rpid)
                    # print(comment_url)
                    resp = requests.get(comment_url, headers=HEADERS)
                    comments_json_text = json.loads(resp.text)
                    replies = comments_json_text["data"]["replies"]
    
                    if replies is None:
                        print("该评论回复只有%d页"%(i-1))
                        break
    
                    for reply in replies:
                        message = reply["content"]["message"]  # 评论内容
                        rcount = reply["rcount"]  # 评论回复人数
                        like = reply["like"]  # 评论点赞人数
                        ctime = reply["ctime"]  # 评论时间戳
                        mid = reply["member"]["mid"]  # 评论用户的ID
                        current_level = reply["member"]["level_info"][
                            "current_level"]  # 用户等级
    
                        # 去掉回复xxx:
                        try:
                            message = re.findall(":(.*)", message)[0]
                        except:
                            pass
                        print(message)
    
                    time.sleep(1.0)
    
    
        def get_bullet_chat(self):
            """
                func: 获取弹幕内容
    
            """
            bullet_chat_url = "https://api.bilibili.com/x/v1/dm/list.so?oid=" + \
                              str(self.film_cid)
            resp = requests.get(bullet_chat_url, headers=HEADERS)
            resp.encoding = "utf-8"
            # xml文档解析
            xml_data = xmltodict.parse(resp.text)
            # print(xml_data)
            liat_DM = xml_data['i']['d']
            print(len(liat_DM)) # 抓取到的弹幕数量
            for i in range(len(liat_DM)):
                p = liat_DM[i]['@p']
                pub_time = time.localtime(int(p.split(',')[4]))
                pub_time = time.strftime("%Y-%m-%d %H:%M:%S", pub_time)
                print(pub_time, liat_DM[i]['#text']) # 弹幕发出时间和内容
    
    b = Bili("让子弹飞")
    # b.get_first_level_comments()
    # b.get_film_oid()
    # b.get_film_detail_info()
    # b.get_not_first_level_comments()
    # b.get_bullet_chat()
    
    

    在这里插入图片描述
    运行结果显示(获取电影详细信息)

    b = Bili("你的名字")
    # b.get_first_level_comments()
    # b.get_film_oid()
    b.get_film_detail_info()
    # b.get_not_first_level_comments()
    # b.get_bullet_chat()
    

    在这里插入图片描述

    b = Bili("让子弹飞")
    b.get_first_level_comments()
    # b.get_film_oid()
    # b.get_film_detail_info()
    # b.get_not_first_level_comments()
    # b.get_bullet_chat()
    

    运行结果显示(获取一级评论及相关信息)
    在这里插入图片描述

    展开全文
  • 移动端弹幕发射器 功能并不依赖于幻灯片网页展示端的存在,也可以用于多人版聊。 运行方法 安装node.js 下载本仓库 终端运行 npm install node index.js 浏览器打开 http://localhost:3000/danmu/2015-07-16-example...
  • 美拍弹幕评论点赞源码,源码调用的模块请自行删除和替换。
  • HTML5弹幕文字评论代码基于jQuery.1.10.2.min.js制作,页面右下角弹幕代码,发表新年祝福。
  • 基于神经网络的在线课堂弹幕评论的情感分析与研究.pdf
  • js实现的弹幕评论插件,可嵌入任意网页,与基于nodejs的websocket实现的后端 个人的小玩具,请不要用于生产 Features 对原网页代码做少量修改,添加danmu-comment.js和danmu-comment.css文件 快捷键召唤出评论框 ...
  • 资源介绍:美拍弹幕评论点赞源码,源码调用的模块请自行删除和替换。
  • 使用requests库爬取B站视频弹幕评论 爬取目标 明星大侦探巨想谈恋爱(上)、(下)和头号玩家Ⅱ(上)、(下) urls = [ 'https://www.bilibili.com/video/BV1St411S7GP', # 巨想谈恋爱 '...

    使用requests库爬取B站视频弹幕和评论以及评论的评论

    爬取目标

    明星大侦探巨想谈恋爱(上)、(下)和头号玩家Ⅱ(上)、(下)

    urls = [
            'https://www.bilibili.com/video/BV1St411S7GP',  # 巨想谈恋爱
            'https://www.bilibili.com/video/BV1Ut411i7dk',
            'https://www.bilibili.com/video/BV14t411a7aN',  # 头号玩家
            'https://www.bilibili.com/video/BV1xt41187ti'
        ]
    

    主要有四个获取数据的URL

    1、爬取目标视频的URL

    例如:https://www.bilibili.com/video/BV14t411a7aN

    • 根据url获取BV号
    • 从返回的请求页面中获取av号
      av号
    • 根据BV号获取cid(cid是获取弹幕url中的参数)
      URL为:https://api.bilibili.com/x/player/pagelist?bvid=BV14t411a7aN&jsonp=jsonp
      返回结果如下:
      在这里插入图片描述
    2、爬取目标视频弹幕的URL

    请求的URL:http://comment.bilibili.com/72211064.xml
    返回结果如下:
    在这里插入图片描述
    可以看到是xml格式的数据,之后解析即可,具体解析代码:

    response = requests.get(danmu_url, headers=headers)
    if response.status_code == 200:
    with open('bilibili.xml', 'wb') as fp:
       fp.write(response.content)
    html_comment = etree.parse('bilibili.xml', etree.HTMLParser())
    ds = html_comment.xpath('//d')
    danmu_list = []
    for d in ds:
    	p = d.xpath('./@p')[0].split(',')
    	danmu_current_time = p[0]  # 弹幕出现的时间
    	danmu_mode = p[1]  # 弹幕模式:1..3 滚动弹幕 4底端弹幕 5顶端弹幕 6.逆向弹幕 7精准定位 8高级弹幕
    	danmu_font_size = p[2]  # 弹幕字号
    	danmu_font_color = p[3]  # 弹幕字体颜色
    	danmu_send_time = p[4]  # 弹幕发送的时间
    	danmu_send_time = timestamp_datetime(int(danmu_send_time))
    	danmu_pool = p[5]  # 弹幕池 0普通池 1字幕池 2特殊池 【目前特殊池为高级弹幕专用】
    	danmu_send_id = p[6]  # 弹幕发送者id
    	danmu_id = p[7]  # 弹幕在弹幕数据库中的id
    	text = d.xpath('./text()')[0]
    	comment = {
    	   'danmu_current_time': danmu_current_time,
    	   'danmu_send_time': danmu_send_time,
    	   'danmu_send_id': danmu_send_id,
    	   'text': text
    	}
    danmu_list.append(comment)
    
    3、爬取目标视频的评论URL

    URL:https://api.bilibili.com/x/v2/reply?pn=1&type=1&oid=41111008&sort=1
    其中oid就是之前获取到的av号
    返回结果如下:
    在这里插入图片描述

    4、爬取目标视频评论的评论的URL

    URL:https://api.bilibili.com/x/v2/reply/reply?&pn=1&type=1&oid=41111008&ps=10&root=1327071827
    其返回结果如下:
    在这里插入图片描述
    ps字段就是每页10条记录
    root字段就是获取到评论的数据里面的rpid,如下图:
    在这里插入图片描述

    实现代码

    '''
    @Description: 爬取B站弹幕和评论
    @Author: sikaozhifu
    @Date: 2020-06-24 11:29:58
    @LastEditTime: 2020-07-02 19:13:42
    @LastEditors: Please set LastEditors
    '''
    import requests
    from lxml import etree
    import re
    import time
    import pymongo
    import math
    from pyecharts import options
    from pyecharts.charts import Bar
    headers = {
        'User-Agent':
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
    }
    
    '''
    @description: 日期格式转换
    @param : value
    @return: dt
    '''
    
    
    def timestamp_datetime(value):
        format = r'%Y-%m-%d %H:%M:%S'
        # value为传入的值为时间戳(整形),如:1332888820
        value = time.localtime(value)
        # 经过localtime转换后变成
        # time.struct_time(tm_year=2012, tm_mon=3, tm_mday=28, tm_hour=6, tm_min=53, tm_sec=40, tm_wday=2, tm_yday=88, tm_isdst=0)
        # 最后再经过strftime函数转换为正常日期格式。
        dt = time.strftime(format, value)
        return dt
    
    
    def parse_data(dbname):
        com = dbname.comments
        perfix = 'https:'
        urls = [
            'https://www.bilibili.com/video/BV1St411S7GP',  # 巨想谈恋爱
            'https://www.bilibili.com/video/BV1Ut411i7dk',
            'https://www.bilibili.com/video/BV14t411a7aN',  # 头号玩家
            'https://www.bilibili.com/video/BV1xt41187ti'
        ]
        ID = 0
        for url in urls:
            response = requests.get(url, headers=headers)
            html = etree.HTML(response.text)
            title = html.xpath('//h1[@class = "video-title"]/@title')[0]  # video的标题
            up_url = perfix + html.xpath('//div[@class = "name"]/a/@href')[0]
            up_id = re.search(r'\d+', up_url).group(0)  # up_id
            up_name = html.xpath('//div[@class = "name"]/a/text()')[0]  # up_name
            av_id_url = html.xpath('//meta[@itemprop = "url"]/@content')[0]
            av_id = re.search(r'\d+', av_id_url).group(0)  # av_id
            bvid = re.search(r'video/(.*)', url).group(1)  # bv_id
            bvid_url = 'https://api.bilibili.com/x/player/pagelist?bvid=%s&jsonp=jsonp' % bvid
            response = requests.get(bvid_url, headers=headers)
            cid = response.json()['data'][0]['cid']
            danmu_url = 'http://comment.bilibili.com/%s.xml' % cid
            time.sleep(1)
            response = requests.get(danmu_url, headers=headers)
            if response.status_code == 200:
                with open('bilibili.xml', 'wb') as fp:
                    fp.write(response.content)
            html_comment = etree.parse('bilibili.xml', etree.HTMLParser())
            ds = html_comment.xpath('//d')
            danmu_list = []
            for d in ds:
                p = d.xpath('./@p')[0].split(',')
                danmu_current_time = p[0]  # 弹幕出现的时间
                danmu_mode = p[1]  # 弹幕模式:1..3 滚动弹幕 4底端弹幕 5顶端弹幕 6.逆向弹幕 7精准定位 8高级弹幕
                danmu_font_size = p[2]  # 弹幕字号
                danmu_font_color = p[3]  # 弹幕字体颜色
                danmu_send_time = p[4]  # 弹幕发送的时间
                danmu_send_time = timestamp_datetime(int(danmu_send_time))
                danmu_pool = p[5]  # 弹幕池 0普通池 1字幕池 2特殊池 【目前特殊池为高级弹幕专用】
                danmu_send_id = p[6]  # 弹幕发送者id
                danmu_id = p[7]  # 弹幕在弹幕数据库中的id
                text = d.xpath('./text()')[0]
                comment = {
                    'danmu_current_time': danmu_current_time,
                    'danmu_send_time': danmu_send_time,
                    'danmu_send_id': danmu_send_id,
                    'text': text
                }
                danmu_list.append(comment)
                # print(danmu_send_time)
                # print(text)
    
            comment_url = 'https://api.bilibili.com/x/v2/reply?pn=1&type=1&oid=%s&sort=1' % av_id
            response = requests.get(comment_url, headers=headers)
            count = response.json()['data']['page']['count']  # 评论总数
            page_count = math.ceil(int(count) / 20)  # 评论总页数
            comment_list = []
            for pn in range(1, page_count + 1):
                comment_url = 'https://api.bilibili.com/x/v2/reply?pn=%s&type=1&oid=%s&sort=1' % (pn, av_id)
                response = requests.get(comment_url, headers=headers)
                replies = response.json()['data']['replies']
                for reply in replies:
                    reply_id = reply['member']['mid']  # 评论者id
                    reply_name = reply['member']['uname']  # 评论者昵称
                    reply_sex = reply['member']['sex']  # 评论者性别
                    reply_time = timestamp_datetime(int(reply['ctime']))  # 评论时间
                    reply_like = reply['like']  # 评论点赞数
                    reply_content = reply['content']['message']  # 评论内容
                    reply_info = {
                        'reply_id': reply_id,
                        'reply_name': reply_name,
                        'reply_sex': reply_sex,
                        'reply_time': reply_time,
                        'reply_like': reply_like,
                        'reply_content': reply_content
                    }
                    comment_list.append(reply_info)
                    rcount = reply['rcount']  # 表示回复的评论数
                    page_rcount = math.ceil(int(rcount) / 10)  # 回复评论总页数
                    root = reply['rpid']
                    for reply_pn in range(1, page_rcount + 1):
                        reply_url = 'https://api.bilibili.com/x/v2/reply/reply?&pn=%s&type=1&oid=%s&ps=10&root=%s' % (reply_pn, av_id, root)
                        response = requests.get(reply_url, headers=headers)
                        rreplies = response.json()['data']['replies']
                        for reply in rreplies:
                            reply_id = reply['member']['mid']  # 评论者id
                            reply_name = reply['member']['uname']  # 评论者昵称
                            reply_sex = reply['member']['sex']  # 评论者性别
                            reply_time = timestamp_datetime(int(reply['ctime']))  # 评论时间
                            reply_like = reply['like']  # 评论点赞数
                            reply_content = reply['content']['message']  # 评论内容
                            reply_info = {
                                'reply_id': reply_id,
                                'reply_name': reply_name,
                                'reply_sex': reply_sex,
                                'reply_time': reply_time,
                                'reply_like': reply_like,
                                'reply_content': reply_content
                            }
                            comment_list.append(reply_info)
            info = {
                'ID': ID,
                'video_title': title,
                'up_id': up_id,
                'up_name': up_name,
                'danmu_list': danmu_list,
                'comment_list': comment_list
            }
            print(info)
            com.insert_one(info)
            ID = ID + 1
            time.sleep(1)
    
    
    def show_web(show_data):
        for data in show_data:
            title = data[0]
            danmu_month_count = data[1]
            bar = Bar()
            bar.add_xaxis(['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'])
            bar.add_yaxis('弹幕数量', danmu_month_count)
            bar.set_global_opts(title_opts=options.TitleOpts(title=title))
            bar.render('bar_danmu_count.html')
            break
    
    
    def get_show_data(dbname):
        danmu_data = get_data(dbname)
        show_data = []
        for data in danmu_data:
            title = data['video_title']
            danmu_list = data['danmu_list']
            danmu_month_count = []
            for index, danmu in enumerate(danmu_list):
                num = len(danmu)
                danmu_month_count.append(num)
            data = (title, danmu_month_count)
            show_data.append(data)
        return show_data
    
    
    def sort_data_by_time(danmu_data):
        danmu_data = sorted(danmu_data, key=lambda data_time: data_time['danmu_send_time'])
        return danmu_data
    
    
    def get_data(dbname):
        com = dbname.comments
        documents = com.find()
        data_list = []
        for document in documents:
            danmu_data = []
            video_title = document['video_title']
            danmu_list = document['danmu_list']
            # danmu_year_set = set()
            danmu_month_set = set()
            for danmu in danmu_list:
                danmu_send_time = danmu['danmu_send_time']
                year = danmu_send_time.split(' ')[0].split('-')[0]
                month = danmu_send_time.split(' ')[0].split('-')[1]
                day = danmu_send_time.split(' ')[0].split('-')[2]
                # print('%s-%s-%s' % (year, month, day))
                # danmu_year_set.add(int(year))
                if year == '2019':
                    danmu_month_set.add(int(month))
                    data = {
                        'danmu_send_time': danmu['danmu_send_time'],
                        'month': int(month),
                        'day': int(day),
                        'text': danmu['text']
                    }
                    danmu_data.append(data)
                # print(data)
            danmu_data = sort_data_by_time(danmu_data)
            data_group_by_month = []
            for x in range(0, 12):
                index = x + 1
                data_month = []
                for danmu in danmu_data:
                    if danmu['month'] == index:
                        data_month.append(danmu)
                data_group_by_month.append(data_month)
            # print(data_group_by_month)
            data = {
                'video_title': video_title,
                'danmu_year': 2019,
                # 'danmu_month': data_group_by_month,
                'danmu_list': data_group_by_month
            }
            data_list.append(data)
        return data_list
    
    
    '''
    @description: 根据日期获取星期
    @param : 日期
    @return: 0 - 6 表示周日到周六
    '''
    
    
    def get_week(date_time):
        y = int(date_time.split(' ')[0].split('-')[0])
        m = int(date_time.split(' ')[0].split('-')[1])
        d = int(date_time.split(' ')[0].split('-')[2])
        week = -1
        if m == 1 or m == 2:
            m += 12
            y = y - 1
        week = int((d + 2 * m + 3 * (m + 1) / 5 + y + y/4 - y/100 + y/400 + 1) % 7)
        return week
    
    
    '''
    @description: 返回星期几的弹幕数量
    @param : dbname
    @return: 
    '''
    
    
    def get_week_data(dbname):
        com = dbname.comments
        documents = com.find()
        data_list = []
        for document in documents:
            video_title = document['video_title']
            danmu_list = document['danmu_list']
            danmu_data = sort_data_by_time(danmu_list)
            data_group_by_week = []
            for x in range(0, 7):
                data_week = []
                for danmu in danmu_data:
                    week = get_week(danmu['danmu_send_time'])
                    if week == x:
                        data_week.append(danmu)
                data_group_by_week.append(data_week)
            data = {
                'video_title': video_title,
                'danmu_list': data_group_by_week
            }
            data_list.append(data)
        week_data = []
        for data in data_list:
            title = data['video_title']
            danmu_list = data['danmu_list']
            danmu_month_count = []
            for index, danmu in enumerate(danmu_list):
                num = len(danmu)
                danmu_month_count.append(num)
            data = (title, danmu_month_count)
            week_data.append(data)
        return week_data
    
    
    def main():
        client = pymongo.MongoClient(host='127.0.0.1', port=27017)
        db = client.bilibili
        parse_data(db)
        # week_data = get_week_data(db)
        # show_web(show_data)
        # print(danmu_data)
        # week = get_week('2020-7-5')
        # print(week)
        # print(week_data)
    
    
    if __name__ == "__main__":
        main()
    
    

    运行结果

    存到Mongodb里面
    在Mongodb compass里面展示如下:
    在这里插入图片描述

    展开全文
  • android 弹幕评论效果

    千次阅读 2015-07-28 09:21:04
    纯粹按照自己的想法仿照b站的弹幕写的一个demo,不知道正确的姿势怎么样的。 首先,一条弹幕就是一个textview public abstract class Danmu extends TextView{ private Context context; private int position;/...

    纯粹按照自己的想法仿照b站的弹幕写的一个demo,不知道正确的姿势怎么样的。

    demo下载地址

    首先,一条弹幕就是一个textview

    public abstract class Danmu extends TextView{
        private Context context;
        private int position;//弹幕的位置,在屏幕哪一行
    
        public Danmu(Context context) {
            super(context);
            this.context=context;
            setSingleLine();
        }
    
        public int getPosition() {
            return position;
        }
    
        public void setPosition(int position) {
            this.position = position;
        }
    
        public abstract void send();
    
    
    }

    将弹幕放在一个相对布局容器中

     <RelativeLayout
            android:id="@+id/danmuContainer"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="3" />
    

    当字数很多时,会放不下所有文字,所以手动设置了容器的宽度

    容器设置足够大就好

    ViewGroup.LayoutParams lp=container.getLayoutParams();
            lp.width=DensityUtils.sp2px(this,15)*100;
            container.setLayoutParams(lp);
    弹幕分为好几种这里做了普通的从右到左的,逆向的,还有在顶部和底部的

    普通弹幕由两个TranslateAnimation完成,第一个是当弹幕移动后空出足够多空间时通知其他弹幕可以跟在它后面,第二个动画完成接下来的移出屏幕

    public class NormalDanmu extends Danmu {
        private Animation animation0,animation1;
        private int fx0,tx0,fx1,tx1;
        private int duration0,duration1;
        private OnAnimationEndListener onAnimationEndListener;
    
        public interface OnAnimationEndListener
        {
            public void clearPosition();//第一个动画结束,将当前行设置为可以发送弹幕
            public void animationEnd();//弹幕完全移出屏幕
        }
    
        public NormalDanmu(Context context,int fx,int tx)
        {
            super(context);
            this.fx0=fx;
            this.tx0=Math.abs(fx)-Math.abs(tx)-100;//第一个动画结束位置,当尾部空出100像素时就可以通知其他弹幕跟上了
            this.fx1=tx0;
            this.tx1=tx;
    
            duration0=2000*(Math.abs(tx0-fx0))/DensityUtils.getScreenW(context);
            duration1=2000*(Math.abs(tx1-fx1))/DensityUtils.getScreenW(context);
    
            initAnimation();
        }
    
        private void initAnimation()
        {
            animation0=new TranslateAnimation(fx0,tx0,0,0);
            animation1=new TranslateAnimation(fx1,tx1,0,0);
            animation0.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
    
                }
    
                @Override
                public void onAnimationEnd(Animation animation) {
    
                    clearAnimation();
                    startAnimation(animation1);
                    if (onAnimationEndListener!=null)
                    {
                        onAnimationEndListener.clearPosition();
                    }
                }
    
                @Override
                public void onAnimationRepeat(Animation animation) {
    
                }
            });
    
            animation0.setFillAfter(true);
            animation0.setDuration(duration0);
            animation0.setInterpolator(new AccelerateInterpolator());
    
            animation1.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
    
                }
    
                @Override
                public void onAnimationEnd(Animation animation) {
    
                    if(onAnimationEndListener!=null)
                    {
                        onAnimationEndListener.animationEnd();
                    }
    
                }
    
                @Override
                public void onAnimationRepeat(Animation animation) {
    
                }
            });
    
            animation1.setFillAfter(true);
            animation1.setDuration(duration1);
            animation1.setInterpolator(new DecelerateInterpolator());
        }
    
        public void setOnAnimationEndListener(OnAnimationEndListener onAnimationEndListener)
        {
            this.onAnimationEndListener=onAnimationEndListener;
        }
    
        @Override
        public void send() {
            startAnimation(animation0);
        }
    }

    然后发送弹幕 final NormalDanmu danmu=new NormalDanmu(this,sWidth,(int) -paint.measureText(str));

    swidth表示屏幕宽度,paint.measureText(str)是textview宽度,表示从最右端移动到左边完全移出屏幕

    lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);

    lp.topMargin=i*danmuHeight;

    danmuHeight是一个textview的高度,这里设置放在容器的第i行


    private void setDanmu()
        {
            String ss="按是按时按是android.os.BinderProx按是";
            int ll=ss.length()*DensityUtils.sp2px(this,15);
            int ran= new Random().nextInt(ss.length());
            String str=ss.substring(ran);
            final NormalDanmu danmu=new NormalDanmu(this,sWidth,(int) -paint.measureText(str));
            danmu.setTextSize(15);
            danmu.setText(str);
            danmu.setOnAnimationEndListener(new NormalDanmu.OnAnimationEndListener() {
                @Override
                public void clearPosition() {
    
                    sendPosition.put(danmu.getPosition(), false);
                }
    
                @Override
                public void animationEnd() {
    
                    container.removeView(danmu);
                }
    
            });
    
            for(int i=0;i<count;i++)
            {
                if(sendPosition.get(i)==false)
                {
                    danmu.setPosition(i);
                    RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, danmuHeight);
                    lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
                    lp.topMargin=i*danmuHeight;
                    danmu.setGravity(Gravity.CENTER);
                    container.addView(danmu, lp);
    
                    danmu.send();
    
                    sendPosition.put(i,true);
                    break;
                }
    
            }
        }




    逆向弹幕就是和普通弹幕移动方向不同其他完全一样


    顶部和底部的弹幕主要就是显示几秒后再消失就行了比较简单

    public class TopDanmu extends Danmu {
        private OnDisappearListener onDisappearListener;
        private int duration;
        private Handler handler=new Handler()
        {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if(msg.what==1)
                {
                    if(onDisappearListener!=null)
                    {
                        onDisappearListener.disappear();
                    }
                }
            }
        };
    
        public TopDanmu(Context context,int duration) {
            super(context);
            this.duration=duration;
        }
    
    
    
        public interface OnDisappearListener
        {
            public void disappear();
        }
        @Override
        public void send() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(duration);
                        handler.sendEmptyMessage(1);
    
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    
        public void setOnDisappearListener(OnDisappearListener onDisappearListener )
        {
            this.onDisappearListener=onDisappearListener;
        }
    }
    发送顶部弹幕

    顶部弹幕要水平居中,这里的容器设置的宽度超过的屏幕大小,所以要手动计算弹幕的水平位置

    int margin= (int) ((sWidth-paint.measureText(danmu.getText().toString()))/2);


    private void setTopDanmu()
        {
            String ss="按是按时按是android.os.BinderProx按是";
    
            int ran= new Random().nextInt(ss.length());
            String str=ss.substring(ran);
            int ll=str.length()*DensityUtils.sp2px(this, 15);
            final TopDanmu danmu=new TopDanmu(this,2000);
            danmu.setTextSize(15);
            danmu.setText(str);
            danmu.setTextColor(Color.GREEN);
            danmu.setOnDisappearListener(new TopDanmu.OnDisappearListener() {
                @Override
                public void disappear() {
                    container.removeView(danmu);
                    topSendPosition.put(danmu.getPosition(), false);
                }
            });
    
            for(int i=0;i<count;i++)
            {
                if(topSendPosition.get(i)==false)
                {
                    danmu.setPosition(i);
                    RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, danmuHeight);
                    lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
                    int margin= (int) ((sWidth-paint.measureText(danmu.getText().toString()))/2);
                    lp.topMargin=i*danmuHeight;
                    lp.leftMargin=margin;
                    danmu.setGravity(Gravity.CENTER);
                    container.addView(danmu, lp);
    
                    danmu.send();
    
                    topSendPosition.put(i,true);
                    break;
                }
    
            }
        }






    展开全文
  • 弹幕效果全屏的弹幕文字基于js.所编写的代码基于JavaScript,效果想视频软件一样的效果,即时性
  • 可以通过UP主的视频空间地址爬取UP下的全部视频弹幕以及评论,并统一生成词云 注:评论下的评论暂不支持全量获取 支持继续爬取,调整禁闭/common/get_urls.py中的线程池=pool.ThreadPool(x)分子,但需要注意,B站...
  • 主要介绍了Python爬虫爬取Bilibili弹幕过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 一、前言《送你一朵小红花》2020年12月31日上映,最近的微博和身边的人都在讨论这部电影,所以今天就来对这部电影的弹幕评论分析。本文完整源码获取方式:在底部二、获取数据先给出视频地址:...

    一、前言

    《送你一朵小红花》2020年12月31日上映,最近的微博和身边的人都在讨论这部电影,所以今天就来对这部电影的弹幕评论分析。

    本文完整源码获取方式:在底部

    二、获取数据

    先给出视频地址:

    https://www.bilibili.com/video/BV1nX4y1u7BH?from=search&seid=13601446070722236862
    

    这个B站视频的播放量达到了74万多,底下有很多评论以及弹幕,所以现在了这个视频去进行分析。

    爬取过B站弹幕的小伙伴都知道,B站的弹幕是有专门的URL去获取的

    https://api.bilibili.com/x/v1/dm/list.so?oid=id
    

    oid参数的id是对于的视频id(通过F12可以看到这个id

    因此本次要爬取的视频id是266851015

    弹幕地址

    https://api.bilibili.com/x/v1/dm/list.so?oid=266851015
    

    编程获取数据

    请求库和请求头

    ####李运辰  2021-01-04
    import requests
    headers = {
         'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0'
    }
    

    请求数据,并去掉无关的p标签

    ####李运辰  2021-01-04
    url="https://api.bilibili.com/x/v1/dm/list.so?oid=266851015"
    r = requests.get(url, headers=headers)
    r.encoding = 'utf-8'
    list_s = r.text.split("<d p=")
    list_s = list_s[1:]
    

    写入txt文件,保存为t2.txt

    with open("t2.txt","a+",encoding='utf-8') as f:
      for i in list_s:
            i = (i.split(">"))[1].replace("</d","")
            #print(i)
            i = i.replace("?","").replace("。","").replace(",","").replace("+","").replace("!","").replace("....","").replace(".......","")
            f.write(str(i)+"\n")
    

    为了方便分析,所以需要去掉一些符号?、!,等等这些

    i = i.replace("?","").replace("。","").replace(",","").replace("+","").replace("!","").replace("....","").replace(".......","")
    

    保存后的txt结果如下

    三、词云可视化分析

    同样需要使用到jieba库

    from stylecloud import gen_stylecloud
    import jieba
    

    6种词云图案

    为了不同的视觉效果,这里使用了6种不同的图案去画词云图

    (1、国旗,2、翼龙,3、狗,4、猫,5、鸽子,6、QQ)

    icon_name='',#国旗
    icon_name='fas fa-dragon',#翼龙
    icon_name='fas fa-dog',#狗
    icon_name='fas fa-cat',#猫
    icon_name='fas fa-dove',#鸽子
    icon_name='fab fa-qq',#qq
    

    画好的词云图保存到本地

    simsun.ttc是词云图的字体,必须加中文字体,否则格式错误

    gen_stylecloud(text=result, icon_name=icon_name, font_path='simsun.ttc', output_name=picp)  #
    

    代码

    ####李运辰  2021-01-04
    with open(file_name, 'r', encoding='utf8') as f:
        word_list = jieba.cut(f.read())
        result = " ".join(word_list)  # 分词用 隔开
        # 制作中文云词
        icon_name = ""
        if icon == "1":
            icon_name = ''
        elif icon == "2":
            icon_name = 'fas fa-dragon'
        elif icon == "3":
            icon_name = 'fas fa-dog'
        elif icon == "4":
            icon_name = 'fas fa-cat'
        elif icon == "5":
            icon_name = 'fas fa-dove'
        elif icon == "6":
            icon_name = 'fab fa-qq'
        """
        # icon_name='',#国旗
        # icon_name='fas fa-dragon',#翼龙
        #icon_name='fas fa-dog',#狗
        # icon_name='fas fa-cat',#猫
        # icon_name='fas fa-dove',#鸽子
        # icon_name='fab fa-qq',#qq
        """
        picp = file_name.split('.')[0] + str(icon) + '.png'
        if icon_name is not None and len(icon_name) > 0:
            gen_stylecloud(text=result, icon_name=icon_name, font_path='simsun.ttc', output_name=picp)  # 必须加中文字体,否则格式错误
        else:
            gen_stylecloud(text=result, font_path='simsun.ttc', output_name=picp)  # 必须加中文字体,否则格式错误
    

    效果图

    1.国旗-词云图

    2.翼龙-词云图

    3.狗-词云图

    4.猫-词云图

    5.鸽子-词云图

    6.QQ-词云图

    分析

    最好的易烊千玺,最“丧”的韦一航,最感人的《送你一朵小红花》

    词云图中,字体越大词,说明提到的次数越多

    1、可以看出《送你一朵小红花》这部电影的看点是易烊千玺的角色韦一航

    2、全员演技派,情绪真挚动人,通过弹幕评论,大家对这部电影表现出强烈的喜欢,同时里面的演技赢得了大家的认可。

    3、这部电影完成了一组很有趣的社会实验,我们观众这个群体的存在将本片预设的某些主题延展到了影片之外的真实世界之中。

    结尾

    1、最后大家有什么问题,或者对代码不懂的,可以在下方评论

    2、本文完整源码获取方式

    本文完整源码获取方式

    公众号回复:送你一朵小红花

    ------------------- End -------------------

    各种爬虫源码获取方式

    公众号回复:爬虫源码

    4个小时我赚了600块

    记录一次爬虫接单项目【采集国际淘宝数据】

    终于还是对B站动漫动手了!【数据可视化分析】

    欢迎大家点赞,留言,转发,转载,感谢大家的相伴与支持

    想加入Python学习群请在后台回复【入群

    万水千山总是情,点个【在看】行不行

     

     
    【加群获取学习资料QQ群:901381280】
    【各种爬虫源码获取方式】
    识别文末二维码,回复:爬虫源码
    欢迎关注公众号:Python爬虫数据分析挖掘,方便及时阅读最新文章
    回复【开源源码】免费获取更多开源项目源码
    

    æìâèÿæëçà

    展开全文
  • HTML5手机视频弹幕文字评论代码,新的评价视频弹幕,评价显示视频中JS效果。
  • wilddog评论文字弹幕效果代码是一款基于jQuery制作的,利用野狗云实现弹幕的发送以及屏幕弹幕的消除。 <title>wilddog评论文字弹幕效果代码 </title> [removed][removed] [removed][removed] ...
  • 本文实例为大家分享了Android实现弹幕效果的具体代码,供大家参考,具体内容如下 首先分析一下,他是由三层布局来共同完成的,第一层视频布局,第二层字幕布局,第三层输入框布局,要想让这三个布局在同一页面上,...
  • AcFunDanmaku是用C# 和 .Net Core 3.1编写的AcFun直播弹幕工具。 该项目分为13个子项目。 AcFunDanmu AcFun直播弹幕解析工具。开发中 在AcFunDanmu文件夹中运行generate.bat或generate.sh csharp生成C# Protobuf文件...
  • 主要介绍了JavaScript直播评论弹幕切图功能点集合效果代码的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
  • 工具准备: 云采爬虫:... 目标: 比如我们抓取这个视频的数据: ... 主要抓取评论、标题、弹幕这些信息,如图: 数据建模: 整个数据结构预览如下: 其中有两个关键的字段,分...
  • 大家对B站不陌生吧,特别是他...今天小猿圈web前端讲师就用jQuery实现弹幕评论效果,希望对你有所启发。首先第一步:布局CSS部分<style> *{padding: 0;margin: 0; font-family: "微软雅黑"; font-size: 16px; ...
  • 前言 利用Python实现抓取腾讯视频弹幕...本文以爬取电影《革命者》为例,讲解如何爬取腾讯视频的弹幕评论! 目标网址 https://v.qq.com/x/cover/mzc00200m72fcup.html 抓取弹幕 分析网址 依然进入浏览器的开发者工具
  • HTML5弹幕式滚动评论留言墙

    千次阅读 2018-01-29 08:53:13
    我们不生产代码,我们只是大数据的搬运工。为大家找到一个经典版并且改动空间很大的一个弹幕式滚动评论留言墙的代码,基本页面如下: 全部文件链接(百度云盘):https://pan.baidu.com/s/1dzQsP4
  • 1、微信小程序—-弹幕的实现(无后台) 小程序刚刚出来,现在网上的demo是多,但是要找到一个自己需要的却不容易。今天跟大家分享自己写的一个弹幕功能。 效果图:  我的思路是这样的,先用标签确定是否打开弹幕,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,689
精华内容 1,875
关键字:

弹幕评论