mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-19 22:00:11 +08:00
更换api版bilibiliparse (#255)
* Update bilibili_parse.go * make lint happy * 改进提出的问题
This commit is contained in:
parent
9ac276767d
commit
706d54db76
@ -2,36 +2,115 @@
|
|||||||
package bilibiliparse
|
package bilibiliparse
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
ctrl "github.com/FloatTech/zbpctrl"
|
||||||
"github.com/FloatTech/zbputils/control"
|
"github.com/FloatTech/zbputils/control"
|
||||||
"github.com/antchfx/htmlquery"
|
"github.com/FloatTech/zbputils/ctxext"
|
||||||
|
"github.com/FloatTech/zbputils/web"
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
zero "github.com/wdvxdr1123/ZeroBot"
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type result struct {
|
||||||
|
Data struct {
|
||||||
|
Bvid string `json:"bvid"`
|
||||||
|
Aid int `json:"aid"`
|
||||||
|
Copyright int `json:"copyright"`
|
||||||
|
Pic string `json:"pic"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Pubdate int `json:"pubdate"`
|
||||||
|
Ctime int `json:"ctime"`
|
||||||
|
Rights struct {
|
||||||
|
IsCooperation int `json:"is_cooperation"`
|
||||||
|
} `json:"rights"`
|
||||||
|
Owner struct {
|
||||||
|
Mid int `json:"mid"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"owner"`
|
||||||
|
Stat struct {
|
||||||
|
Aid int `json:"aid"`
|
||||||
|
View int `json:"view"`
|
||||||
|
Danmaku int `json:"danmaku"`
|
||||||
|
Reply int `json:"reply"`
|
||||||
|
Favorite int `json:"favorite"`
|
||||||
|
Coin int `json:"coin"`
|
||||||
|
Share int `json:"share"`
|
||||||
|
Like int `json:"like"`
|
||||||
|
} `json:"stat"`
|
||||||
|
Staff []struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Follower int `json:"follower"`
|
||||||
|
} `json:"staff"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type owner struct {
|
||||||
|
Data struct {
|
||||||
|
Card struct {
|
||||||
|
Fans int `json:"fans"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
validRe = "https://www.bilibili.com/video/(BV[0-9a-zA-Z]+)"
|
videoapi = "https://api.bilibili.com/x/web-interface/view?"
|
||||||
|
cardapi = "http://api.bilibili.com/x/web-interface/card?"
|
||||||
|
origin = "https://www.bilibili.com/video/"
|
||||||
)
|
)
|
||||||
|
|
||||||
var re = regexp.MustCompile(validRe)
|
var (
|
||||||
|
reg = regexp.MustCompile(`https://www.bilibili.com/video/([0-9a-zA-Z]+)`)
|
||||||
|
limit = ctxext.NewLimiterManager(time.Second*10, 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
// 插件主体
|
||||||
func init() {
|
func init() {
|
||||||
engine := control.Register("bilibiliparse", &ctrl.Options[*zero.Ctx]{
|
en := control.Register("bilibiliparse", &ctrl.Options[*zero.Ctx]{
|
||||||
DisableOnDefault: false,
|
DisableOnDefault: false,
|
||||||
Help: "b站视频链接解析\n" +
|
Help: "b站视频链接解析\n" +
|
||||||
"- https://www.bilibili.com/video/BV1xx411c7BF | https://www.bilibili.com/video/av1605 | https://b23.tv/I8uzWCA | https://www.bilibili.com/video/bv1xx411c7BF",
|
"- https://www.bilibili.com/video/BV1xx411c7BF | https://www.bilibili.com/video/av1605 | https://b23.tv/I8uzWCA | https://www.bilibili.com/video/bv1xx411c7BF",
|
||||||
})
|
})
|
||||||
|
en.OnRegex(`(av[0-9]+|BV[0-9a-zA-Z]{10}){1}`).SetBlock(true).Limit(limit.LimitByGroup).
|
||||||
engine.OnRegex("(av[0-9]+|BV[0-9a-zA-Z]+|https://b23.tv/[0-9a-zA-Z]+|bv[0-9a-zA-Z]+){1}").SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
Handle(func(ctx *zero.Ctx) {
|
||||||
bilibiliURL := ctx.State["regex_matched"].([]string)[1]
|
id := ctx.State["regex_matched"].([]string)[1]
|
||||||
if bilibiliURL[0] != 'h' {
|
m, err := parse(id)
|
||||||
bilibiliURL = "https://www.bilibili.com/video/" + bilibiliURL
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
m, err := parseURL(bilibiliURL)
|
ctx.Send(m)
|
||||||
|
})
|
||||||
|
en.OnRegex(`https://www.bilibili.com/video/([0-9a-zA-Z]+)`).SetBlock(true).Limit(limit.LimitByGroup).
|
||||||
|
Handle(func(ctx *zero.Ctx) {
|
||||||
|
id := ctx.State["regex_matched"].([]string)[1]
|
||||||
|
m, err := parse(id)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Send(m)
|
||||||
|
})
|
||||||
|
en.OnRegex(`(https://b23.tv/[0-9a-zA-Z]+)`).SetBlock(true).Limit(limit.LimitByGroup).
|
||||||
|
Handle(func(ctx *zero.Ctx) {
|
||||||
|
url := ctx.State["regex_matched"].([]string)[1]
|
||||||
|
realurl, err := getrealurl(url)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id, err := cuturl(realurl)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m, err := parse(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
return
|
return
|
||||||
@ -40,38 +119,73 @@ func init() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseURL(bilibiliURL string) (m message.Message, err error) {
|
// parse 解析视频数据
|
||||||
doc, err := htmlquery.LoadURL(bilibiliURL)
|
func parse(id string) (m message.Message, err error) {
|
||||||
|
var vid string
|
||||||
|
switch id[:2] {
|
||||||
|
case "av":
|
||||||
|
vid = "aid=" + id[2:]
|
||||||
|
case "BV":
|
||||||
|
vid = "bvid=" + id
|
||||||
|
}
|
||||||
|
data, err := web.GetData(videoapi + vid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
videoURL := htmlquery.FindOne(doc, "/html/head/meta[@itemprop='url']").Attr[2].Val
|
var r result
|
||||||
if !re.MatchString(videoURL) {
|
err = json.Unmarshal(data, &r)
|
||||||
err = errors.New("parse html error: invalid video url")
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m = make(message.Message, 0, 9)
|
m = make(message.Message, 0, 16)
|
||||||
title := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/h1/span/text()").Data
|
m = append(m, message.Text("标题:", r.Data.Title, "\n"))
|
||||||
m = append(m, message.Text(title, "\n"))
|
if r.Data.Rights.IsCooperation == 1 {
|
||||||
upName := strings.TrimSpace(htmlquery.FindOne(doc, "//*[@id='v_upinfo']/div[2]/div[1]/a[1]/text()").Data)
|
for i := 0; i < len(r.Data.Staff); i++ {
|
||||||
fanNumber := htmlquery.InnerText(htmlquery.FindOne(doc, "//i[@class='van-icon-general_addto_s']").NextSibling.NextSibling)
|
if i != len(r.Data.Staff) {
|
||||||
m = append(m, message.Text("UP: ", upName, ", 粉丝: ", fanNumber, "\n"))
|
m = append(m, message.Text(r.Data.Staff[i].Title, ":", r.Data.Staff[i].Name, ",粉丝:", r.Data.Staff[i].Follower, "\n"))
|
||||||
view := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[@class='view']/text()").Data
|
} else {
|
||||||
dm := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[@class='dm']/text()").Data
|
m = append(m, message.Text(r.Data.Staff[i].Title, ":", r.Data.Staff[i].Name, ",粉丝:", r.Data.Staff[i].Follower))
|
||||||
m = append(m, message.Text(view, dm, "\n"))
|
}
|
||||||
t := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[3]/text()").Data
|
}
|
||||||
m = append(m, message.Text(t))
|
} else {
|
||||||
image := htmlquery.FindOne(doc, "/html/head/meta[@itemprop='image']").Attr[2].Val
|
o, err := getcard(r.Data.Owner.Mid)
|
||||||
m = append(m, message.Image(image))
|
if err != nil {
|
||||||
like := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='like']/text()").Data
|
return m, err
|
||||||
coin := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='coin']/text()").Data
|
}
|
||||||
m = append(m, message.Text("\n点赞: ", strings.TrimSpace(like), ", 投币: ", strings.TrimSpace(coin), "\n"))
|
m = append(m, message.Text("\nUP主:", r.Data.Owner.Name, ",粉丝:", o.Data.Card.Fans, "\n"))
|
||||||
collect := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='collect']/text()").Data
|
}
|
||||||
share := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='share']/text()").Data
|
m = append(m, message.Text("播放:", r.Data.Stat.View, ",弹幕:", r.Data.Stat.Danmaku, "\n"),
|
||||||
m = append(m, message.Text("收藏: ", strings.TrimSpace(collect), ", 分享: ", strings.TrimSpace(share), "\n"))
|
message.Image(r.Data.Pic),
|
||||||
play := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[1]/text()").Data
|
message.Text("\n点赞:", r.Data.Stat.Like, ",投币:", r.Data.Stat.Coin, "\n收藏:", r.Data.Stat.Favorite, ",分享:", r.Data.Stat.Share, "\n", origin, id))
|
||||||
danmaku := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[2]/text()").Data
|
return
|
||||||
m = append(m, message.Text(strings.TrimSpace(play), "播放, ", strings.TrimSpace(danmaku), "弹幕\n"))
|
}
|
||||||
m = append(m, message.Text(videoURL))
|
|
||||||
|
// getrealurl 获取跳转后的链接
|
||||||
|
func getrealurl(url string) (realurl string, err error) {
|
||||||
|
data, err := http.Head(url)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
realurl = data.Request.URL.String()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// cuturl 获取aid或者bvid
|
||||||
|
func cuturl(url string) (id string, err error) {
|
||||||
|
if !reg.MatchString(url) {
|
||||||
|
err = errors.New("invalid video url")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id = reg.FindStringSubmatch(url)[1]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// getcard 获取个人信息
|
||||||
|
func getcard(mid int) (o owner, err error) {
|
||||||
|
data, err := web.GetData(cardapi + "mid=" + strconv.Itoa(mid))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(data, &o)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user