Skip to content

Commit

Permalink
feat: support video download for zhihu.com #1203
Browse files Browse the repository at this point in the history
  • Loading branch information
MisakaTAT committed Mar 27, 2023
1 parent 7580afe commit ede6fb8
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 0 deletions.
1 change: 1 addition & 0 deletions app/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ import (
_ "github.com/iawia002/lux/extractors/yinyuetai"
_ "github.com/iawia002/lux/extractors/youku"
_ "github.com/iawia002/lux/extractors/youtube"
_ "github.com/iawia002/lux/extractors/zhihu"
)
17 changes: 17 additions & 0 deletions extractors/zhihu/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package zhihu

// minimum field
type video struct {
PlayList struct {
FHD resolution `json:"FHD"`
HD resolution `json:"HD"`
SD resolution `json:"SD"`
} `json:"playlist_v2"`
}

// minimum field
type resolution struct {
Size int64 `json:"size"`
Format string `json:"format"`
PlayURL string `json:"play_url"`
}
90 changes: 90 additions & 0 deletions extractors/zhihu/zhihu.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package zhihu

import (
"encoding/json"
"fmt"
"github.com/iawia002/lux/extractors"
"github.com/iawia002/lux/request"
"github.com/iawia002/lux/utils"
"github.com/pkg/errors"
"strings"
)

const (
videoURL = "www.zhihu.com/zvideo"
api = "https://lens.zhihu.com/api/v4/videos/"
)

func init() {
extractors.Register("zhihu", New())
}

type extractor struct{}

func New() extractors.Extractor {
return &extractor{}
}

func (e *extractor) Extract(url string, option extractors.Options) ([]*extractors.Data, error) {
if !strings.Contains(url, videoURL) {
return nil, errors.WithStack(extractors.ErrURLParseFailed)
}

var err error
html, err := request.Get(url, url, nil)
if err != nil {
return nil, errors.WithStack(err)
}

videoID := utils.MatchOneOf(html, `"videoId":"(\d+)"`)
titleMatch := utils.MatchOneOf(html, `<title.*?>(.*?)</title>`)

if len(videoID) <= 1 {
return nil, errors.New("zhihu video id extract failed")
}

title := "Unknown"
if len(titleMatch) > 1 {
title = titleMatch[1]
}

resp, err := request.GetByte(fmt.Sprintf("%s%s", api, videoID[1]), url, nil)
if err != nil {
return nil, errors.WithStack(err)
}
var data video
if err = json.Unmarshal(resp, &data); err != nil {
return nil, errors.WithStack(err)
}

streams := make(map[string]*extractors.Stream)
resolutions := map[string]resolution{
"FHD": data.PlayList.FHD,
"HD": data.PlayList.HD,
"SD": data.PlayList.SD,
}

for k, v := range resolutions {
stream := &extractors.Stream{
Parts: []*extractors.Part{
{
URL: v.PlayURL,
Size: v.Size,
Ext: v.Format,
},
},
Size: v.Size,
}
streams[k] = stream
}

return []*extractors.Data{
{
Site: "知乎 zhihu.com",
Title: title,
Streams: streams,
Type: extractors.DataTypeVideo,
URL: url,
},
}, nil
}
29 changes: 29 additions & 0 deletions extractors/zhihu/zhihu_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package zhihu

import (
"github.com/iawia002/lux/extractors"
"github.com/iawia002/lux/test"
"testing"
)

func TestDownload(t *testing.T) {
tests := []struct {
name string
args test.Args
}{
{
name: "video test",
args: test.Args{
URL: "https://www.zhihu.com/zvideo/1620162752064061440",
Title: `Cursor, GPT-4 驱动的强大代码编辑器 - 知乎`,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
data, err := New().Extract(tt.args.URL, extractors.Options{})
test.CheckError(t, err)
test.Check(t, tt.args, data[0])
})
}
}

0 comments on commit ede6fb8

Please sign in to comment.