An easy method of f***ing annoying danmakus in videos on Bilibili

Warning

The program may trigger the security system of Bilibili if you send too much requests rapidly especially when you want to report danmakus, comments, etc.
The program is restricted for learning use. Do not use it to do anything against policies of Bilibili.
And the author is innocent for any third party use, legal or illegal.

0. Abstract

Because of the commercialization of Bilibili, a lot of new users joined it. These new users enriches the variety of the community but it turned out that this action has side effects. New users don't follow the rules and send danmakus subjectively. And it's annoying to see those meaningless danmakus. Here is a solution to it.

1.1 What makes a danmaku danmaku?

When a user sends a danmaku, he sends a requests to the server of Bilibili. And we can get history danmakus in xml format. For example:
<d p="490.19100,1,25,16777215,1584268892,0,a16f**dd,299508*****521095">蒙古上单对位击杀睿马一粥粘</d>
In this tag we can get some information including:

  • The time the danmaku can appear on screen;
  • The type of the danmaku;
  • The font size of danmaku;
  • The time stamp;
  • The pool the danmaku belongs to;
  • The encrypted uid of the user(a16f**dd);
  • The id of the danmaku(299508*****521095);
  • The content of danmaku;

And the last 3 items are all things we need!

1.2 How to get danmaku

To get the danmakus in a video, you need to call api of Bilibili.
Here is a method to get danmakus in a video.

def GetCid(bv):#convert bv to cid.
    headers={
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36',
    'Host':'api.bilibili.com',
    'content-type':'application/x-www-form-urlencoded'
    }
    data={}
    data.update(bvid=bv)
    #print(data)
    rslt=requests.get('http://api.bilibili.com/x/player/pagelist',headers=headers,
                      params=data,timeout=10)
    print(rslt.text)
    rsltJson=json.loads('['+rslt.text+']')
    cid=rsltJson[0]['data'][0]['cid']
    return cid

def GetDanmaku(cid):
    headers={
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36',
    'Host':'api.bilibili.com',
    'content-type':'application/x-www-form-urlencoded'
    }
    data={}
    data.update(oid=cid)
    rslt=requests.get('http://api.bilibili.com/x/v1/dm/list.so',headers=headers,
                      params=data,timeout=10)
    return rslt

2.1 Preparations before reporting the danmakus

Before you report the danmakus, you need to log in to Bilibili.
Here is a method to get the info you need.

def loginQr():
    print('打开b站客户端,扫码并确认后关闭扫码窗口即可。')
    headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36',
    'Host':'passport.bilibili.com'
    }
    rslt=requests.get('http://passport.bilibili.com/qrcode/getLoginUrl',
                  headers=headers,timeout=10)
    urlJson=json.loads('['+rslt.text+']')
    url=urlJson[0]['data']['url']
    sp=os.getcwd()+'\\'
    myqr.run(words=url,
         version=1,
         level='M',
         save_dir=sp,
        )
    root=Tk()
    root.resizable(width='false', height='false')
    root.title='QrCode'
    label=Label(root,text='使用b站客户端扫码,扫完关掉窗口')
    label.grid(row=0,column=0)
    img=Image.open('qrcode.png')
    photo=ImageTk.PhotoImage(img)
    imglabel=Label(root,image=photo)
    imglabel.grid(row=1,column=0,columnspan=3)
    root.mainloop()
    return urlJson

def loginRslt(data):
    headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36',
    'Host':'passport.bilibili.com'
    }
    postData={}
    postData.update(oauthKey=data[0]['data']['oauthKey'])
    #print(postData)
    loginInfo=requests.post('http://passport.bilibili.com/qrcode/getLoginInfo',
                           headers=headers,data=postData,timeout=10)
    #print(loginInfo.text)
    #print(str(loginInfo.cookies))
    return loginInfo
loginInfo=loginRslt(loginQr())
sessdata=loginInfo.cookies['SESSDATA']
bili_jct=loginInfo.cookies['bili_jct']

2.2 Report danmaku

def reportdm(key,csrf,dmid,cid):
    headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36',
    'Host':'api.bilibili.com',
    'content-type':'application/x-www-form-urlencoded'
    }
    c = {
    'csrf':csrf,
    'SESSDATA':key
    }
    postData={
    'csrf':csrf,
    'cid':cid,
    'dmid':dmid,
    'reason':'9'
    }
    rslt=requests.post('http://api.bilibili.com/x/dm/report/add',
                           cookies=c,headers=headers,data=postData,timeout=10)
    print(rslt.text)

"csrf" is the bili_token.
"key" is the session data.

3. Conclusion

Although a lot of users send annoying damakus, and it's not easy to report them manually, we can still find another way to accomplish our goal with the help of this program. But most importantly, a good environment cannot be created by keep reporting and banning users. However, it seems that the old days are gone, and Bilibili is no longer Mikufans. Nothing will stop Mr. Chen's commercialization plan. Then what we'll have tomorrow will be a Brave New Bilibili.

13