searchImpl 实现具体的搜索逻辑
(client *http.Client, keyword string, ext map[string]interface{})
| 138 | |
| 139 | // searchImpl 实现具体的搜索逻辑 |
| 140 | func (p *DuoduoAsyncPlugin) searchImpl(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) { |
| 141 | // 性能统计 |
| 142 | start := time.Now() |
| 143 | atomic.AddInt64(&searchRequests, 1) |
| 144 | defer func() { |
| 145 | duration := time.Since(start).Nanoseconds() |
| 146 | atomic.AddInt64(&totalSearchTime, duration) |
| 147 | }() |
| 148 | |
| 149 | // 使用优化的客户端 |
| 150 | if p.optimizedClient != nil { |
| 151 | client = p.optimizedClient |
| 152 | } |
| 153 | |
| 154 | // 1. 构建搜索URL |
| 155 | searchURL := fmt.Sprintf("https://tv.yydsys.top/index.php/vod/search/wd/%s.html", url.QueryEscape(keyword)) |
| 156 | |
| 157 | // 2. 创建带超时的上下文 |
| 158 | ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout) |
| 159 | defer cancel() |
| 160 | |
| 161 | // 3. 创建请求 |
| 162 | req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil) |
| 163 | if err != nil { |
| 164 | return nil, fmt.Errorf("[%s] 创建请求失败: %w", p.Name(), err) |
| 165 | } |
| 166 | |
| 167 | // 4. 设置完整的请求头(避免反爬虫) |
| 168 | req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36") |
| 169 | req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8") |
| 170 | req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8") |
| 171 | req.Header.Set("Connection", "keep-alive") |
| 172 | req.Header.Set("Upgrade-Insecure-Requests", "1") |
| 173 | req.Header.Set("Cache-Control", "max-age=0") |
| 174 | req.Header.Set("Referer", "https://tv.yydsys.top/") |
| 175 | |
| 176 | // 5. 发送请求(带重试机制) |
| 177 | resp, err := p.doRequestWithRetry(req, client) |
| 178 | if err != nil { |
| 179 | return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err) |
| 180 | } |
| 181 | defer resp.Body.Close() |
| 182 | |
| 183 | if resp.StatusCode != 200 { |
| 184 | return nil, fmt.Errorf("[%s] 搜索请求返回状态码: %d", p.Name(), resp.StatusCode) |
| 185 | } |
| 186 | |
| 187 | // 6. 解析搜索结果页面 |
| 188 | doc, err := goquery.NewDocumentFromReader(resp.Body) |
| 189 | if err != nil { |
| 190 | return nil, fmt.Errorf("[%s] 解析搜索页面失败: %w", p.Name(), err) |
| 191 | } |
| 192 | |
| 193 | // 7. 提取搜索结果 |
| 194 | var results []model.SearchResult |
| 195 | |
| 196 | doc.Find(".module-search-item").Each(func(i int, s *goquery.Selection) { |
| 197 | result := p.parseSearchItem(s, keyword) |
nothing calls this directly
no test coverage detected