From 71799a48584285ede2814de11927444a56842262 Mon Sep 17 00:00:00 2001 From: fantasticbin Date: Wed, 3 Apr 2024 22:36:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=96=87=E4=BB=B6=E5=A4=B9?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E7=BB=86=E8=8A=82=EF=BC=8C=E7=AB=A0=E8=8A=82?= =?UTF-8?q?=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cmd/lib.go | 12 +++-- src/cmd/start.go | 115 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 112 insertions(+), 15 deletions(-) diff --git a/src/cmd/lib.go b/src/cmd/lib.go index a01cb42..9af89eb 100644 --- a/src/cmd/lib.go +++ b/src/cmd/lib.go @@ -6,16 +6,20 @@ import ( ) var ( - url string - max int - output string - host = "https://img4.qy0.ru" + url string + folderTitleUrl string + max int + output string + chapter int + host = "https://img4.qy0.ru" ) func init() { rootCmd.PersistentFlags().StringVarP(&url, "url", "u", "", "除域名外的链接") rootCmd.PersistentFlags().IntVarP(&max, "max", "m", 1, "图片最大值") rootCmd.PersistentFlags().StringVarP(&output, "output", "o", "anime", "设置漫画抓取结果的保存位置,默认为当前用户的主目录下的 anime 文件夹") + rootCmd.PersistentFlags().StringVarP(&folderTitleUrl, "folderTitleUrl", "t", "", "文件夹标题抓取链接") + rootCmd.PersistentFlags().IntVarP(&chapter, "chapter", "c", 1, "指定章节,用于文件夹标题抓取") } func IfPathNotExistDoMkdir(path string) error { diff --git a/src/cmd/start.go b/src/cmd/start.go index db62f22..f81ec59 100644 --- a/src/cmd/start.go +++ b/src/cmd/start.go @@ -6,6 +6,8 @@ import ( "io" "net/http" "os" + "path/filepath" + "regexp" "strconv" "strings" "sync" @@ -13,22 +15,36 @@ import ( var wg sync.WaitGroup +// start 开始执行 func start() { - err := IfPathNotExistDoMkdir(output) + path := output + if folderTitleUrl != "" { + chapterTitle := findChapterTitle(folderTitleUrl, chapter) + title := strings.Join([]string{ + "第", + strconv.Itoa(chapter), + "章-", + chapterTitle, + }, "") + path = filepath.Join(output, title) // 组装章节路径 + } + + err := IfPathNotExistDoMkdir(path) if err != nil { - fmt.Println("输出目录创建失败") + fmt.Println("输出目录创建失败:", err) return } for i := 1; i <= max; i++ { wg.Add(1) - go get(i) + go get(i, path) } wg.Wait() } -func get(num int) { +// get 获取漫画图片 +func get(num int, path string) { defer wg.Done() // 兼容未携带斜杆的地址 @@ -36,10 +52,27 @@ func get(num int) { url = "/" + url } - urlSlice := strings.Split(url, "_") // 取URL组装 - fileSlice := strings.Split(urlSlice[1], ".") // 取后缀名 - fileName := strconv.Itoa(num) + "." + fileSlice[1] // 组装文件名 - imgUrl := host + urlSlice[0] + "_" + fmt.Sprintf("%02d", num) + "." + fileSlice[1] // 组装图片URL + numString := strconv.Itoa(num) + urlSlice := strings.Split(url, "_") // 取URL组装 + fileSlice := strings.Split(urlSlice[1], ".") // 取后缀名 + fileName := strings.Join([]string{ // 组装文件名 + numString, + fileSlice[1], + }, ".") + + urlNum := numString + if fileSlice[0][0] == '0' { // 序号首位为0,则链接补0 + urlNum = fmt.Sprintf("%02d", num) + } + + imgUrl := strings.Join([]string{ // 组装图片URL + host, + urlSlice[0], + "_", + urlNum, + ".", + fileSlice[1], + }, "") fmt.Println("获取图片:" + imgUrl) resp, err := http.Get(imgUrl) @@ -47,15 +80,27 @@ func get(num int) { fmt.Println(fileName, "图片获取失败:", err) return } - defer resp.Body.Close() + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + fmt.Println(fileName, "http请求关闭失败:", err) + return + } + }(resp.Body) reader := bufio.NewReaderSize(resp.Body, 32*1024) - file, err := os.Create(output + "/" + fileName) + file, err := os.Create(path + "/" + fileName) if err != nil { fmt.Println(fileName, "图片创建失败:", err) return } - defer file.Close() + defer func(file *os.File) { + err := file.Close() + if err != nil { + fmt.Println(fileName, "文件流关闭失败:", err) + return + } + }(file) _, err = io.Copy(file, reader) if err != nil { @@ -63,3 +108,51 @@ func get(num int) { return } } + +// findChapterTitle 解析文件夹标题 +func findChapterTitle(url string, num int) string { + resp, err := http.Get(url) + if err != nil { + fmt.Println("请求文件夹标题失败:", err) + return "" + } + + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + fmt.Println("文件夹标题http请求关闭失败:", err) + return + } + }(resp.Body) + + body, err := io.ReadAll(resp.Body) + if err != nil { + fmt.Println("文件夹标题读取失败:", err) + return "" + } + + content := string(body) + re := regexp.MustCompile(`\\u7b2c` + strconv.Itoa(num) + `\\u8bdd (.+?)"`) + matches := re.FindAllStringSubmatch(content, -1) + + if len(matches) == 0 { + return "" + } + unquoted, err := strconv.Unquote(`"` + matches[0][1] + `"`) + if err != nil { + fmt.Println("文件夹标题转码失败:", err) + return "" + } + + replacements := map[string]string{ + "?": "?", + ":": ":", + "!": "!", + } + unquoted = strings.TrimSpace(unquoted) + for old, re := range replacements { + unquoted = strings.ReplaceAll(unquoted, old, re) + } + + return unquoted +}