@@ -24,18 +24,18 @@ var (
2424
2525 // 从__NEXT_DATA__脚本中提取数据的正则表达式
2626 nextDataRegex = regexp .MustCompile (`<script id="__NEXT_DATA__" type="application/json">(.*?)</script>` )
27-
27+
2828 // 缓存相关变量
29- searchResultCache = sync.Map {}
29+ searchResultCache = sync.Map {}
3030 lastCacheCleanTime = time .Now ()
31- cacheTTL = 1 * time .Hour
31+ cacheTTL = 1 * time .Hour
3232)
3333
3434// 在init函数中注册插件
3535func init () {
3636 // 使用全局超时时间创建插件实例并注册
3737 plugin .RegisterGlobalPlugin (NewPanSearchPlugin ())
38-
38+
3939 // 启动缓存清理goroutine
4040 go startCacheCleaner ()
4141}
@@ -45,7 +45,7 @@ func startCacheCleaner() {
4545 // 每小时清理一次缓存
4646 ticker := time .NewTicker (1 * time .Hour )
4747 defer ticker .Stop ()
48-
48+
4949 for range ticker .C {
5050 // 清空所有缓存
5151 searchResultCache = sync.Map {}
@@ -102,17 +102,18 @@ type PanSearchAsyncPlugin struct {
102102 maxResults int
103103 maxConcurrent int
104104 retries int
105- workerPool * WorkerPool // 添加工作池
106105}
107106
108107// WorkerPool 工作池结构
109108type WorkerPool struct {
110- tasks chan Task
111- results chan TaskResult
112- errors chan error
113- wg sync.WaitGroup
114- closed atomic.Bool // 添加原子标志来标记工作池是否已关闭
115- mu sync.Mutex // 添加互斥锁保护提交操作
109+ tasks chan Task
110+ results chan TaskResult
111+ errors chan error
112+ workerCount int
113+ wg sync.WaitGroup
114+ closed atomic.Bool
115+ mu sync.Mutex
116+ closeOnce sync.Once
116117}
117118
118119// Task 工作任务
@@ -129,17 +130,25 @@ type TaskResult struct {
129130}
130131
131132// NewWorkerPool 创建新的工作池
132- func NewWorkerPool (size int ) * WorkerPool {
133+ func NewWorkerPool (workerCount , bufferSize int ) * WorkerPool {
134+ if workerCount < 1 {
135+ workerCount = 1
136+ }
137+ if bufferSize < workerCount {
138+ bufferSize = workerCount
139+ }
140+
133141 return & WorkerPool {
134- tasks : make (chan Task , size * 3 ), // 增加任务通道容量
135- results : make (chan TaskResult , size * 3 ), // 增加结果通道容量
136- errors : make (chan error , size * 3 ), // 增加错误通道容量
142+ tasks : make (chan Task , bufferSize ),
143+ results : make (chan TaskResult , bufferSize ),
144+ errors : make (chan error , bufferSize ),
145+ workerCount : workerCount ,
137146 }
138147}
139148
140149// Start 启动工作池
141150func (wp * WorkerPool ) Start (ctx context.Context , handler func (ctx context.Context , task Task ) (TaskResult , error )) {
142- for i := 0 ; i < cap ( wp .tasks ) ; i ++ {
151+ for i := 0 ; i < wp .workerCount ; i ++ {
143152 wp .wg .Add (1 )
144153 go func () {
145154 defer wp .wg .Done ()
@@ -154,18 +163,14 @@ func (wp *WorkerPool) Start(ctx context.Context, handler func(ctx context.Contex
154163 if err != nil {
155164 select {
156165 case wp .errors <- err :
157- // 成功发送错误
158- default :
159- // 通道可能已关闭,忽略错误
160- fmt .Printf ("无法发送错误: %v\n " , err )
166+ case <- ctx .Done ():
167+ return
161168 }
162169 } else {
163170 select {
164171 case wp .results <- result :
165- // 成功发送结果
166- default :
167- // 通道可能已关闭,忽略结果
168- fmt .Printf ("无法发送结果\n " )
172+ case <- ctx .Done ():
173+ return
169174 }
170175 }
171176
@@ -182,52 +187,26 @@ func (wp *WorkerPool) Submit(task Task) bool {
182187 wp .mu .Lock ()
183188 defer wp .mu .Unlock ()
184189
185- // 检查工作池是否已关闭
186190 if wp .closed .Load () {
187191 return false
188192 }
189193
190- select {
191- case wp .tasks <- task :
192- return true
193- default :
194- // 如果通道已满,返回失败
195- return false
196- }
194+ wp .tasks <- task
195+ return true
197196}
198197
199198// Close 关闭工作池
200199func (wp * WorkerPool ) Close () {
201- wp .mu . Lock ()
202- if ! wp .closed . Load () {
200+ wp .closeOnce . Do ( func () {
201+ wp .mu . Lock ()
203202 wp .closed .Store (true )
204203 close (wp .tasks )
205- }
206- wp .mu .Unlock ()
204+ wp .mu .Unlock ()
207205
208- wp .wg .Wait ()
209-
210- // 安全关闭结果和错误通道
211- wp .mu .Lock ()
212- defer wp .mu .Unlock ()
213-
214- select {
215- case _ , ok := <- wp .results :
216- if ok {
217- close (wp .results )
218- }
219- default :
206+ wp .wg .Wait ()
220207 close (wp .results )
221- }
222-
223- select {
224- case _ , ok := <- wp .errors :
225- if ok {
226- close (wp .errors )
227- }
228- default :
229208 close (wp .errors )
230- }
209+ })
231210}
232211
233212// NewPanSearchPlugin 创建新的盘搜异步插件
@@ -241,7 +220,6 @@ func NewPanSearchPlugin() *PanSearchAsyncPlugin {
241220 maxResults : MaxResults ,
242221 maxConcurrent : maxConcurrent ,
243222 retries : MaxRetries ,
244- workerPool : NewWorkerPool (maxConcurrent ), // 初始化工作池
245223 }
246224
247225 // 初始化时预热获取 buildId
@@ -548,13 +526,13 @@ func (p *PanSearchAsyncPlugin) doSearch(client *http.Client, keyword string, ext
548526 remainingResults := min (total - PageSize , p .maxResults - PageSize )
549527 if remainingResults <= 0 {
550528 results := p .convertResults (allResults , keyword )
551-
529+
552530 // 缓存结果
553531 searchResultCache .Store (keyword , cachedResponse {
554532 results : results ,
555533 timestamp : time .Now (),
556534 })
557-
535+
558536 return results , nil
559537 }
560538
@@ -564,21 +542,21 @@ func (p *PanSearchAsyncPlugin) doSearch(client *http.Client, keyword string, ext
564542 // 如果只需要获取少量页面,直接返回
565543 if neededPages <= 0 {
566544 results := p .convertResults (allResults , keyword )
567-
545+
568546 // 缓存结果
569547 searchResultCache .Store (keyword , cachedResponse {
570548 results : results ,
571549 timestamp : time .Now (),
572550 })
573-
551+
574552 return results , nil
575553 }
576554
577555 // 根据实际页数确定并发数,但不超过最大并发数
578556 actualConcurrent := min (neededPages , p .maxConcurrent )
579557
580- // 创建适合实际并发数的工作池
581- p . workerPool = NewWorkerPool (actualConcurrent )
558+ // 工作池是单次请求的局部资源,避免并发请求共享状态
559+ pool : = NewWorkerPool (actualConcurrent , neededPages )
582560
583561 // 创建上下文用于管理所有请求
584562 ctx , cancel := context .WithTimeout (context .Background (), p .timeout * 2 )
@@ -588,7 +566,7 @@ func (p *PanSearchAsyncPlugin) doSearch(client *http.Client, keyword string, ext
588566 needRefreshBuildId := & atomic.Bool {}
589567
590568 // 启动工作池
591- p . workerPool .Start (ctx , func (ctx context.Context , task Task ) (TaskResult , error ) {
569+ pool .Start (ctx , func (ctx context.Context , task Task ) (TaskResult , error ) {
592570 var pageResults []PanSearchItem
593571 var err error
594572
@@ -664,15 +642,8 @@ func (p *PanSearchAsyncPlugin) doSearch(client *http.Client, keyword string, ext
664642 // 提交任务计数器
665643 submittedTasks := 0
666644
667- // 简化批次处理逻辑,考虑到最多只有99页需要获取(第一页已经获取)
668- // 使用两个批次:每批次最多50页,避免一次性提交过多任务
669- batchSize := (neededPages + 1 ) / 2 // 将总页数分成两批
670- if batchSize < 1 {
671- batchSize = neededPages // 如果页数很少,就一次性提交所有任务
672- }
673-
674645 // 提交所有任务
675- for i := 0 ; i < neededPages ; i += batchSize {
646+ for i := 0 ; i < neededPages ; i ++ {
676647 // 检查上下文是否已取消
677648 select {
678649 case <- ctx .Done ():
@@ -682,46 +653,26 @@ func (p *PanSearchAsyncPlugin) doSearch(client *http.Client, keyword string, ext
682653 // 继续执行
683654 }
684655
685- end := i + batchSize
686- if end > neededPages {
687- end = neededPages
688- }
689-
690- // 提交一批任务
691- for j := i ; j < end ; j ++ {
692- offset := PageSize + j * PageSize
693- if offset < p .maxResults {
694- task := Task {
695- keyword : keyword ,
696- offset : offset ,
697- baseURL : baseURL ,
698- }
699-
700- // 尝试提交任务,如果失败则跳出循环
701- if ! p .workerPool .Submit (task ) {
702- fmt .Printf ("无法提交任务,工作池可能已关闭\n " )
703- goto CollectResults
704- }
705-
706- submittedTasks ++
656+ offset := PageSize + i * PageSize
657+ if offset < p .maxResults {
658+ task := Task {
659+ keyword : keyword ,
660+ offset : offset ,
661+ baseURL : baseURL ,
707662 }
708- }
709663
710- // 只有在有多个批次且不是最后一批时才等待
711- if batchSize < neededPages && end < neededPages {
712- select {
713- case <- time .After (50 * time .Millisecond ):
714- // 继续执行
715- case <- ctx .Done ():
716- // 上下文已取消,停止提交任务
664+ if ! pool .Submit (task ) {
665+ fmt .Printf ("无法提交任务,工作池可能已关闭\n " )
717666 goto CollectResults
718667 }
668+
669+ submittedTasks ++
719670 }
720671 }
721672
722673CollectResults:
723674 // 关闭任务提交通道
724- go p . workerPool .Close ()
675+ go pool .Close ()
725676
726677 // 收集结果
727678 resultCount := 0
@@ -731,15 +682,15 @@ CollectResults:
731682 // 使用select非阻塞地收集结果和错误
732683 for resultCount + errorCount < submittedTasks {
733684 select {
734- case result , ok := <- p . workerPool .results :
685+ case result , ok := <- pool .results :
735686 if ! ok {
736687 // 结果通道已关闭
737688 goto ProcessResults
738689 }
739690 allResults = append (allResults , result .results ... )
740691 resultCount ++
741692
742- case err , ok := <- p . workerPool .errors :
693+ case err , ok := <- pool .errors :
743694 if ! ok {
744695 // 错误通道已关闭
745696 goto ProcessResults
@@ -750,13 +701,13 @@ CollectResults:
750701 case <- ctx .Done ():
751702 // 上下文超时,返回已收集的结果
752703 results := p .convertResults (allResults , keyword )
753-
704+
754705 // 缓存结果(即使超时也缓存已获取的结果)
755706 searchResultCache .Store (keyword , cachedResponse {
756707 results : results ,
757708 timestamp : time .Now (),
758709 })
759-
710+
760711 return results , fmt .Errorf ("搜索超时: %w" , ctx .Err ())
761712 }
762713 }
@@ -765,20 +716,20 @@ ProcessResults:
765716 // 如果所有请求都失败且没有获得首页以外的结果,则返回错误
766717 if submittedTasks > 0 && errorCount == submittedTasks && len (allResults ) == len (firstPageResults ) {
767718 results := p .convertResults (allResults , keyword )
768-
719+
769720 // 缓存结果(即使有错误也缓存已获取的结果)
770721 searchResultCache .Store (keyword , cachedResponse {
771722 results : results ,
772723 timestamp : time .Now (),
773724 })
774-
725+
775726 return results , fmt .Errorf ("所有后续页面请求失败: %v" , lastError )
776727 }
777728
778729 // 4. 去重和格式化结果
779730 uniqueResults := p .deduplicateItems (allResults )
780731 results := p .convertResults (uniqueResults , keyword )
781-
732+
782733 // 缓存结果
783734 searchResultCache .Store (keyword , cachedResponse {
784735 results : results ,
0 commit comments