diff --git a/CHANGELOG b/CHANGELOG index 79218ba..d5b45e4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,15 +1,19 @@ ## 更新日志文件 - 2022.8.28 go版本 - 1. windows平台,ui界面,重新生成syso文件,对应用windows平台386,x86_64 + 2022.10.16 go版本 + 1. 添加https://www.zhhbq.com/小说网站支持 + 2. 更新单元测试ebookdl_test.go,使用 gopkg.in/check.v1 做为测试框架 + + 2022.8.28 go版本 + 1. windows平台,ui界面,重新生成syso文件,对应用windows平台386,x86_64 2. 修改ui界面生成的版本号为v2.0.0.0 3. 删除ui/resource.syso以解决在Linux系统的编译连接时问题 4. Linux平台,内嵌kindlegen到程序中,索马里时使用go-memexec来加载程序 5. Linux平台,实现单个文件可执行,不需要其它依赖文件 - 2022.08.26 go版本 + 2022.08.26 go版本 1. windows平台,使用embed内嵌kindlegen.exe到程序中,运行时使用go-memexec来加载程序 - 2. windows平台,实现单个文件可执行,不需要其它依赖文件 + 2. windows平台,实现单个文件可执行,不需要其它依赖文件 2022.08.25 go版本 1. 更新go版本为v1.16+ diff --git a/README.md b/README.md index 6fb9680..a732d85 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ 网文下载器 - [![GitHub license](https://img.shields.io/github/license/sndnvaps/ebookdownloader)](https://github.com/sndnvaps/ebookdownloader/blob/master/LICENSE) +[![GitHub license](https://img.shields.io/github/license/sndnvaps/ebookdownloader)](https://github.com/sndnvaps/ebookdownloader/blob/master/LICENSE) [![Build Status](https://travis-ci.org/sndnvaps/ebookdownloader.svg?branch=master)](https://travis-ci.org/sndnvaps/ebookdownloader)[![release_version](https://img.shields.io/github/release/sndnvaps/ebookdownloader.svg)](https://github.com/sndnvaps/ebookdownloader/releases)[![Download Count](https://img.shields.io/github/downloads/sndnvaps/ebookdownloader/total.svg)](https://github.com/sndnvaps/ebookdownloader/releases) @@ -10,38 +10,38 @@ [![godoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/sndnvaps/ebookdownloader/) -# ebookdl 网文下载器,go语言版本 +# ebookdl 网文下载器,go 语言版本 ## 编译版本依赖条件 - 1. go >= 1.16 - 2. gcc 必须要安装,用于编译 github.com/andlabs/ui库 +1. go >= 1.16 +2. gcc 必须要安装,用于编译 github.com/andlabs/ui 库 ## 安装方法 - ```bash - go get github.com/sndnvaps/ebookdownloader/cli - go get github.com/sndnvaps/ebookdownloader/qtgui #此项目暂停更新,备份在backup分支当中 - go get github.com/sndnvaps/ebookdownloader/http-server #此项目暂停更新,备份在backup分支当中 - go get github.com/sndnvaps/ebookdownloader/ui - ``` +```bash +go get github.com/sndnvaps/ebookdownloader/cli +go get github.com/sndnvaps/ebookdownloader/qtgui #此项目暂停更新,备份在backup分支当中 +go get github.com/sndnvaps/ebookdownloader/http-server #此项目暂停更新,备份在backup分支当中 +go get github.com/sndnvaps/ebookdownloader/ui +``` ## 使用方法 - ```bash - .\ebookdownloader.exe --bookid=0_642 --txt #只生成txt文本 - .\ebookdownloader.exe --bookid=0_642 --mobi #只生成mobi电子书 - .\ebookdownloader.exe --bookid=0_642 --txt --mobi #生成txt 和 mobi - .\ebookdownloader.exe --bookid=0_642 --txt --awz3 #生成txt 和 awz3 - .\ebookdownloader.exe --proxy="http://proxyip:proxyport" --bookid=0_642 --mobi #生成mobi电子书,在下载章节的过程中使用 Proxy - .\ebookdownloader.exe --ebhost=xsbiquge.com --bookid=0_642 --txt --mobi #使用xsbiquge.com做为下载源,生成txt 和 mobi - .\ebookdownloader.exe --ebhost=999xs.com --bookid=0_642 --txt --mobi #使用999xs.com做为下载源,生成txt 和 mobi - .\ebookdownloader.exe --ebhost=999xs.com --bookid=0_642 --txt --mobi --meta #使用999xs.com做为下载源,生成txt,mobi电子书,并生成meta.json文件于小说目录当中 - .\ebookdownloader.exe --ebhost=23us.la --bookid=127064 --pv #新功能,用于打印小说的分卷信息,此时不下载小说任何内容 - .\ebookdownloader.exe --bookid=0_0642 --json #生成json格式的小说数据 - .\ebookdownloader.exe conv --json=".\outputs\我是谁-sndnvaps\我是谁-sndnvaps.json" --txt --mobi #新功能,转换json格式到txt,mobi格式 - .\ebookdownloader.exe --help #显示帮助信息 - ``` +```bash +.\ebookdownloader.exe --bookid=0_642 --txt #只生成txt文本 +.\ebookdownloader.exe --bookid=0_642 --mobi #只生成mobi电子书 +.\ebookdownloader.exe --bookid=0_642 --txt --mobi #生成txt 和 mobi +.\ebookdownloader.exe --bookid=0_642 --txt --awz3 #生成txt 和 awz3 +.\ebookdownloader.exe --proxy="http://proxyip:proxyport" --bookid=0_642 --mobi #生成mobi电子书,在下载章节的过程中使用 Proxy +.\ebookdownloader.exe --ebhost=xsbiquge.com --bookid=0_642 --txt --mobi #使用xsbiquge.com做为下载源,生成txt 和 mobi +.\ebookdownloader.exe --ebhost=999xs.com --bookid=0_642 --txt --mobi #使用999xs.com做为下载源,生成txt 和 mobi + .\ebookdownloader.exe --ebhost=999xs.com --bookid=0_642 --txt --mobi --meta #使用999xs.com做为下载源,生成txt,mobi电子书,并生成meta.json文件于小说目录当中 +.\ebookdownloader.exe --ebhost=23us.la --bookid=127064 --pv #新功能,用于打印小说的分卷信息,此时不下载小说任何内容 +.\ebookdownloader.exe --bookid=0_0642 --json #生成json格式的小说数据 +.\ebookdownloader.exe conv --json=".\outputs\我是谁-sndnvaps\我是谁-sndnvaps.json" --txt --mobi #新功能,转换json格式到txt,mobi格式 +.\ebookdownloader.exe --help #显示帮助信息 +``` ## 依赖程序 @@ -59,20 +59,20 @@ gtk-3.0,用于构建ui界面 ## 懒人模式,直接下载编译好的程序 - - 墙里面使用gitee - [gitee ebookdownloader release page](https://gitee.com/sndnvaps/ebookdownloader/releases "https://gitee.com/sndnvaps/ebookdownloader/releases") +墙里面使用 gitee + +[gitee ebookdownloader release page](https://gitee.com/sndnvaps/ebookdownloader/releases "https://gitee.com/sndnvaps/ebookdownloader/releases") -墙外面使用github +墙外面使用 github - [github ebookdownloader release page](https://github.com/sndnvaps/ebookdownloader/releases "https://github.com/sndnvaps/ebookdownloader/releases") +[github ebookdownloader release page](https://github.com/sndnvaps/ebookdownloader/releases "https://github.com/sndnvaps/ebookdownloader/releases") ---------------------- +--- -## 验证下载的文件的完整性(使用gpg签名验证) +## 验证下载的文件的完整性(使用 gpg 签名验证) -下载./scripts/gpg_pub_key.gpg到/home/username/ +下载./scripts/gpg_pub_key.gpg 到/home/username/ 导入公钥到系统中,以用于验证文件的完整性 @@ -80,16 +80,16 @@ $gpg --import gpg_pub_key.gpg ``` -在releases页面下载的文件,将会包含ebookdownloader_$version_$arch.zip,ebookdownloader_$version_$arch.zip.sig - 验证方法 +在 releases 页面下载的文件,将会包含 ebookdownloader*$version*$arch.zip,ebookdownloader_$version\_$arch.zip.sig +验证方法 验证文件完整性 - ```bash - $gpg --verify ebookdownloader_v2.0.0_Win_x86_64.zip.sig ebookdownloader_v2.0.0_Win_x86_64.zip +```bash + $gpg --verify ebookdownloader_v2.0.0_Win_x86_64.zip.sig ebookdownloader_v2.0.0_Win_x86_64.zip ``` - 得到的信息如下 +得到的信息如下 ```bash F:\gowork\src\github.com\sndnvaps\ebookdownloader>gpg --verify ebookdownloader_v @@ -101,41 +101,42 @@ gpg: Good signature from "JimesYang (sndnvaps) " [ultimate] ## ❤️ 赞助 -如果你觉得EbookDownloader项目对你有帮助。你可以给我来一杯啤酒! +如果你觉得 EbookDownloader 项目对你有帮助。你可以给我来一杯啤酒! -| PayPal打赏 | 微信打赏Pay | -| :-: | :-: | -| paypal.me/sndnvaps | Donate_WeChatPay.jpg| +| PayPal 打赏 | 微信打赏 Pay | +| :-----------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------: | +| paypal.me/sndnvaps | Donate_WeChatPay.jpg | -------------- +--- ## 支持的小说网站 - 网站名 | 网址 | 是否支持 | 备注 | - :-: | :-: | :-: | :-: | - 笔趣阁 | | × | 网站改名 | - 笔趣阁 | | × | 网站改名 | - 笔趣阁 | | × | 网站改名 | - 笔趣阁 | | × | 网站改名 | - 笔趣阁 | | × | 网站改名 | - 笔趣阁 | | × | 网站改名 | - 笔趣阁 | | × | 网站改名 | - 笔趣阁 | | √ | - 笔趣阁 | | √ | - 西西文学网 | | √ | - 999小说 | | × | 网站改名 | - 999小说 | | × | 网站改名 | - 999小说 | | × | 网站改名 | - 顶点小说网 | | × | 网站改名 | - 顶点小说网 | | × | 因为网站原因无法打开,暂定无法使用 | - ------------- +| 网站名 | 网址 | 是否支持 | 备注 | +| :--------: | :--------------------------------: | :------: | :--------------------------------: | +| 笔趣阁 | | × | 网站改名 | +| 笔趣阁 | | × | 网站改名 | +| 笔趣阁 | | × | 网站改名 | +| 笔趣阁 | | × | 网站改名 | +| 笔趣阁 | | × | 网站改名 | +| 笔趣阁 | | × | 网站改名 | +| 笔趣阁 | | × | 网站改名 | +| 笔趣阁 | | √ | +| 笔趣阁 | | √ | +| 笔趣阁 | | √ | +| 西西文学网 | | √ | +| 999 小说 | | × | 网站改名 | +| 999 小说 | | × | 网站改名 | +| 999 小说 | | × | 网站改名 | +| 顶点小说网 | | × | 网站改名 | +| 顶点小说网 | | × | 因为网站原因无法打开,暂定无法使用 | + +--- ## 更新日志 - [CHANGELOG](./CHANGELOG "日志文件") +[CHANGELOG](./CHANGELOG "日志文件") - ----------- +--- ## To Do List @@ -156,3 +157,4 @@ gpg: Good signature from "JimesYang (sndnvaps) " [ultimate] [√] 15. 打包需要用到的资源到程序中,减少目录数量,kindlegen程序因为技术和安全性考虑,暂不封装到go程序中 [√] 16. 减少程序运行时的依赖,尝试使用 github.com/andlabs/ui来构建gui界面 [√] 17. 添加 http://www.biqugei.net/ 小说网站支持 + [√] 18. i添加https://www.zhhbq.com/ 小说网站支持 diff --git a/cli/ebookdl_cli.go b/cli/ebookdl_cli.go index 3ea095d..aa89bc4 100644 --- a/cli/ebookdl_cli.go +++ b/cli/ebookdl_cli.go @@ -65,6 +65,9 @@ func EbookDownloader(c *cli.Context) error { } else if ebhost == "xixiwx.net" { xixiwx := ebook.NewXixiwx() EBDLInterface = xixiwx + } else if ebhost == "zhhbq.com" { + zzhbq := ebook.NewZhhbq() + EBDLInterface = zzhbq } else { cli.ShowAppHelpAndExit(c, 0) return nil @@ -229,13 +232,13 @@ func main() { }, } app.Copyright = "© 2019 - 2022 Jimes Yang" - app.Usage = "用于下载 笔趣阁(http://www.biqugse.com/,http://www.biqugei.net) 上面的电子书,并保存为txt格式或者(mobi格式,awz3格式)的电子书" + app.Usage = "用于下载 笔趣阁(http://www.biqugse.com/,http://www.biqugei.net,https://www.zhhbq.com/) 上面的电子书,并保存为txt格式或者(mobi格式,awz3格式)的电子书" app.Action = EbookDownloader app.Flags = []cli.Flag{ cli.StringFlag{ Name: "ebhost", Value: "biqugse.com", - Usage: "定义下载ebook的网站地址(可选择biqugse.com,biqugei.net),西西文学(http://www.xixiwx.net/)", + Usage: "定义下载ebook的网站地址(可选择biqugse.com,biqugei.net,zhhbq.com),西西文学(http://www.xixiwx.net/)", }, cli.StringFlag{ Name: "bookid,id", diff --git a/ebook-sources/zhhbq.go b/ebook-sources/zhhbq.go new file mode 100644 index 0000000..c5b8bae --- /dev/null +++ b/ebook-sources/zhhbq.go @@ -0,0 +1,374 @@ +package ebook + +import ( + "context" + "fmt" + "sync" + + "strings" + + "github.com/Aiicy/htmlquery" + progressbar "github.com/schollz/progressbar/v2" + edl "github.com/sndnvaps/ebookdownloader" +) + +var _ edl.EBookDLInterface = Zhhbq{} + +// Zhhbq https://www.zhhbq.com/ 小说网 +type Zhhbq struct { + URL string + Lock *sync.Mutex +} + +// NewZhhbq 初始化 +func NewZhhbq() Zhhbq { + return Zhhbq{ + URL: "https://www.zhhbq.com/", + Lock: new(sync.Mutex), + } +} + +// GetBookBriefInfo 获取小说的信息 +func (this Zhhbq) GetBookBriefInfo(bookid string, proxy string) edl.BookInfo { + var bi edl.BookInfo + pollURL := this.URL + bookid + "/" + + //当 proxy 不为空的时候,表示设置代理 + if proxy != "" { + doc, err := htmlquery.LoadURLWithProxy(pollURL, proxy) + if err != nil { + fmt.Println(err.Error()) + } + + //获取书名字 + bookNameMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:novel:book_name']") + bookName := htmlquery.SelectAttr(bookNameMeta, "content") + bookName = SanitizeName(bookName) + fmt.Println("书名 = ", bookName) + + //获取书作者 + AuthorMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:novel:author']") + author := htmlquery.SelectAttr(AuthorMeta, "content") + author = SanitizeName(author) + fmt.Println("作者 = ", author) + + //获取书的描述信息 + DescriptionMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:description']") + description := htmlquery.SelectAttr(DescriptionMeta, "content") + fmt.Println("简介 = ", description) + + //获取书的封面下载地址 + CoverURLMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:image']") + CoverURL := htmlquery.SelectAttr(CoverURLMeta, "content") + //fmt.Println("封面下载地址 = ", CoverURL) + + //导入信息 + bi = edl.BookInfo{ + EBHost: this.URL, + EBookID: bookid, + Name: bookName, + Author: author, + Description: description, + CoverURL: CoverURL, + } + } else { //没有设置代理 + doc, err := htmlquery.LoadURL(pollURL) + if err != nil { + fmt.Println(err.Error()) + } + + //获取书名字 + bookNameMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:novel:book_name']") + bookName := htmlquery.SelectAttr(bookNameMeta, "content") + bookName = SanitizeName(bookName) + fmt.Println("书名 = ", bookName) + + //获取书作者 + AuthorMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:novel:author']") + author := htmlquery.SelectAttr(AuthorMeta, "content") + author = SanitizeName(author) + fmt.Println("作者 = ", author) + + //获取书的描述信息 + DescriptionMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:description']") + description := htmlquery.SelectAttr(DescriptionMeta, "content") + fmt.Println("简介 = ", description) + + //获取书的封面下载地址 + CoverURLMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:image']") + CoverURL := htmlquery.SelectAttr(CoverURLMeta, "content") + //fmt.Println("封面下载地址 = ", CoverURL) + + //导入信息 + bi = edl.BookInfo{ + EBHost: this.URL, + EBookID: bookid, + Name: bookName, + Author: author, + Description: description, + CoverURL: CoverURL, + } + } + return bi +} + +// GetBookInfo 获取小说的信息 +func (this Zhhbq) GetBookInfo(ctx context.Context, bookid string, proxy string) edl.BookInfo { + + var bi edl.BookInfo + var chapters []edl.Chapter + pollURL := this.URL + bookid + "/" + + //当 proxy 不为空的时候,表示设置代理 + if proxy != "" { + doc, err := htmlquery.LoadURLWithProxy(pollURL, proxy) + if err != nil { + fmt.Println(err.Error()) + } + + //获取书名字 + bookNameMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:novel:book_name']") + bookName := htmlquery.SelectAttr(bookNameMeta, "content") + bookName = SanitizeName(bookName) + fmt.Println("书名 = ", bookName) + + //获取书作者 + AuthorMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:novel:author']") + author := htmlquery.SelectAttr(AuthorMeta, "content") + author = SanitizeName(author) + fmt.Println("作者 = ", author) + + //获取书的描述信息 + DescriptionMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:description']") + description := htmlquery.SelectAttr(DescriptionMeta, "content") + fmt.Println("简介 = ", description) + + //获取书的封面下载地址 + CoverURLMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:image']") + CoverURL := htmlquery.SelectAttr(CoverURLMeta, "content") + //fmt.Println("封面下载地址 = ", CoverURL) + + //获取书章节列表 + ddNode, _ := htmlquery.Find(doc, "//div[@class='listmain']//dl//dd") + //i := 12,因为最前面的12章是:显示最新章节信息,需要忽略掉 + for i := 12; i < len(ddNode); i++ { + var tmp edl.Chapter + aNode, _ := htmlquery.Find(ddNode[i], "//a") + tmp.Link = this.URL + htmlquery.SelectAttr(aNode[0], "href") + tmp.Title = htmlquery.InnerText(aNode[0]) + chapters = append(chapters, tmp) + } + + //导入信息 + bi = edl.BookInfo{ + EBHost: this.URL, + EBookID: bookid, + Name: bookName, + Author: author, + Description: description, + CoverURL: CoverURL, + Chapters: chapters, + } + } else { //没有设置代理 + doc, err := htmlquery.LoadURL(pollURL) + if err != nil { + fmt.Println(err.Error()) + } + + //获取书名字 + bookNameMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:novel:book_name']") + bookName := htmlquery.SelectAttr(bookNameMeta, "content") + bookName = SanitizeName(bookName) + fmt.Println("书名 = ", bookName) + + //获取书作者 + AuthorMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:novel:author']") + author := htmlquery.SelectAttr(AuthorMeta, "content") + author = SanitizeName(author) + fmt.Println("作者 = ", author) + + //获取书的描述信息 + DescriptionMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:description']") + description := htmlquery.SelectAttr(DescriptionMeta, "content") + fmt.Println("简介 = ", description) + + //获取书的封面下载地址 + CoverURLMeta, _ := htmlquery.FindOne(doc, "//meta[@property='og:image']") + CoverURL := htmlquery.SelectAttr(CoverURLMeta, "content") + //fmt.Println("封面下载地址 = ", CoverURL) + + //获取书章节列表 + ddNode, _ := htmlquery.Find(doc, "//div[@class='listmain']//dl//dd") + //i := 12,因为最前面的12章是:显示最新章节信息,需要忽略掉 + for i := 12; i < len(ddNode); i++ { + var tmp edl.Chapter + aNode, _ := htmlquery.Find(ddNode[i], "//a") + tmp.Link = this.URL + htmlquery.SelectAttr(aNode[0], "href") + tmp.Title = htmlquery.InnerText(aNode[0]) + chapters = append(chapters, tmp) + } + + //导入信息 + bi = edl.BookInfo{ + EBHost: this.URL, + EBookID: bookid, + Name: bookName, + Author: author, + Description: description, + CoverURL: CoverURL, + Chapters: chapters, + } + + } + //生成ISBN码 + bi.GenerateISBN() + //生成UUID + bi.GenerateUUID() + return bi +} + +// DownloadChapters 下载所有章节 +func (this Zhhbq) DownloadChapters(Bi edl.BookInfo, proxy string) edl.BookInfo { + result := Bi //先进行赋值,把数据 + var chapters []edl.Chapter + result.Chapters = chapters //把原来的数据清空 + bis := Bi.Split() + + for index := 0; index < len(bis); index++ { + this.Lock.Lock() + bookinfo := bis[index] + rec := this.downloadChapters(bookinfo, "") + chapters = append(chapters, rec.Chapters...) + //fmt.Printf("Get into this.Lock.Unlock() time: %d\n", index+1) + this.Lock.Unlock() + } + result.Chapters = chapters + + return result +} + +// 根据每个章节的 URL连接,下载每章对应的内容Content当中 +func (this Zhhbq) downloadChapters(Bi edl.BookInfo, proxy string) edl.BookInfo { + chapters := Bi.Chapters + + NumChapter := len(chapters) + tmpChapter := make(chan edl.Chapter, NumChapter) + ResultCh := make(chan chan edl.Chapter, NumChapter) + wg := sync.WaitGroup{} + var c []edl.Chapter + var bar *progressbar.ProgressBar + go AsycChapter(ResultCh, tmpChapter) + for index := 0; index < NumChapter; index++ { + tmp := edl.ProxyChapter{ + Proxy: proxy, + C: chapters[index], + } + this.DownloaderChapter(ResultCh, tmp, &wg) + } + + wg.Wait() + + //下载章节的时候显示进度条 + bar = progressbar.NewOptions( + NumChapter, + progressbar.OptionSetPredictTime(true), + progressbar.OptionShowIts(), + progressbar.OptionShowCount(), + progressbar.OptionSetTheme(progressbar.Theme{Saucer: "#", SaucerPadding: "-", BarStart: ">", BarEnd: "<"}), + ) + + for index := 0; index <= NumChapter; { + select { + case tmp := <-tmpChapter: + //fmt.Printf("tmp.Title = %s\n", tmp.Title) + //fmt.Printf("tmp.Content= %s\n", tmp.Content) + c = append(c, tmp) + index++ + bar.Add(1) + if index == NumChapter { + goto ForEnd + } + } + + } +ForEnd: + + result := edl.BookInfo{ + EBHost: Bi.EBHost, + EBookID: Bi.EBookID, + BookISBN: Bi.ISBN(), + BookUUID: Bi.UUID(), + Name: Bi.Name, + Author: Bi.Author, + Description: Bi.Description, + Volumes: Bi.Volumes, //小说分卷信息在 GetBookInfo()的时候已经下载完成 + HasVolume: Bi.VolumeState(), //小说分卷信息在 GetBookInfo()的时候已经定义 + Chapters: c, + } + + return result +} + +// DownloaderChapter 一个章节一个章节得下载 +func (this Zhhbq) DownloaderChapter(ResultChan chan chan edl.Chapter, pc edl.ProxyChapter, wg *sync.WaitGroup) { + wg.Add(1) + defer wg.Done() + c := make(chan edl.Chapter) + ResultChan <- c + + go func(pc edl.ProxyChapter) { + pollURL := pc.C.Link + proxy := pc.Proxy + var result edl.Chapter + + if proxy != "" { + doc, _ := htmlquery.LoadURLWithProxy(pollURL, proxy) + contentNode, _ := htmlquery.FindOne(doc, "//div[@class='content']/div[@id='content']") + contentText := htmlquery.OutputHTML(contentNode, false) + + //替换两个 html换行 + tmp := strings.Replace(contentText, "

", "\r\n", -1) + //替换一个 html换行 + tmp = strings.Replace(tmp, "
", "\r\n", -1) + //替换一个 html换行 + tmp = strings.Replace(tmp, "
", "\r\n", -1) + + //把 readx(); 替换成 "" + tmp = strings.Replace(tmp, "readx();", "", -1) + //tmp = tmp + "\r\n" + //返回数据,填写Content内容 + result = edl.Chapter{ + Title: pc.C.Title, + Link: pc.C.Link, + Content: tmp, + } + } else { + doc, _ := htmlquery.LoadURL(pollURL) + contentNode, _ := htmlquery.FindOne(doc, "//div[@class='content']/div[@id='content']") + contentText := htmlquery.OutputHTML(contentNode, false) + + //替换两个 html换行 + tmp := strings.Replace(contentText, "

", "\r\n", -1) + //替换一个 html换行 + tmp = strings.Replace(tmp, "
", "\r\n", -1) + //替换一个 html换行 + tmp = strings.Replace(tmp, "
", "\r\n", -1) + //替换一个 html换行 + //</p> ->

+ tmp = strings.Replace(tmp, "</p>", "", -1) + //   -> 代表一个html空格 + tmp = strings.Replace(tmp, "    ", " ", -1) + + //把 readx(); 替换成 "" + tmp = strings.Replace(tmp, "readx();", "", -1) + //tmp = tmp + "\r\n" + //返回数据,填写Content内容 + result = edl.Chapter{ + Title: pc.C.Title, + Link: pc.C.Link, + Content: tmp, + } + } + c <- result + }(pc) +} diff --git a/ebookdl.go b/ebookdl.go index 30c4cd8..bba0283 100644 --- a/ebookdl.go +++ b/ebookdl.go @@ -25,7 +25,7 @@ type BookInfo struct { Author string `json:"author"` //小说作者 Description string `json:"novel_description"` //小说简介 CoverURL string `json:"cover_url"` //小说封面图片地址 - DlCoverFromWeb bool `json:"dl_cover_from_web` //小说封面是否网上下载,或者自动生成 + DlCoverFromWeb bool `json:"dl_cover_from_web"` //小说封面是否网上下载,或者自动生成 IsMobi bool `json:"is_mobi"` //当为true的时候生成mobi IsAzw3 bool `json:"is_azw3"` //当为true的时候生成azw3, HasVolume bool `json:"has_volume"` //是否有小说分卷,默认为false;当设置为true的时候,Volumes里面需要包含分卷信息 diff --git a/ebookdl_test.go b/ebookdl_test.go index 67c1b6c..999e585 100644 --- a/ebookdl_test.go +++ b/ebookdl_test.go @@ -4,7 +4,7 @@ import ( "os" "testing" - "github.com/stretchr/testify/assert" + . "gopkg.in/check.v1" ) var testbi = BookInfo{ @@ -12,7 +12,7 @@ var testbi = BookInfo{ Author: "sndnvaps", Description: "这是我随便写的测试内容简介!", Volumes: V, //分卷信息 - Chapters: C, + Chapters: Chapters, DlCoverFromWeb: false, //使用直接生成的封面 } @@ -33,7 +33,7 @@ var V = []Volume{ NextChapterID: 6, }, } -var C = []Chapter{ +var Chapters = []Chapter{ { Title: "第一章", Content: "这是第一章\r\n内容测试\r\n", @@ -88,63 +88,59 @@ var C = []Chapter{ var savePath = "./outputs/" + testbi.Name + "-" + testbi.Author -func TestBookInfo(t *testing.T) { - bookname := "我是谁" - assert := assert.New(t) +// Hook up gocheck into the "go test" runner. +func Test(t *testing.T) { TestingT(t) } - assert.Equal(bookname, testbi.Name) +type MySuite struct{} - author := "sndnvaps" - assert.Equal(author, testbi.Author) +var _ = Suite(&MySuite{}) + +func (s *MySuite) TestBookInfo(c *C) { - Size := len(testbi.Chapters) - assert.Equal(10, Size) + bookname := "我是谁" + + c.Assert(bookname, Equals, testbi.Name) + author := "sndnvaps" + c.Assert(author, Equals, testbi.Author) + size := len(testbi.Chapters) + c.Assert(size, Equals, 10) link := "https://github.com/sndnvaps/ebookdownloader" - assert.Equal(link, testbi.Chapters[0].Link) + c.Assert(link, Equals, testbi.Chapters[0].Link) } -func TestGenerateTxt(t *testing.T) { - assert := assert.New(t) - +func (s *MySuite) TestGenerateTxt(c *C) { testbi.ChangeVolumeState(true /* hasVolume */) testbi.GenerateTxt() savename := savePath + "/" + testbi.Name + "-" + testbi.Author + ".txt" - assert.True(isExist(savename)) + c.Assert(isExist(savename), Equals, true) os.RemoveAll(savePath) - } -func TestGenerateMobi(t *testing.T) { - assert := assert.New(t) - +func (s *MySuite) TestGenerateMobi(c *C) { testbi.ChangeVolumeState(true /* hasVolume */) testbi.SetKindleEbookType(true /* isMobi */, false /* isAwz3 */) testbi.GenerateISBN() //先生成ISBN码 testbi.GenerateMobi() savename := savePath + "/" + testbi.Name + "-" + testbi.Author + ".mobi" - assert.True(isExist(savename)) + c.Assert(isExist(savename), Equals, true) //os.RemoveAll(savePath) } -func TestGenerateAzw3(t *testing.T) { - assert := assert.New(t) - +func (s *MySuite) TestGenerateAzw3(c *C) { testbi.ChangeVolumeState(true /* hasVolume */) testbi.SetKindleEbookType(false /* isMobi */, true /* isAzw3 */) testbi.GenerateISBN() //先生成ISBN码 testbi.GenerateMobi() savename := savePath + "/" + testbi.Name + "-" + testbi.Author + ".azw3" - assert.True(isExist(savename)) + c.Assert(isExist(savename), Equals, true) os.RemoveAll(savePath) } -func TestGenerateEPUB(t *testing.T) { - assert := assert.New(t) - +func (s *MySuite) TestGenerateEPUB(c *C) { testbi.GenerateISBN() //先生成ISBN码 testbi.GenerateEPUB() savename := savePath + "/" + testbi.Name + "-" + testbi.Author + ".epub" - assert.True(isExist(savename)) + c.Assert(isExist(savename), Equals, true) os.RemoveAll(savePath) } diff --git a/go.mod b/go.mod index 56f6ee6..009f559 100644 --- a/go.mod +++ b/go.mod @@ -14,8 +14,8 @@ require ( github.com/satori/go.uuid v1.2.0 github.com/schollz/progressbar/v2 v2.15.0 github.com/sndnvaps/go-epub v1.0.0 - github.com/stretchr/testify v1.6.1 github.com/unknwon/com v1.0.1 + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/urfave/cli.v1 v1.20.0 ) @@ -23,20 +23,18 @@ require ( github.com/antchfx/xpath v1.1.4 // indirect github.com/bmaupin/go-epub v0.10.0 // indirect github.com/chromedp/sysutil v1.0.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/gobwas/httphead v0.0.0-20200921212729-da3d93bc3c58 // indirect github.com/gobwas/pool v0.2.1 // indirect github.com/gobwas/ws v1.0.4 // indirect github.com/gofrs/uuid v3.1.0+incompatible // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.2.1 // indirect + github.com/kr/text v0.1.0 // indirect github.com/mailru/easyjson v0.7.6 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.8.0 // indirect golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect golang.org/x/net v0.0.0-20210505024714-0287a6fb4125 // indirect golang.org/x/sys v0.0.0-20210903071746-97244b99971b // indirect golang.org/x/text v0.3.6 // indirect - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) diff --git a/go.sum b/go.sum index fb46efa..eb76214 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -66,9 +66,11 @@ github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:X github.com/sndnvaps/go-epub v1.0.0 h1:1bT2UrzVroS8SWAJYH2wm2rWLw++BS9Jra11yFsmhRM= github.com/sndnvaps/go-epub v1.0.0/go.mod h1:U1EGU1aKY4EUtMyBL77P5UFcvdoKQEQ7F1yO+h7hJnE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs= github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= github.com/vincent-petithory/dataurl v0.0.0-20191104211930-d1553a71de50 h1:uxE3GYdXIOfhMv3unJKETJEhw78gvzuQqRX/rVirc2A= @@ -88,9 +90,10 @@ golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/ui/form.go b/ui/form.go index 1470ed4..8a99df8 100644 --- a/ui/form.go +++ b/ui/form.go @@ -89,6 +89,7 @@ func makeHomeWindow() ui.Control { fictionWebsiteCombox.Append("biqugei.net") fictionWebsiteCombox.Append("biqugse.com") fictionWebsiteCombox.Append("xixiwx.net") + fictionWebsiteCombox.Append("zhhbq.com") fictionWebsiteCombox.SetSelected(0) //设置默认选择为 biqugei.net fictionWebsiteLabel := ui.NewLabel("请选择要用到的下载源") @@ -136,6 +137,9 @@ func makeHomeWindow() ui.Control { case 2: xixiwx := ebook.NewXixiwx() EBDLInterface = xixiwx //实例化接口 + case 3: + zhhbq := ebook.NewZhhbq() + EBDLInterface = zhhbq //实例化接口 } bookinfo = EBDLInterface.GetBookInfo(ctx, bookid, proxy)