我用go colly仿照一个python的视频爬取教程,写了一个go的视频爬取程序,然后稍稍改造了一下,用来爬取某站的合集视频,但是爬取速度不太让人满意,一次只能爬取一个视频,大家能不能 用goroutine改写一下 ,用多个协程,增加爬取速度?
我的go语言入门还不深,我试过给主函数加协程,但是每次都还是只能爬取两个链接,不知道为什么,也试过用协程来同时爬取音频视频,但是我的方法也不对
改一下对应位置应该能用的
package main
import (
"bookCrawler/collyTry/06test/crawler"
"fmt"
"strconv"
)
func main() {
url := "https://www.bilibili.com/video/把这串中文替换为合集视频的BV号?p="
for i := 1; i <= 合集数量; i++ { // 用于循环爬取具有合集的某站视频
fmt.Println("正在处理第", i, "个文件")
fmt.Println(crawler.Response(url + strconv.Itoa(i)))
}
}
package crawler
import (
"encoding/json"
"fmt"
"github.com/gocolly/colly/v2"
"os"
"os/exec"
"regexp"
)
// Response response 访问解析链接
func Response(url string) string {
c := colly.NewCollector(
colly.UserAgent("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60"))
re := regexp.MustCompile(`window.__playinfo__=(.*?)}`)
var title string
c.OnHTML("title", func(e *colly.HTMLElement) {
title = e.Text[:len(e.Text)-22]
fmt.Println(title)
})
c.OnHTML("script", func(e *colly.HTMLElement) {
match := re.FindStringSubmatch(e.Text) // 用正则表达式匹配palyinfo
if len(match) > 1 {
//fmt.Println(e.Text)
fmt.Println()
var data map[string]interface{}
q := []byte(e.Text)
q = q[20:] // 删去不需要的内容来转化为json格式
err := json.Unmarshal(q, &data)
if err != nil {
fmt.Println("发现错误:", err)
}
// 分别提取音频和视频链接
audioUrl := data["data"].(map[string]interface{})["dash"].(map[string]interface{})["audio"].([]interface{})[0].(map[string]interface{})["baseUrl"]
videoUrl := data["data"].(map[string]interface{})["dash"].(map[string]interface{})["video"].([]interface{})[0].(map[string]interface{})["baseUrl"]
// 下载文件
download(videoUrl.(string), audioUrl.(string), title, c)
}
})
if err := c.Visit(url); err != nil {
fmt.Println("cVisit访问页面链接失败:", err)
}
c.Wait()
return url + "finished"
}
// download 下载文件
func download(videoUrl string, audioUrl string, title string, c *colly.Collector) {
d := c.Clone()
// 防盗链
d.OnRequest(func(r *colly.Request) {
r.Headers.Set("Referer", "https://www.bilibili.com")
}) // On scraped response
d.OnScraped(func(e *colly.Response) {
fmt.Println("Downloading:", e.Request.URL.String())
if e.Request.URL.String() == audioUrl {
if err := e.Save(title + ".mp3"); err != nil {
fmt.Println("mp3保存失败:", err)
}
} else {
if err := e.Save(title + ".mp4"); err != nil {
fmt.Println("mp4保存失败:", err)
}
}
})
if err := d.Visit(videoUrl); err != nil {
fmt.Println("访问视频失败:", err)
}
if err := d.Visit(audioUrl); err != nil {
fmt.Println("访问音频失败:", err)
}
d.Wait()
merge(title)
}
// merge 合并文件
func merge(title string) {
mp3File, mp4File := title+".mp3", title+".mp4"
outputFile := "video/" + title + "_.mp4"
cmd := exec.Command("ffmpeg", "-i", mp4File, "-i", mp3File, "-c:v", "copy", "-c:a", "aac", "-strict", "experimental", outputFile)
fmt.Println("ffmpeg程序开始运行")
err := cmd.Run()
if err != nil {
fmt.Println("Error:", err)
return
}
if err := os.Remove(mp3File); err != nil {
fmt.Println("删除mp3失败:", err)
}
if err := os.Remove(mp4File); err != nil {
fmt.Println("删除mp4失败:", err)
}
fmt.Println(title, " Success")
}
另外,大家对用chatgpt改代码有没有什么意见呀