Skip to content

Commit 706d54d

Browse files
authored
更换api版bilibiliparse (#255)
* Update bilibili_parse.go * make lint happy * 改进提出的问题
1 parent 9ac2767 commit 706d54d

File tree

1 file changed

+156
-42
lines changed

1 file changed

+156
-42
lines changed

plugin/bilibili_parse/bilibili_parse.go

Lines changed: 156 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,76 +2,190 @@
22
package bilibiliparse
33

44
import (
5+
"encoding/json"
56
"errors"
7+
"net/http"
68
"regexp"
7-
"strings"
9+
"strconv"
10+
"time"
811

912
ctrl "github.com/FloatTech/zbpctrl"
1013
"github.com/FloatTech/zbputils/control"
11-
"github.com/antchfx/htmlquery"
14+
"github.com/FloatTech/zbputils/ctxext"
15+
"github.com/FloatTech/zbputils/web"
1216
zero "github.com/wdvxdr1123/ZeroBot"
1317
"github.com/wdvxdr1123/ZeroBot/message"
1418
)
1519

20+
type result struct {
21+
Data struct {
22+
Bvid string `json:"bvid"`
23+
Aid int `json:"aid"`
24+
Copyright int `json:"copyright"`
25+
Pic string `json:"pic"`
26+
Title string `json:"title"`
27+
Pubdate int `json:"pubdate"`
28+
Ctime int `json:"ctime"`
29+
Rights struct {
30+
IsCooperation int `json:"is_cooperation"`
31+
} `json:"rights"`
32+
Owner struct {
33+
Mid int `json:"mid"`
34+
Name string `json:"name"`
35+
} `json:"owner"`
36+
Stat struct {
37+
Aid int `json:"aid"`
38+
View int `json:"view"`
39+
Danmaku int `json:"danmaku"`
40+
Reply int `json:"reply"`
41+
Favorite int `json:"favorite"`
42+
Coin int `json:"coin"`
43+
Share int `json:"share"`
44+
Like int `json:"like"`
45+
} `json:"stat"`
46+
Staff []struct {
47+
Title string `json:"title"`
48+
Name string `json:"name"`
49+
Follower int `json:"follower"`
50+
} `json:"staff"`
51+
} `json:"data"`
52+
}
53+
54+
type owner struct {
55+
Data struct {
56+
Card struct {
57+
Fans int `json:"fans"`
58+
} `json:"data"`
59+
}
60+
}
61+
1662
const (
17-
validRe = "https://www.bilibili.com/video/(BV[0-9a-zA-Z]+)"
63+
videoapi = "https://api.bilibili.com/x/web-interface/view?"
64+
cardapi = "http://api.bilibili.com/x/web-interface/card?"
65+
origin = "https://www.bilibili.com/video/"
1866
)
1967

20-
var re = regexp.MustCompile(validRe)
68+
var (
69+
reg = regexp.MustCompile(`https://www.bilibili.com/video/([0-9a-zA-Z]+)`)
70+
limit = ctxext.NewLimiterManager(time.Second*10, 1)
71+
)
2172

73+
// 插件主体
2274
func init() {
23-
engine := control.Register("bilibiliparse", &ctrl.Options[*zero.Ctx]{
75+
en := control.Register("bilibiliparse", &ctrl.Options[*zero.Ctx]{
2476
DisableOnDefault: false,
2577
Help: "b站视频链接解析\n" +
2678
"- https://www.bilibili.com/video/BV1xx411c7BF | https://www.bilibili.com/video/av1605 | https://b23.tv/I8uzWCA | https://www.bilibili.com/video/bv1xx411c7BF",
2779
})
80+
en.OnRegex(`(av[0-9]+|BV[0-9a-zA-Z]{10}){1}`).SetBlock(true).Limit(limit.LimitByGroup).
81+
Handle(func(ctx *zero.Ctx) {
82+
id := ctx.State["regex_matched"].([]string)[1]
83+
m, err := parse(id)
84+
if err != nil {
85+
ctx.SendChain(message.Text("ERROR: ", err))
86+
return
87+
}
88+
ctx.Send(m)
89+
})
90+
en.OnRegex(`https://www.bilibili.com/video/([0-9a-zA-Z]+)`).SetBlock(true).Limit(limit.LimitByGroup).
91+
Handle(func(ctx *zero.Ctx) {
92+
id := ctx.State["regex_matched"].([]string)[1]
93+
m, err := parse(id)
94+
if err != nil {
95+
ctx.SendChain(message.Text("ERROR: ", err))
96+
return
97+
}
98+
ctx.Send(m)
99+
})
100+
en.OnRegex(`(https://b23.tv/[0-9a-zA-Z]+)`).SetBlock(true).Limit(limit.LimitByGroup).
101+
Handle(func(ctx *zero.Ctx) {
102+
url := ctx.State["regex_matched"].([]string)[1]
103+
realurl, err := getrealurl(url)
104+
if err != nil {
105+
ctx.SendChain(message.Text("ERROR: ", err))
106+
return
107+
}
108+
id, err := cuturl(realurl)
109+
if err != nil {
110+
ctx.SendChain(message.Text("ERROR: ", err))
111+
return
112+
}
113+
m, err := parse(id)
114+
if err != nil {
115+
ctx.SendChain(message.Text("ERROR: ", err))
116+
return
117+
}
118+
ctx.Send(m)
119+
})
120+
}
28121

29-
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) {
30-
bilibiliURL := ctx.State["regex_matched"].([]string)[1]
31-
if bilibiliURL[0] != 'h' {
32-
bilibiliURL = "https://www.bilibili.com/video/" + bilibiliURL
122+
// parse 解析视频数据
123+
func parse(id string) (m message.Message, err error) {
124+
var vid string
125+
switch id[:2] {
126+
case "av":
127+
vid = "aid=" + id[2:]
128+
case "BV":
129+
vid = "bvid=" + id
130+
}
131+
data, err := web.GetData(videoapi + vid)
132+
if err != nil {
133+
return
134+
}
135+
var r result
136+
err = json.Unmarshal(data, &r)
137+
if err != nil {
138+
return
139+
}
140+
m = make(message.Message, 0, 16)
141+
m = append(m, message.Text("标题:", r.Data.Title, "\n"))
142+
if r.Data.Rights.IsCooperation == 1 {
143+
for i := 0; i < len(r.Data.Staff); i++ {
144+
if i != len(r.Data.Staff) {
145+
m = append(m, message.Text(r.Data.Staff[i].Title, ":", r.Data.Staff[i].Name, ",粉丝:", r.Data.Staff[i].Follower, "\n"))
146+
} else {
147+
m = append(m, message.Text(r.Data.Staff[i].Title, ":", r.Data.Staff[i].Name, ",粉丝:", r.Data.Staff[i].Follower))
148+
}
33149
}
34-
m, err := parseURL(bilibiliURL)
150+
} else {
151+
o, err := getcard(r.Data.Owner.Mid)
35152
if err != nil {
36-
ctx.SendChain(message.Text("ERROR:", err))
37-
return
153+
return m, err
38154
}
39-
ctx.Send(m)
40-
})
155+
m = append(m, message.Text("\nUP主:", r.Data.Owner.Name, ",粉丝:", o.Data.Card.Fans, "\n"))
156+
}
157+
m = append(m, message.Text("播放:", r.Data.Stat.View, ",弹幕:", r.Data.Stat.Danmaku, "\n"),
158+
message.Image(r.Data.Pic),
159+
message.Text("\n点赞:", r.Data.Stat.Like, ",投币:", r.Data.Stat.Coin, "\n收藏:", r.Data.Stat.Favorite, ",分享:", r.Data.Stat.Share, "\n", origin, id))
160+
return
41161
}
42162

43-
func parseURL(bilibiliURL string) (m message.Message, err error) {
44-
doc, err := htmlquery.LoadURL(bilibiliURL)
163+
// getrealurl 获取跳转后的链接
164+
func getrealurl(url string) (realurl string, err error) {
165+
data, err := http.Head(url)
45166
if err != nil {
46167
return
47168
}
48-
videoURL := htmlquery.FindOne(doc, "/html/head/meta[@itemprop='url']").Attr[2].Val
49-
if !re.MatchString(videoURL) {
50-
err = errors.New("parse html error: invalid video url")
169+
realurl = data.Request.URL.String()
170+
return
171+
}
172+
173+
// cuturl 获取aid或者bvid
174+
func cuturl(url string) (id string, err error) {
175+
if !reg.MatchString(url) {
176+
err = errors.New("invalid video url")
177+
return
178+
}
179+
id = reg.FindStringSubmatch(url)[1]
180+
return
181+
}
182+
183+
// getcard 获取个人信息
184+
func getcard(mid int) (o owner, err error) {
185+
data, err := web.GetData(cardapi + "mid=" + strconv.Itoa(mid))
186+
if err != nil {
51187
return
52188
}
53-
m = make(message.Message, 0, 9)
54-
title := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/h1/span/text()").Data
55-
m = append(m, message.Text(title, "\n"))
56-
upName := strings.TrimSpace(htmlquery.FindOne(doc, "//*[@id='v_upinfo']/div[2]/div[1]/a[1]/text()").Data)
57-
fanNumber := htmlquery.InnerText(htmlquery.FindOne(doc, "//i[@class='van-icon-general_addto_s']").NextSibling.NextSibling)
58-
m = append(m, message.Text("UP: ", upName, ", 粉丝: ", fanNumber, "\n"))
59-
view := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[@class='view']/text()").Data
60-
dm := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[@class='dm']/text()").Data
61-
m = append(m, message.Text(view, dm, "\n"))
62-
t := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[3]/text()").Data
63-
m = append(m, message.Text(t))
64-
image := htmlquery.FindOne(doc, "/html/head/meta[@itemprop='image']").Attr[2].Val
65-
m = append(m, message.Image(image))
66-
like := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='like']/text()").Data
67-
coin := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='coin']/text()").Data
68-
m = append(m, message.Text("\n点赞: ", strings.TrimSpace(like), ", 投币: ", strings.TrimSpace(coin), "\n"))
69-
collect := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='collect']/text()").Data
70-
share := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='share']/text()").Data
71-
m = append(m, message.Text("收藏: ", strings.TrimSpace(collect), ", 分享: ", strings.TrimSpace(share), "\n"))
72-
play := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[1]/text()").Data
73-
danmaku := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[2]/text()").Data
74-
m = append(m, message.Text(strings.TrimSpace(play), "播放, ", strings.TrimSpace(danmaku), "弹幕\n"))
75-
m = append(m, message.Text(videoURL))
189+
err = json.Unmarshal(data, &o)
76190
return
77191
}

0 commit comments

Comments
 (0)