浏览代码

修复 zimuku 的问题

Signed-off-by: allan716 <[email protected]>
allan716 3 年之前
父节点
当前提交
1d6b1998fd

+ 2 - 0
.gitignore

@@ -80,3 +80,5 @@ TestData/
 /internal/pkg/hot_fix/ChineseSubFinder-Cache.db
 /internal/pkg/sub_formatter/ChineseSubFinder-Cache.db
 /opendebuglog
+/internal/logic/sub_supplier/subhd/cache
+/internal/logic/sub_supplier/zimuku/cache

+ 2 - 5
internal/common/urls.go

@@ -4,12 +4,9 @@ const (
 	SubXunLeiRootUrl  = "http://sub.xmp.sandai.net:8000/subxl/%s.json"
 	SubShooterRootUrl = "https://www.shooter.cn/api/subapi.php"
 
-	SubZiMuKuRootUrl   = "https://zmk.pw"
-	SubZiMuKuSearchUrl = SubZiMuKuRootUrl + "/search"
+	SubZiMuKuRootUrl         = "https://zimuku.org"
+	SubZiMuKuSearchFormatUrl = SubZiMuKuRootUrl + "/search?q=%s"
 
 	SubSubHDRootUrl   = "https://subhd.tv"
 	SubSubHDSearchUrl = SubSubHDRootUrl + "/search/%s"
-
-	TVDBRootUrl   = "https://thetvdb.com"
-	TVDBSearchUrl = TVDBRootUrl + "/search"
 )

+ 3 - 25
internal/logic/sub_supplier/subhd/subhd.go

@@ -20,7 +20,6 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/types/series"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/supplier"
 	"github.com/go-rod/rod"
-	"github.com/go-rod/rod/lib/launcher"
 	"github.com/huandu/go-clone"
 	"github.com/nfnt/resize"
 	"github.com/sirupsen/logrus"
@@ -38,7 +37,6 @@ type Supplier struct {
 	settings         settings.Settings
 	log              *logrus.Logger
 	topic            int
-	rodLauncher      *launcher.Launcher
 	tt               time.Duration
 	debugMode        bool
 	httpProxyAddress string
@@ -331,7 +329,7 @@ func (s Supplier) step0(browser *rod.Browser, keyword string) (string, error) {
 		}
 	}()
 
-	result, page, err := s.httpGetFromBrowser(browser, fmt.Sprintf(common.SubSubHDSearchUrl, url.QueryEscape(keyword)))
+	result, page, err := rod_helper.HttpGetFromBrowser(browser, fmt.Sprintf(common.SubSubHDSearchUrl, url.QueryEscape(keyword)), s.tt)
 	if err != nil {
 		return "", err
 	}
@@ -400,7 +398,7 @@ func (s Supplier) step1(browser *rod.Browser, detailPageUrl string, isMovieOrSer
 		}
 	}()
 	detailPageUrl = my_util.AddBaseUrl(common.SubSubHDRootUrl, detailPageUrl)
-	result, page, err := s.httpGetFromBrowser(browser, detailPageUrl)
+	result, page, err := rod_helper.HttpGetFromBrowser(browser, detailPageUrl, s.tt)
 	if err != nil {
 		return nil, err
 	}
@@ -471,7 +469,7 @@ func (s Supplier) step2Ex(browser *rod.Browser, subDownloadPageUrl string) (bool
 	}()
 	subDownloadPageUrl = my_util.AddBaseUrl(common.SubSubHDRootUrl, subDownloadPageUrl)
 
-	_, page, err := s.httpGetFromBrowser(browser, subDownloadPageUrl)
+	_, page, err := rod_helper.HttpGetFromBrowser(browser, subDownloadPageUrl, s.tt)
 	if err != nil {
 		return false, nil, err
 	}
@@ -687,26 +685,6 @@ search:
 	}
 }
 
-func (s Supplier) httpGetFromBrowser(browser *rod.Browser, inputUrl string) (string, *rod.Page, error) {
-
-	page, err := rod_helper.NewPageNavigate(browser, inputUrl, s.tt, 5)
-	if err != nil {
-		return "", nil, err
-	}
-	pageString, err := page.HTML()
-	if err != nil {
-		return "", nil, err
-	}
-	// 每次搜索间隔
-	if s.debugMode == true {
-		time.Sleep(my_util.RandomSecondDuration(5, 10))
-	} else {
-		time.Sleep(my_util.RandomSecondDuration(5, 20))
-	}
-
-	return pageString, page, nil
-}
-
 type HdListItem struct {
 	Url        string `json:"url"`
 	BaseUrl    string `json:"baseUrl"`

+ 145 - 68
internal/logic/sub_supplier/zimuku/zimuku.go

@@ -7,29 +7,37 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/common"
 	pkgcommon "github.com/allanpk716/ChineseSubFinder/internal/pkg/common"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/decode"
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/global_value"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/language"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/my_util"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/notify_center"
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/rod_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/settings"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_parser_hub"
-	"github.com/allanpk716/ChineseSubFinder/internal/pkg/url_connectedness_helper"
 	language2 "github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/series"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/supplier"
+	"github.com/go-rod/rod"
 	"github.com/huandu/go-clone"
 	"github.com/sirupsen/logrus"
+	"net/url"
+	"os"
 	"path/filepath"
 	"regexp"
 	"sort"
 	"strings"
+	"time"
 )
 
 type Supplier struct {
-	settings settings.Settings
-	log      *logrus.Logger
-	topic    int
-	isAlive  bool
+	settings         settings.Settings
+	log              *logrus.Logger
+	tt               time.Duration
+	debugMode        bool
+	httpProxyAddress string
+	topic            int
+	isAlive          bool
 }
 
 func NewSupplier(_settings settings.Settings) *Supplier {
@@ -43,25 +51,43 @@ func NewSupplier(_settings settings.Settings) *Supplier {
 	if sup.settings.AdvancedSettings.Topic > 0 && sup.settings.AdvancedSettings.Topic != sup.topic {
 		sup.topic = sup.settings.AdvancedSettings.Topic
 	}
+
+	// 默认超时是 2 * 60s,如果是调试模式则是 5 min
+	sup.tt = common.HTMLTimeOut
+	sup.debugMode = sup.settings.AdvancedSettings.DebugMode
+	if sup.debugMode == true {
+		sup.tt = common.OneMovieProcessTimeOut
+	}
+	// 判断是否启用代理
+	if sup.settings.AdvancedSettings.ProxySettings.UseHttpProxy == true {
+		sup.httpProxyAddress = sup.settings.AdvancedSettings.ProxySettings.HttpProxyAddress
+	} else {
+		sup.httpProxyAddress = ""
+	}
+
 	return &sup
 }
 
 func (s *Supplier) CheckAlive() (bool, int64) {
 
-	proxyStatus, proxySpeed, err := url_connectedness_helper.UrlConnectednessTest(common.SubZiMuKuRootUrl, s.settings.AdvancedSettings.ProxySettings.HttpProxyAddress)
+	// TODO 是用本地的 Browser 还是远程的,推荐是远程的
+	browser, err := rod_helper.NewBrowser(s.httpProxyAddress, true, common.SubZiMuKuRootUrl)
 	if err != nil {
-		s.log.Errorln(s.GetSupplierName(), "CheckAlive", "Error", err)
-		s.isAlive = false
 		return false, 0
 	}
-	if proxyStatus == false {
-		s.log.Errorln(s.GetSupplierName(), "CheckAlive", "Status != 200")
-		s.isAlive = false
-		return false, proxySpeed
-	}
+	defer func() {
+		_ = browser.Close()
+	}()
 
+	begin := time.Now() //判断代理访问时间
+	_, page, err := rod_helper.HttpGetFromBrowser(browser, common.SubZiMuKuRootUrl, 15*time.Second)
+	if err != nil {
+		return false, 0
+	}
+	_ = page.Close()
+	speed := time.Now().Sub(begin).Nanoseconds() / 1000 / 1000 //ms
 	s.isAlive = true
-	return true, proxySpeed
+	return true, speed
 }
 
 func (s *Supplier) IsAlive() bool {
@@ -73,7 +99,17 @@ func (s Supplier) GetSupplierName() string {
 }
 
 func (s Supplier) GetSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
-	return s.getSubListFromMovie(filePath)
+
+	// TODO 是用本地的 Browser 还是远程的,推荐是远程的
+	browser, err := rod_helper.NewBrowser(s.httpProxyAddress, true, common.SubZiMuKuRootUrl)
+	if err != nil {
+		return nil, err
+	}
+	defer func() {
+		_ = browser.Close()
+	}()
+
+	return s.getSubListFromMovie(browser, filePath)
 }
 
 func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
@@ -85,6 +121,14 @@ func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]su
 	s.log.Debugln(s.GetSupplierName(), seriesInfo.Name, "Start...")
 
 	var err error
+	// TODO 是用本地的 Browser 还是远程的,推荐是远程的
+	browser, err := rod_helper.NewBrowser(s.httpProxyAddress, true, common.SubZiMuKuRootUrl)
+	if err != nil {
+		return nil, err
+	}
+	defer func() {
+		_ = browser.Close()
+	}()
 	/*
 		去网站搜索的时候,有个比较由意思的逻辑,有些剧集,哪怕只有一季,sonarr 也会给它命名为 Season 1
 		但是在 zimuku 搜索的时候,如果你加上 XXX 第一季 就搜索不出来,那么目前比较可行的办法是查询两次
@@ -98,7 +142,7 @@ func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]su
 		// 第一级界面,找到影片的详情界面
 		keyword := seriesInfo.Name + " 第" + zh.Uint64(value).String() + "季"
 		s.log.Debugln(s.GetSupplierName(), "step 0", "0 times", "keyword:", keyword)
-		filmDetailPageUrl, err := s.step0(keyword)
+		filmDetailPageUrl, err := s.step0(browser, keyword)
 		if err != nil {
 			s.log.Errorln(s.GetSupplierName(), "step 0", "0 times", "keyword:", keyword, err)
 			// 如果只是搜索不到,则继续换关键词
@@ -108,7 +152,7 @@ func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]su
 			}
 			keyword = seriesInfo.Name
 			s.log.Debugln(s.GetSupplierName(), "step 0", "1 times", "keyword:", keyword)
-			filmDetailPageUrl, err = s.step0(keyword)
+			filmDetailPageUrl, err = s.step0(browser, keyword)
 			if err != nil {
 				s.log.Errorln(s.GetSupplierName(), "1 times", "keyword:", keyword, err)
 				continue
@@ -116,7 +160,7 @@ func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]su
 		}
 		// 第二级界面,有多少个字幕
 		s.log.Debugln(s.GetSupplierName(), "step 1", filmDetailPageUrl)
-		subResult, err := s.step1(filmDetailPageUrl)
+		subResult, err := s.step1(browser, filmDetailPageUrl)
 		if err != nil {
 			s.log.Errorln(s.GetSupplierName(), "step 1", filmDetailPageUrl, err)
 			continue
@@ -133,7 +177,7 @@ func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]su
 	// 找到那些 Eps 需要下载字幕的
 	subInfoNeedDownload := s.whichEpisodeNeedDownloadSub(seriesInfo, AllSeasonSubResult)
 	// 剩下的部分跟 GetSubListFroKeyword 一样,就是去下载了
-	outSubInfoList := s.whichSubInfoNeedDownload(subInfoNeedDownload, err)
+	outSubInfoList := s.whichSubInfoNeedDownload(browser, subInfoNeedDownload, err)
 
 	// 返回前,需要把每一个 Eps 的 Season Episode 信息填充到每个 SubInfo 中
 	return outSubInfoList, nil
@@ -143,7 +187,7 @@ func (s Supplier) GetSubListFromFile4Anime(seriesInfo *series.SeriesInfo) ([]sup
 	panic("not implemented")
 }
 
-func (s Supplier) getSubListFromMovie(fileFPath string) ([]supplier.SubInfo, error) {
+func (s Supplier) getSubListFromMovie(browser *rod.Browser, fileFPath string) ([]supplier.SubInfo, error) {
 
 	defer func() {
 		s.log.Debugln(s.GetSupplierName(), fileFPath, "End...")
@@ -181,7 +225,7 @@ func (s Supplier) getSubListFromMovie(fileFPath string) ([]supplier.SubInfo, err
 	if imdbInfo.ImdbId != "" {
 		// 先用 imdb id 找
 		s.log.Debugln(s.GetSupplierName(), fileFPath, "getSubListFromKeyword -> Search By IMDB ID:", imdbInfo.ImdbId)
-		subInfoList, err = s.getSubListFromKeyword(imdbInfo.ImdbId)
+		subInfoList, err = s.getSubListFromKeyword(browser, imdbInfo.ImdbId)
 		if err != nil {
 			// 允许的错误,跳过,继续进行文件名的搜索
 			s.log.Errorln(s.GetSupplierName(), "keyword:", imdbInfo.ImdbId)
@@ -199,7 +243,7 @@ func (s Supplier) getSubListFromMovie(fileFPath string) ([]supplier.SubInfo, err
 
 	s.log.Debugln(s.GetSupplierName(), fileFPath, "VideoNameSearchKeywordMaker Keyword:", searchKeyword)
 
-	subInfoList, err = s.getSubListFromKeyword(searchKeyword)
+	subInfoList, err = s.getSubListFromKeyword(browser, searchKeyword)
 	if err != nil {
 		s.log.Errorln(s.GetSupplierName(), "keyword:", searchKeyword)
 		return nil, err
@@ -209,17 +253,17 @@ func (s Supplier) getSubListFromMovie(fileFPath string) ([]supplier.SubInfo, err
 	return subInfoList, nil
 }
 
-func (s Supplier) getSubListFromKeyword(keyword string) ([]supplier.SubInfo, error) {
+func (s Supplier) getSubListFromKeyword(browser *rod.Browser, keyword string) ([]supplier.SubInfo, error) {
 
 	var outSubInfoList []supplier.SubInfo
 	// 第一级界面,找到影片的详情界面
-	filmDetailPageUrl, err := s.step0(keyword)
+	filmDetailPageUrl, err := s.step0(browser, keyword)
 	if err != nil {
 		return nil, err
 	}
 	s.log.Debugln(s.GetSupplierName(), "getSubListFromKeyword -> step0 -> filmDetailPageUrl:", filmDetailPageUrl)
 	// 第二级界面,有多少个字幕
-	subResult, err := s.step1(filmDetailPageUrl)
+	subResult, err := s.step1(browser, filmDetailPageUrl)
 	if err != nil {
 		return nil, err
 	}
@@ -236,7 +280,7 @@ func (s Supplier) getSubListFromKeyword(keyword string) ([]supplier.SubInfo, err
 		s.log.Debugln(s.GetSupplierName(), "getSubListFromKeyword -> step1 -> info.DownloadTimes:", i, info.DownloadTimes)
 	}
 
-	outSubInfoList = s.whichSubInfoNeedDownload(subResult.SubInfos, err)
+	outSubInfoList = s.whichSubInfoNeedDownload(browser, subResult.SubInfos, err)
 
 	return outSubInfoList, nil
 }
@@ -296,7 +340,7 @@ func (s Supplier) whichEpisodeNeedDownloadSub(seriesInfo *series.SeriesInfo, All
 	return subInfoNeedDownload
 }
 
-func (s Supplier) whichSubInfoNeedDownload(subInfos SubInfos, err error) []supplier.SubInfo {
+func (s Supplier) whichSubInfoNeedDownload(browser *rod.Browser, subInfos SubInfos, err error) []supplier.SubInfo {
 
 	var outSubInfoList = make([]supplier.SubInfo, 0)
 	for i := range subInfos {
@@ -304,7 +348,7 @@ func (s Supplier) whichSubInfoNeedDownload(subInfos SubInfos, err error) []suppl
 		pkgcommon.SetSubScanJobStatusScanSeriesSub(i+1, len(subInfos),
 			fmt.Sprintf("%v - S%v-E%v", subInfos[i].Name, subInfos[i].Season, subInfos[i].Episode))
 
-		err = s.step2(&subInfos[i])
+		err = s.step2(browser, &subInfos[i])
 		if err != nil {
 			s.log.Error(s.GetSupplierName(), "step 2", subInfos[i].Name, err)
 			continue
@@ -347,7 +391,7 @@ func (s Supplier) whichSubInfoNeedDownload(subInfos SubInfos, err error) []suppl
 	// 第四级界面,具体字幕下载
 	for i, subInfo := range tmpSubInfo {
 		s.log.Debugln(s.GetSupplierName(), "step3 -> subInfo.SubDownloadPageUrl:", i, subInfo.SubDownloadPageUrl)
-		fileName, data, err := s.step3(subInfo.SubDownloadPageUrl)
+		fileName, data, err := s.step3(browser, subInfo.SubDownloadPageUrl)
 		if err != nil {
 			s.log.Error(s.GetSupplierName(), "step 3", err)
 			continue
@@ -371,26 +415,25 @@ func (s Supplier) whichSubInfoNeedDownload(subInfos SubInfos, err error) []suppl
 }
 
 // step0 先在查询界面找到字幕对应第一个影片的详情界面,需要解决自定义错误 ZiMuKuSearchKeyWordStep0DetailPageUrlNotFound
-func (s Supplier) step0(keyword string) (string, error) {
+func (s Supplier) step0(browser *rod.Browser, keyword string) (string, error) {
 	var err error
 	defer func() {
 		if err != nil {
 			notify_center.Notify.Add("zimuku_step0", err.Error())
 		}
 	}()
-	httpClient := my_util.NewHttpClient(*s.settings.AdvancedSettings.ProxySettings)
-	// 第一级界面,有多少个字幕
-	resp, err := httpClient.R().
-		SetQueryParams(map[string]string{
-			"q": keyword,
-		}).
-		Get(common.SubZiMuKuSearchUrl)
+
+	desUrl := fmt.Sprintf(common.SubZiMuKuSearchFormatUrl, url.QueryEscape(keyword))
+	result, page, err := rod_helper.HttpGetFromBrowser(browser, desUrl, s.tt)
 	if err != nil {
 		return "", err
 	}
+	defer func() {
+		_ = page.Close()
+	}()
 	// 找到对应影片的详情界面
 	re := regexp.MustCompile(`<p\s+class="tt\s+clearfix"><a\s+href="(/subs/[\w]+\.html)"\s+target="_blank"><b>(.*?)</b></a></p>`)
-	matched := re.FindAllStringSubmatch(resp.String(), -1)
+	matched := re.FindAllStringSubmatch(result, -1)
 	if matched == nil || len(matched) < 1 {
 		return "", common.ZiMuKuSearchKeyWordStep0DetailPageUrlNotFound
 	}
@@ -400,26 +443,30 @@ func (s Supplier) step0(keyword string) (string, error) {
 }
 
 // step1 分析详情界面,找到有多少个字幕
-func (s Supplier) step1(filmDetailPageUrl string) (SubResult, error) {
+func (s Supplier) step1(browser *rod.Browser, filmDetailPageUrl string) (SubResult, error) {
 	var err error
 	defer func() {
 		if err != nil {
 			notify_center.Notify.Add("zimuku_step1", err.Error())
 		}
 	}()
+
+	var subResult SubResult
+	subResult.SubInfos = SubInfos{}
+
 	filmDetailPageUrl = my_util.AddBaseUrl(common.SubZiMuKuRootUrl, filmDetailPageUrl)
-	httpClient := my_util.NewHttpClient(*s.settings.AdvancedSettings.ProxySettings)
-	resp, err := httpClient.R().
-		Get(filmDetailPageUrl)
+
+	result, page, err := rod_helper.HttpGetFromBrowser(browser, filmDetailPageUrl, s.tt)
 	if err != nil {
-		return SubResult{}, err
+		return subResult, err
 	}
-	doc, err := goquery.NewDocumentFromReader(strings.NewReader(resp.String()))
+	defer func() {
+		_ = page.Close()
+	}()
+	doc, err := goquery.NewDocumentFromReader(strings.NewReader(result))
 	if err != nil {
 		return SubResult{}, err
 	}
-	var subResult SubResult
-	subResult.SubInfos = SubInfos{}
 
 	counterIndex := 3
 	// 先找到页面”下载“关键词是第几列,然后下面的下载量才能正确的解析。否则,电影是[3],而在剧集中,因为多了字幕组的筛选,则为[4]
@@ -458,7 +505,7 @@ func (s Supplier) step1(filmDetailPageUrl string) (SubResult, error) {
 			lang = ""
 		}
 		// 投票
-		rate, exists := tr.Find(".rating-star").First().Attr("title")
+		rate, exists := tr.Find(".rating-star").First().Attr("data-original-title")
 		if !exists {
 			rate = ""
 		}
@@ -501,7 +548,7 @@ func (s Supplier) step1(filmDetailPageUrl string) (SubResult, error) {
 }
 
 // step2 第二级界面,单个字幕详情,需要判断 ZiMuKuDownloadUrlStep2NotFound 这个自定义错误
-func (s Supplier) step2(subInfo *SubInfo) error {
+func (s Supplier) step2(browser *rod.Browser, subInfo *SubInfo) error {
 	var err error
 	defer func() {
 		if err != nil {
@@ -509,15 +556,16 @@ func (s Supplier) step2(subInfo *SubInfo) error {
 		}
 	}()
 	detailUrl := my_util.AddBaseUrl(common.SubZiMuKuRootUrl, subInfo.DetailUrl)
-	httpClient := my_util.NewHttpClient(*s.settings.AdvancedSettings.ProxySettings)
-	resp, err := httpClient.R().
-		Get(detailUrl)
+	result, page, err := rod_helper.HttpGetFromBrowser(browser, detailUrl, s.tt)
 	if err != nil {
 		return err
 	}
+	defer func() {
+		_ = page.Close()
+	}()
 	// 找到下载地址
 	re := regexp.MustCompile(`<a\s+id="down1"\s+href="([^"]*/dld/[\w]+\.html)"`)
-	matched := re.FindAllStringSubmatch(resp.String(), -1)
+	matched := re.FindAllStringSubmatch(result, -1)
 	if matched == nil || len(matched) == 0 || len(matched[0]) == 0 {
 		s.log.Warnln("Step2,sub download url not found", detailUrl)
 		return common.ZiMuKuDownloadUrlStep2NotFound
@@ -531,7 +579,7 @@ func (s Supplier) step2(subInfo *SubInfo) error {
 }
 
 // step3 第三级界面,具体字幕下载 ZiMuKuDownloadUrlStep3NotFound ZiMuKuDownloadUrlStep3AllFailed
-func (s Supplier) step3(subDownloadPageUrl string) (string, []byte, error) {
+func (s Supplier) step3(browser *rod.Browser, subDownloadPageUrl string) (string, []byte, error) {
 	var err error
 	defer func() {
 		if err != nil {
@@ -539,33 +587,60 @@ func (s Supplier) step3(subDownloadPageUrl string) (string, []byte, error) {
 		}
 	}()
 	subDownloadPageUrl = my_util.AddBaseUrl(common.SubZiMuKuRootUrl, subDownloadPageUrl)
-	httpClient := my_util.NewHttpClient(*s.settings.AdvancedSettings.ProxySettings)
-	resp, err := httpClient.R().
-		Get(subDownloadPageUrl)
+	result, page, err := rod_helper.HttpGetFromBrowser(browser, subDownloadPageUrl, s.tt)
 	if err != nil {
 		return "", nil, err
 	}
+	defer func() {
+		_ = page.Close()
+	}()
 	re := regexp.MustCompile(`<li><a\s+rel="nofollow"\s+href="([^"]*/download/[^"]+)"`)
-	matched := re.FindAllStringSubmatch(resp.String(), -1)
+	matched := re.FindAllStringSubmatch(result, -1)
 	if matched == nil || len(matched) == 0 || len(matched[0]) == 0 {
 		s.log.Debugln("Step3,sub download url not found", subDownloadPageUrl)
 		return "", nil, common.ZiMuKuDownloadUrlStep3NotFound
 	}
-	var filename string
-	var data []byte
 
-	s.settings.AdvancedSettings.ProxySettings.Referer = subDownloadPageUrl
-	for i := 0; i < len(matched); i++ {
-		data, filename, err = my_util.DownFile(my_util.AddBaseUrl(common.SubZiMuKuRootUrl, matched[i][1]), *s.settings.AdvancedSettings.ProxySettings)
+	fileName := ""
+	fileByte := []byte{0}
+	downloadSuccess := false
+	err = rod.Try(func() {
+		tmpDir := filepath.Join(global_value.DefTmpFolder, "downloads")
+		wait := browser.WaitDownload(tmpDir)
+		getDownloadFile := func() ([]byte, string, error) {
+			info := wait()
+			downloadPath := filepath.Join(tmpDir, info.GUID)
+			defer func() { _ = os.Remove(downloadPath) }()
+			b, err := os.ReadFile(downloadPath)
+			if err != nil {
+				return nil, "", err
+			}
+			return b, info.SuggestedFilename, nil
+		}
+		// 初始化页面用于查询元素
+		element := page.MustElement(btnClickDownload)
+		// 直接可以下载
+		element.MustClick()
+		time.Sleep(time.Second * 2)
+		fileByte, fileName, err = getDownloadFile()
 		if err != nil {
-			s.log.Errorln("ZiMuKu step3 DownloadFile", err)
-			continue
+			return
 		}
-		s.log.Debugln("Step3,DownFile, FileName:", filename, "DataLen:", len(data))
-		return filename, data, nil
+
+		downloadSuccess = true
+	})
+	if err != nil {
+		s.log.Errorln("ZiMuKu step3 DownloadFile", err)
+		return "", nil, err
+	}
+
+	if downloadSuccess == true {
+		s.log.Debugln("Step3,DownFile, FileName:", fileName, "DataLen:", len(fileByte))
+		return fileName, fileByte, nil
+	} else {
+		s.log.Debugln("Step3,sub download url not found", subDownloadPageUrl)
+		return "", nil, common.ZiMuKuDownloadUrlStep3AllFailed
 	}
-	s.log.Debugln("Step3,sub download url not found", subDownloadPageUrl)
-	return "", nil, common.ZiMuKuDownloadUrlStep3AllFailed
 }
 
 type SubResult struct {
@@ -606,3 +681,5 @@ type SortByPriority struct{ SubInfos }
 func (s SortByPriority) Less(i, j int) bool {
 	return s.SubInfos[i].Priority > s.SubInfos[j].Priority
 }
+
+const btnClickDownload = "a.btn-danger"

+ 41 - 10
internal/logic/sub_supplier/zimuku/zimuku_test.go

@@ -1,7 +1,9 @@
 package zimuku
 
 import (
-	series_helper2 "github.com/allanpk716/ChineseSubFinder/internal/logic/series_helper"
+	"github.com/allanpk716/ChineseSubFinder/internal/common"
+	"github.com/allanpk716/ChineseSubFinder/internal/logic/series_helper"
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/rod_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/settings"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/unit_test_helper"
 	"path/filepath"
@@ -10,10 +12,18 @@ import (
 
 func TestSupplier_GetSubListFromKeyword(t *testing.T) {
 
+	browser, err := rod_helper.NewBrowser("", true, common.SubZiMuKuRootUrl)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer func() {
+		_ = browser.Close()
+	}()
+
 	//imdbId1 := "tt3228774"
 	videoName := "黑白魔女库伊拉"
 	s := NewSupplier(*settings.NewSettings())
-	outList, err := s.getSubListFromKeyword(videoName)
+	outList, err := s.getSubListFromKeyword(browser, videoName)
 	if err != nil {
 		t.Error(err)
 	}
@@ -24,6 +34,15 @@ func TestSupplier_GetSubListFromKeyword(t *testing.T) {
 }
 
 func TestSupplier_GetSubListFromFile(t *testing.T) {
+
+	browser, err := rod_helper.NewBrowser("", true, common.SubZiMuKuRootUrl)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer func() {
+		_ = browser.Close()
+	}()
+
 	//movie1 := "X:\\电影\\The Devil All the Time (2020)\\The Devil All the Time (2020) WEBDL-1080p.mkv"
 	//movie1 := "X:\\电影\\龙猫 (1988)\\龙猫 (1988) 1080p DTS.mkv"
 	//movie1 := "X:\\电影\\消失爱人 (2016)\\消失爱人 (2016) 720p AAC.rmvb"
@@ -34,7 +53,7 @@ func TestSupplier_GetSubListFromFile(t *testing.T) {
 	rootDir := unit_test_helper.GetTestDataResourceRootPath([]string{"sub_spplier"}, 5, true)
 	movie1 := filepath.Join(rootDir, "zimuku", "movies", "The Devil All the Time (2020)", "The Devil All the Time (2020) WEBDL-1080p.mkv")
 	s := NewSupplier(*settings.NewSettings())
-	outList, err := s.getSubListFromMovie(movie1)
+	outList, err := s.getSubListFromMovie(browser, movie1)
 	if err != nil {
 		t.Error(err)
 	}
@@ -42,11 +61,6 @@ func TestSupplier_GetSubListFromFile(t *testing.T) {
 	for i, sublist := range outList {
 		println(i, sublist.Name, sublist.Ext, sublist.Language.String(), sublist.Score, len(sublist.Data))
 	}
-
-	alive, _ := s.CheckAlive()
-	if alive == false {
-		t.Fatal("CheckAlive == false")
-	}
 }
 
 func TestSupplier_GetSubListFromFile4Series(t *testing.T) {
@@ -59,7 +73,7 @@ func TestSupplier_GetSubListFromFile4Series(t *testing.T) {
 	rootDir := unit_test_helper.GetTestDataResourceRootPath([]string{"sub_spplier"}, 5, true)
 	ser := filepath.Join(rootDir, "zimuku", "series", "黄石 (2018)")
 	// 读取本地的视频和字幕信息
-	seriesInfo, err := series_helper2.ReadSeriesInfoFromDir(ser, nil, false)
+	seriesInfo, err := series_helper.ReadSeriesInfoFromDir(ser, nil, false)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -83,6 +97,14 @@ func TestSupplier_GetSubListFromFile4Series(t *testing.T) {
 
 func TestSupplier_getSubListFromKeyword(t *testing.T) {
 
+	browser, err := rod_helper.NewBrowser("", true, common.SubZiMuKuRootUrl)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer func() {
+		_ = browser.Close()
+	}()
+
 	//imdbID := "tt12708542" // 星球大战:残次品
 	//imdbID := "tt7016936" // 杀死伊芙
 	//imdbID := "tt2990738" // 恐怖直播
@@ -92,7 +114,7 @@ func TestSupplier_getSubListFromKeyword(t *testing.T) {
 	//imdbID := "tt3626476"  // Vacation Friends (2021)
 	imdbID := "tt11192306" // Superman.and.Lois
 	zimuku := NewSupplier(*settings.NewSettings())
-	subInfos, err := zimuku.getSubListFromKeyword(imdbID)
+	subInfos, err := zimuku.getSubListFromKeyword(browser, imdbID)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -113,3 +135,12 @@ func TestSupplier_step3(t *testing.T) {
 	//println(fileName)
 	//println(len(datas))
 }
+
+func TestSupplier_CheckAlive(t *testing.T) {
+
+	s := NewSupplier(*settings.NewSettings())
+	alive, _ := s.CheckAlive()
+	if alive == false {
+		t.Fatal("CheckAlive == false")
+	}
+}

+ 47 - 1
internal/pkg/rod_helper/rodHelper.go

@@ -24,7 +24,7 @@ import (
  * @return *rod.Browser
  * @return error
  */
-func NewBrowser(httpProxyURL string, loadAdblock bool) (*rod.Browser, error) {
+func NewBrowser(httpProxyURL string, loadAdblock bool, preLoadUrl ...string) (*rod.Browser, error) {
 
 	var err error
 
@@ -64,6 +64,32 @@ func NewBrowser(httpProxyURL string, loadAdblock bool) (*rod.Browser, error) {
 		return nil, err
 	}
 
+	// 如果加载了插件,那么就需要进行一定的耗时操作,等待其第一次的加载完成
+
+	if loadAdblock == true {
+		_, page, err := HttpGetFromBrowser(browser, "https://www.qq.com", 15*time.Second)
+		if err != nil {
+			return nil, err
+		}
+		defer func() {
+			if page != nil {
+				_ = page.Close()
+			}
+		}()
+	}
+
+	if len(preLoadUrl) > 0 {
+		_, page, err := HttpGetFromBrowser(browser, preLoadUrl[0], 15*time.Second)
+		if err != nil {
+			return nil, err
+		}
+		defer func() {
+			if page != nil {
+				_ = page.Close()
+			}
+		}()
+	}
+
 	return browser, nil
 }
 
@@ -122,6 +148,26 @@ func NewPageNavigate(browser *rod.Browser, desURL string, timeOut time.Duration,
 	return nil, err
 }
 
+func HttpGetFromBrowser(browser *rod.Browser, inputUrl string, tt time.Duration, debugMode ...bool) (string, *rod.Page, error) {
+
+	page, err := NewPageNavigate(browser, inputUrl, tt, 2)
+	if err != nil {
+		return "", nil, err
+	}
+	pageString, err := page.HTML()
+	if err != nil {
+		return "", nil, err
+	}
+	// 每次搜索间隔
+	if len(debugMode) > 0 && debugMode[0] == true {
+		time.Sleep(my_util.RandomSecondDuration(5, 20))
+	} else {
+		time.Sleep(my_util.RandomSecondDuration(5, 10))
+	}
+
+	return pageString, page, nil
+}
+
 // ReloadBrowser 提前把浏览器下载好
 func ReloadBrowser() {
 	newBrowser, err := NewBrowser("", true)