daShangDao_kfzgw-info/kfztp.go
2025-11-24 13:50:54 +08:00

2012 lines
64 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import "C"
///*
//#include <stdlib.h>
//
//// proxyConfig.dll 函数声明
//extern char* ProxyTypeManager(char* proxyType, char* username, char* password, char* machineCode);
//extern void FreeCString(char* str);
//*/
//import "C"
//import (
// "context"
// "encoding/json"
// "fmt"
// "io"
// "log"
// "net/http"
// "os"
// "path/filepath"
// "regexp"
// "strconv"
// "strings"
// "sync"
// "syscall"
// "time"
// "unsafe"
//
// "github.com/PuerkitoBio/goquery"
// "github.com/chromedp/chromedp"
// "github.com/parnurzeal/gorequest"
//)
//
//const (
// UseProxy = "proxy" // 使用代理
// NotProxy = "direct" // 不用代理代理
//)
//
//type Config struct {
// App struct {
// MaxRetryTimes int `ini:"app.max_retry_times" json:"max_retry_times" default:"3"`
// RateLimitDelay time.Duration `ini:"app.rate_limit_delay" json:"rate_limit_delay" default:"500ms"`
// Size int `ini:"app.size" json:"size" default:"5"`
// DefaultUserAgent string `ini:"app.default_user_agent" json:"default_user_agent" default:"Mozilla/5.0"`
// } `ini:"app" json:"app"`
//
// API struct {
// LoginURL string `ini:"api.login_url" json:"login_url" default:"https://login.kongfz.com/Pc/Login/account"`
// BookSearchURL string `ini:"api.book_search_url" json:"book_search_url" default:"https://search.kongfz.com/pc-gw/search-web/client/pc/bookLib/keyword/list"`
// ProductSearchURL string `ini:"api.product_search_url" json:"product_search_url" default:"https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/list"`
// } `ini:"api" json:"api"`
//
// Proxy struct {
// Servers string `ini:"proxy.servers" json:"servers" default:"http-dynamic.xiaoxiangdaili.com,http-dynamic-S02.xiaoxiangdaili.com,http-dynamic-S03.xiaoxiangdaili.com,http-dynamic-S04.xiaoxiangdaili.com"`
// Username string `ini:"proxy.username" json:"username" default:"1297757178467602432"`
// Password string `ini:"proxy.password" json:"password" default:"QgQBvP7f"`
// TailMachineCode string `ini:"proxy.tail_machine_code" json:"tail_machine_code" default:"b7bf22a237ec692f13fcc2c43ee63252"`
// TailCardKey string `ini:"proxy.tail_card_key" json:"tail_card_key" default:"DL_20_YK_1920acb2129844c2aabade3896560a9b"`
// ProxyFilePath string `ini:"proxy.proxy_file_path" json:"proxy_file_path" default:"dll/proxyConfig.dll"`
// } `ini:"proxy" json:"proxy"`
//}
//
//// 条目详情结构体
//type BookInfo struct {
// BookName string `json:"book_name"` // 书名
// Author string `json:"author"` // 作者
// Publisher string `json:"publisher"` // 出版社
// ISBN string `json:"isbn"` // ISBN
// PublicationTime int64 `json:"publication_time"` // 出版时间
// Edition string `json:"edition"` // 版次
// PrintTime string `json:"print_time"` // 印刷时间
// FixPrice string `json:"fix_price"` // 定价
// BindingLayout string `json:"binding_layout"` // 装帧
// Format string `json:"format"` // 开本
// Paper string `json:"paper"` // 纸张
// Pages string `json:"pages"` // 页数
// Wordage string `json:"wordage"` // 字数
// Languages string `json:"languages"` // 语种
// Era string `json:"era"` // 年代
// EngravingMethod string `json:"engraving_method"` // 刻印方式
// Dimensions string `json:"dimensions"` // 尺寸
// VolumeNumber string `json:"volume_number"` // 册数
// BookPic string `json:"book_pic"` // 图书封面图(官图)
// BookPicS string `json:"book_pic_s"` // 图书封面图(实拍图)
// SellingPrice string `json:"selling_price"` // 售价
// Condition string `json:"condition"` // 品相
// ExpressDeliveryFee string `json:"express_delivery_fee"` // 快递费
// Editor string `json:"editor"` // 编辑
// Category string `json:"category"` // 分类
// BuyCount string `json:"buy_count"` // 买过
// SellCount string `json:"sell_count"` // 在卖
// Content string `json:"content"` // 内容
// Mid int64 `json:"mid"` // 商家id
// ItemId int64 `json:"item_id"` // 商品id
// ShopId int64 `json:"shop_id"` // 店铺id
//}
//
//// API响应结构
//type APIResponse struct {
// Success bool `json:"success"`
// Message string `json:"message,omitempty"`
// GoodsNum string `json:"goods_num,omitempty"`
// PNum string `json:"pnum,omitempty"`
// Data interface{} `json:"data,omitempty"`
// Error string `json:"error,omitempty"`
//}
//
//// 全局变量
//var (
// cf Config // 配置信息
// tailProxyMu sync.Mutex // 互斥锁
// proxyFailCount int
//
// // 全局代理管理器
// globalProxyManager *ProxyConfigManager
// proxyManagerOnce sync.Once
// proxyManagerInitErr error
//)
//
//// ProductInfo 商品信息结构
//type ProductInfo struct {
// ItemID string `json:"itemId"`
// BookName string `json:"bookName"`
// Price string `json:"price"`
// ShippingFee string `json:"shippingFee"`
//}
//
//// ProductResponse 响应结构
//type ProductResponse struct {
// Success bool `json:"success"`
// Message string `json:"message,omitempty"`
// Data []ProductInfo `json:"data,omitempty"`
//}
//
//// 并行获取详情的结果结构
//type DetailResult struct {
// URL string
// Doc *goquery.Document
// Error error
// Index int
//}
//
//// 第一阶段:收集基本信息并识别需要详情的项目
//type BookItem struct {
// Book BookInfo
// Selection *goquery.Selection
// HasDetail bool
// DetailURL string
// Index int
//}
//
//// 销量榜目录分类列表响应结构体
//type SalesCategoryResponse struct {
// Status bool `json:"status"`
// Result []SalesCategory `json:"result"`
// ErrMessage string `json:"errMessage"`
// ErrCode int `json:"errCode"`
//}
//
//// 分类项结构体
//type SalesCategory struct {
// Key string `json:"key"`
// Value int `json:"value"`
//}
//
//// 图书详情响应结构体
//type BookDetailResponse struct {
// Status bool `json:"status"`
// Result BookList `json:"result"`
// ErrMessage string `json:"errMessage"`
// ErrCode int `json:"errCode"`
//}
//
//// 图书列表结构体
//type BookList struct {
// Current int `json:"current"`
// Data []BookInformation `json:"data"`
// Total int `json:"total"`
//}
//
//// 图书信息结构体
//type BookInformation struct {
// Author string `json:"author"`
// BookName string `json:"bookName"`
// ContentIntroduction string `json:"contentIntroduction"`
// ImgUrl string `json:"imgUrl"`
// Isbn string `json:"isbn"`
// ItemUrls ItemUrls `json:"itemUrls"`
// Mid int `json:"mid"`
// NewMinPrice string `json:"newMinPrice"`
// OldMinPrice string `json:"oldMinPrice"`
// Press string `json:"press"`
// Price string `json:"price"`
// PubDate string `json:"pubDate"`
// RiseTag string `json:"riseTag"`
// AuthorArr []AuthorInfo `json:"authorArr"`
// PressUrl string `json:"pressUrl"`
//}
//
//// 作者信息结构体
//type AuthorInfo struct {
// Name string `json:"name"`
// OriName string `json:"oriName"`
// Nationality string `json:"nationality"`
// Role string `json:"role"`
// Url string `json:"url"`
//}
//
//// 商品链接结构体
//type ItemUrls struct {
// AppUrl string `json:"appUrl"`
// MUrl string `json:"mUrl"`
// MiniUrl string `json:"miniUrl"`
// PcUrl string `json:"pcUrl"`
//}
//
//// ProxyConfigManager 代理配置DLL管理器
//type ProxyConfigManager struct {
// dll *syscall.DLL
//}
//
//func NewProxyConfigManager(dllPath string) (*ProxyConfigManager, error) {
// dll, err := syscall.LoadDLL(dllPath)
// if err != nil {
// return nil, fmt.Errorf("加载代理配置DLL失败: %v", err)
// }
// return &ProxyConfigManager{dll: dll}, nil
//}
//
//func (m *ProxyConfigManager) Close() {
// if m.dll != nil {
// m.dll.Release()
// }
//}
//
//// ProxyTypeManager 调用代理类型管理器
//func (m *ProxyConfigManager) ProxyTypeManager(proxyType, username, password, machineCode string) (string, error) {
// proc, err := m.dll.FindProc("ProxyTypeManager")
// if err != nil {
// return "", fmt.Errorf("找不到函数 ProxyTypeManager: %v", err)
// }
//
// // 准备参数
// proxyTypePtr, _ := syscall.BytePtrFromString(proxyType)
// usernamePtr, _ := syscall.BytePtrFromString(username)
// passwordPtr, _ := syscall.BytePtrFromString(password)
// machineCodePtr, _ := syscall.BytePtrFromString(machineCode)
//
// // 调用函数
// r1, _, err := proc.Call(
// uintptr(unsafe.Pointer(proxyTypePtr)),
// uintptr(unsafe.Pointer(usernamePtr)),
// uintptr(unsafe.Pointer(passwordPtr)),
// uintptr(unsafe.Pointer(machineCodePtr)),
// )
//
// if err != nil && err.Error() != "The operation completed successfully." {
// return "", fmt.Errorf("调用 ProxyTypeManager 失败: %v", err)
// }
//
// // 转换结果
// result := (*byte)(unsafe.Pointer(r1))
// var resultBytes []byte
// for i := 0; ; i++ {
// bytePtr := (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(result)) + uintptr(i)))
// if *bytePtr == 0 {
// break
// }
// resultBytes = append(resultBytes, *bytePtr)
// }
//
// // 释放内存
// freeProc, _ := m.dll.FindProc("FreeCString")
// if freeProc != nil {
// freeProc.Call(r1)
// }
//
// return string(resultBytes), nil
//}
//
//// 获取销量榜所有分类中图书的isbn
//func GetAllCategoryBooks() ([]string, error) {
// // 1. 获取分类列表
// categories, err := GetSalesBookInfo()
// if err != nil {
// return nil, fmt.Errorf("获取分类列表失败: %v", err)
// }
// // 初始化返回的ISBN数组
// var allISBNs []string
//
// for i, category := range categories {
// fmt.Printf("\n=== 正在处理分类 %d/%d: %s (ID: %d) ===\n", i+1, len(categories), category.Key, category.Value)
// // 根据分类ID获取图书详情
// bookDetails, err := GetBookDetailsByCategory(category.Value)
// if err != nil {
// fmt.Printf("获取分类 %s 的图书信息失败: %v\n", category.Key, err)
// continue
// }
// // 将当前分类的图书数据添加到结果map中
// if bookDetails != nil && bookDetails.Result.Data != nil {
// for _, book := range bookDetails.Result.Data {
// if book.Isbn != "" {
// allISBNs = append(allISBNs, book.Isbn)
// fmt.Printf("添加到ISBN列表: %s\n", book.Isbn)
// }
// }
// fmt.Printf("分类 %s 获取到 %d 本图书\n", category.Key, len(bookDetails.Result.Data))
// } else {
// fmt.Printf("分类 %s 没有获取到图书数据\n", category.Key)
// }
// time.Sleep(500 * time.Microsecond)
// }
// // 去重处理(可选)
// allISBNs = removeDuplicateISBNs(allISBNs)
// // 打印统计信息
// fmt.Printf("\n=== 总计: %d 个分类, %d 个唯一ISBN ===\n", len(categories), len(allISBNs))
// return allISBNs, nil
//}
//
//// 辅助函数去除重复的ISBN
//func removeDuplicateISBNs(isbns []string) []string {
// seen := make(map[string]bool)
// var result []string
//
// for _, isbn := range isbns {
// if !seen[isbn] {
// seen[isbn] = true
// result = append(result, isbn)
// }
// }
//
// return result
//}
//
//// 获取销量榜的图书信息
//func GetSalesBookInfo() ([]SalesCategory, error) {
// // 构建请求URL
// url := "https://item.kongfz.com/api/Pc/getSellWellCatList"
// // 创建HTTP客户端
// client := &http.Client{
// Timeout: 30 * time.Second,
// }
// // 创建请求
// req, err := http.NewRequest("GET", url, nil)
// if err != nil {
// return nil, fmt.Errorf("创建请求失败: %v", err)
// }
// // 设置请求头,模拟浏览器请求
// 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")
// req.Header.Set("Accept", "application/json, text/plain, */*")
// req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
// req.Header.Set("Referer", "https://item.kongfz.com/")
// // 发送请求
// resp, err := client.Do(req)
// if err != nil {
// return nil, fmt.Errorf("请求失败: %v", err)
// }
// defer resp.Body.Close()
// // 检查HTTP状态码
// if resp.StatusCode != http.StatusOK {
// return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
// }
// // 读取响应体
// body, err := io.ReadAll(resp.Body)
// if err != nil {
// return nil, fmt.Errorf("读取响应失败: %v", err)
// }
// // 解析JSON响应
// var salesCategoryResponse SalesCategoryResponse
// err = json.Unmarshal(body, &salesCategoryResponse)
// if err != nil {
// return nil, fmt.Errorf("解析JSON失败: %v", err)
// }
// return salesCategoryResponse.Result, nil
//}
//
//// 根据分类ID获取图书详情
//func GetBookDetailsByCategory(catId int) (*BookDetailResponse, error) {
// // 构建请求URL
// url := fmt.Sprintf("https://item.kongfz.com/api/pc/getSellWellListDetail?page=1&pageSize=100&timeRank=2&catId=%d", catId)
// // 创建HTTP客户端
// client := &http.Client{
// Timeout: 30 * time.Second,
// }
// // 创建请求
// req, err := http.NewRequest("GET", url, nil)
// if err != nil {
// return nil, fmt.Errorf("创建请求失败: %v", err)
// }
// // 设置请求头,模拟浏览器请求
// 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")
// req.Header.Set("Accept", "application/json, text/plain, */*")
// req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
// req.Header.Set("Referer", "https://item.kongfz.com/")
// // 发送请求
// resp, err := client.Do(req)
// if err != nil {
// return nil, fmt.Errorf("请求失败: %v", err)
// }
// defer resp.Body.Close()
// // 检查HTTP状态码
// if resp.StatusCode != http.StatusOK {
// return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
// }
// // 读取响应体
// body, err := io.ReadAll(resp.Body)
// if err != nil {
// return nil, fmt.Errorf("读取响应失败: %v", err)
// }
// var bookDetailResponse BookDetailResponse
// err = json.Unmarshal(body, &bookDetailResponse)
// if err != nil {
// return nil, fmt.Errorf("解析JSON失败: %v", err)
// }
// if !bookDetailResponse.Status {
// return nil, fmt.Errorf("API返回错误: %s (代码: %d)", bookDetailResponse.ErrMessage, bookDetailResponse.ErrCode)
// }
// return &bookDetailResponse, nil
//}
//
//// 通过店铺ID获取孔网实拍图和条目信息
//func getKFZShopBookInfo(fetchMode, proxyType, username, password, machineCode, shopId, isImage, bookNum, pageNum, sortType, sort, priceDown, priceUp string) (books []BookInfo, goodsNum string, pNum string, err error) {
// // 判断店铺ID
// if shopId == "" {
// return nil, "", "", fmt.Errorf("店铺编码为空!")
// }
// // 判断是否有图片设置默认值0
// if isImage == "" {
// isImage = "0"
// } else {
// _, isImageErr := strconv.Atoi(isImage)
// if isImageErr != nil {
// return nil, "", "", fmt.Errorf("是否有图片输入必须是数字!", isImageErr)
// }
// }
// // 判断一页图书数量设置默认值100
// if bookNum == "" {
// bookNum = "100"
// } else {
// isBookNum, bookNumErr := strconv.Atoi(bookNum)
// if bookNumErr != nil {
// return nil, "", "", fmt.Errorf("图书数量输入必须是数字!", bookNumErr)
// }
// if isBookNum < 0 && isBookNum > 100 {
// return nil, "", "", fmt.Errorf("图书数量输入错误:只能出入(0~100区间)")
// }
// }
// // 判断页数设置默认值1
// if pageNum == "" {
// pageNum = "1"
// } else {
// _, pageNumErr := strconv.Atoi(pageNum)
// if pageNumErr != nil {
// return nil, "", "", fmt.Errorf("页数输入必须是数字!", pageNumErr)
// }
// }
// // 判断排序类型设置默认值sort
// if sortType == "" {
// sortType = "sort"
// } else {
// validSortTypes := map[string]bool{
// "sort": true,
// "putDate": true,
// "newItem": true,
// "price": true,
// }
// if !validSortTypes[sortType] {
// return nil, "", "", fmt.Errorf("无效的排序类型: %s可选值: sort, putDate, newItem, price", sortType)
// }
// }
// // 判断排序设置默认值desc
// if sort == "" {
// sort = "desc"
// } else {
// validSorts := map[string]bool{
// "desc": true,
// "asc": true,
// }
// if !validSorts[sort] {
// return nil, "", "", fmt.Errorf("无效的排序类型: %s可选值: desc, asc", sort)
// }
// }
// // 判断价格下限设置默认值0
// if priceDown == "" {
// priceDown = "0"
// } else {
// _, priceDownErr := strconv.ParseFloat(priceDown, 64)
// if priceDownErr != nil {
// return nil, "", "", fmt.Errorf("价格输入必须是数字!", priceDownErr)
// }
// }
// // 判断价格上限设置默认值0
// if priceUp == "" {
// priceUp = "0"
// } else {
// _, priceUpErr := strconv.ParseFloat(priceUp, 64)
// if priceUpErr != nil {
// return nil, "", "", fmt.Errorf("价格输入必须是数字!", priceUpErr)
// }
// }
// // 调用的url
// url := fmt.Sprintf("https://shop.kongfz.com/%s/all/%s_%s_0_0_%s_%s_%s_%s_%s",
// shopId, isImage, bookNum, pageNum, sortType, sort, priceDown, priceUp)
// log.Printf("调用的URL: %s", url)
// // 并行获取商品信息使用优化后的Chromedp
// response, err := FetchProductInfoWithChromedp(url)
// if err != nil {
// fmt.Printf("❌ 获取商品信息失败: %v", err)
// }
// // 发送请求
// doc, err := fetchDocument(fetchMode, proxyType, username, password, machineCode, url)
//
// // 全部商品数量
// num := doc.Find("div.crumbs-nav-main.clearfix").Find("span")
// if match := regexp.MustCompile(`\d+`).FindString(num.Text()); match != "" {
// goodsNum = match
// }
// // 商品页数
// pg := doc.Find("li.pull-right.page_num").Find("span")
// _, split, found := strings.Cut(strings.TrimSpace(pg.Text()), "/")
// if found {
// pNum = split
// } else {
// log.Printf("未找到页数!")
// }
//
// infoDiv := doc.Find("div.list-content")
// if infoDiv.Length() > 0 {
// item := infoDiv.Find("div.item.clearfix")
// var bookItems []BookItem
//
// for i := 0; i < item.Length(); i++ {
// s := item.Eq(i)
// book := BookInfo{}
// // 书名
// book.BookName = strings.TrimSpace(s.Find("div.title a.link").Text())
// // 作者
// book.Author = extractNormalText(s, "作者")
// // 出版社
// book.Publisher = extractNormalText(s, "出版社")
// // 出版时间,提取出版时间并转换为时间戳
// pubTimeStr := extractNormalText(s, "出版时间")
// if pubTimeStr != "" {
// // 尝试不同的时间格式
// formats := []string{"2006-01", "2006-01-02", "2006"}
// for _, format := range formats {
// if t, err := time.Parse(format, pubTimeStr); err == nil {
// book.PublicationTime = t.Unix()
// break
// }
// }
// }
// // 提取ISBN
// book.ISBN = strings.TrimSpace(s.AttrOr("isbn", ""))
// // 版次
// book.Edition = extractNormalText(s, "版次")
// // 印刷时间
// book.PrintTime = extractNormalText(s, "印刷时间")
// // 装帧
// book.BindingLayout = extractNormalText(s, "装帧")
// // 开本
// book.Format = extractNormalText(s, "开本")
// // 纸张
// book.Paper = extractNormalText(s, "纸张")
// // 字数
// book.Wordage = extractNormalText(s, "字数")
// // 售价,提取价格(优先从元素属性获取)
// book.SellingPrice = s.AttrOr("price", "")
// if book.SellingPrice == "" {
// book.SellingPrice = strings.TrimSpace(s.Find("div.price span.bold").Text())
// }
// // 提取图片
// if img, exists := s.Find("div.item-img img").Attr("src"); exists {
// book.BookPicS = img
// }
// // 快递费
// val, exists := s.Attr("itemid")
// for in, p := range response.Data {
// if exists {
// if val == p.ItemID {
// book.ExpressDeliveryFee = p.ShippingFee
// in = in + 1
// }
// }
// }
// // 提取品相
// book.Condition = strings.TrimSpace(s.Find("div.quality").Text())
//
// // 检查是否需要获取详情
// hasDetail := s.Find("div.zl-isbn-info").Length() > 0
// detailURl := ""
// if hasDetail {
// detailURl = s.Find("a.img-box").AttrOr("href", "")
// }
//
// bookItems = append(bookItems, BookItem{
// Book: book,
// Selection: s,
// HasDetail: hasDetail,
// DetailURL: detailURl,
// Index: i,
// })
// }
//
// detailResults := fetchAllDetailsParallel(fetchMode, proxyType, username, password, machineCode, bookItems)
// books = mergeBookDetails(bookItems, detailResults)
// }
// return books, goodsNum, pNum, nil
//}
//
//// 并行获取所有详情
//func fetchAllDetailsParallel(fetchMode, proxyType, username, password, machineCode string, bookItems []BookItem) map[string]*DetailResult {
// // 收集所有需要获取详情的URL
// var detailTasks []struct {
// URL string
// Index int
// }
//
// for _, item := range bookItems {
// if item.HasDetail && item.DetailURL != "" {
// detailTasks = append(detailTasks, struct {
// URL string
// Index int
// }{
// URL: item.DetailURL,
// Index: item.Index,
// })
// }
// }
//
// if len(detailTasks) == 0 {
// return make(map[string]*DetailResult)
// }
//
// type taskResult struct {
// URL string
// Doc *goquery.Document
// Error error
// Index int
// }
//
// ch := make(chan taskResult, len(detailTasks))
// var wg sync.WaitGroup
//
// // 限制并发数,避免过多连接
// sem := make(chan struct{}, 5) // 最大5个并发
//
// for _, task := range detailTasks {
// wg.Add(1)
// go func(url string, index int) {
// defer wg.Done()
// sem <- struct{}{} // 获取信号量
// defer func() { <-sem }() // 释放信号量
//
// doc, err := fetchDocument(fetchMode, proxyType, username, password, machineCode, url)
// ch <- taskResult{
// URL: url,
// Doc: doc,
// Error: err,
// Index: index,
// }
// }(task.URL, task.Index)
// }
//
// wg.Wait()
// close(ch)
//
// results := make(map[string]*DetailResult)
// for res := range ch {
// results[res.URL] = &DetailResult{
// URL: res.URL,
// Doc: res.Doc,
// Error: res.Error,
// Index: res.Index,
// }
// }
//
// return results
//}
//
//// 获取Document文档(带重试机制)
//func fetchDocument(fetchMode, proxyType, username, password, machineCode, url string) (*goquery.Document, error) {
// log.Printf("调用的URL: %s", url)
// maxRetries := cf.App.MaxRetryTimes
// var detailsResp *http.Response
// var errors []error
// var detailsBody []byte
// for attempt := 0; attempt < maxRetries; attempt++ {
// if attempt > 0 {
// log.Printf("第 %d 次重试请求...", attempt)
// // 重试前等待,使用指数退避策略
// waitTime := time.Duration(attempt*attempt) * cf.App.RateLimitDelay // 平方退避
// log.Printf("等待 %v 后重试", waitTime)
// time.Sleep(waitTime)
// }
// if fetchMode == NotProxy {
// detailsResp, _, errors = gorequest.New().
// Get(url).
// Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36").
// Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8").
// Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
// Timeout(120 * time.Second).
// End()
// } else if fetchMode == UseProxy {
// detailsReq := XxProxyRequest(proxyType, username, password, machineCode).
// Get(url).
// Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36").
// Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8").
// Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
// Set("Connection", "close") // 每次请求关闭连接
// detailsResp, _, errors = detailsReq.End()
// } else {
// errors = append(errors, fmt.Errorf("请求失败,选择模式错误!"))
// }
// // 检查是否需要重试
// shouldRetry := false
// if len(errors) > 0 {
// shouldRetry = true
// log.Printf("请求失败 (尝试 %d/%d): %v", attempt+1, maxRetries+1, errors)
// } else if detailsResp == nil {
// shouldRetry = true
// log.Printf("响应为空 (尝试 %d/%d)", attempt+1, maxRetries+1)
// } else if detailsResp.StatusCode != http.StatusOK {
// // 只对服务器错误进行重试,不对客户端错误重试
// if detailsResp.StatusCode >= 500 {
// shouldRetry = true
// }
// log.Printf("HTTP状态码 %d,HTTP请求失败: %s (尝试 %d/%d)", detailsResp.StatusCode, detailsResp.Body, attempt+1, maxRetries+1)
// }
// // 如果不需要重试,跳出循环
// if !shouldRetry {
// break
// }
// // 如果是最后一次尝试,不继续重试
// if attempt == maxRetries {
// break
// }
// // 关闭响应体(如果存在)
// if detailsResp != nil && detailsResp.Body != nil {
// detailsResp.Body.Close()
// }
// }
// // 检测请求是否错误
// if len(errors) > 0 {
// var proxyAuthFailed bool
// var timeoutError bool
// var connectionError bool
// for _, e := range errors {
// errStr := e.Error()
// if strings.Contains(errStr, "Proxy Authentication Required") {
// proxyAuthFailed = true
// }
// if strings.Contains(errStr, "timeout") || strings.Contains(errStr, "i/o timeout") {
// timeoutError = true
// }
// if strings.Contains(errStr, "connection") || strings.Contains(errStr, "connect") {
// connectionError = true
// }
// }
// if proxyAuthFailed {
// return nil, fmt.Errorf("代理认证失败")
// }
// if timeoutError {
// return nil, fmt.Errorf("请求超时,经过 %d 次尝试,超时网址:%s", maxRetries+1, url)
// }
// if connectionError {
// return nil, fmt.Errorf("网络连接错误,经过 %d 次尝试,错误网址:%s", maxRetries+1, url)
// }
// return nil, fmt.Errorf("查询请求失败,经过 %d 次尝试: %v失败网址:%s", maxRetries+1, errors, url)
// }
// if detailsResp.StatusCode != http.StatusOK {
// return nil, fmt.Errorf("HTTP错误: %s", detailsResp.Status)
// }
//
// detailsBody, err := io.ReadAll(detailsResp.Body)
// if err != nil {
// return nil, err
// }
//
// return goquery.NewDocumentFromReader(strings.NewReader(string(detailsBody)))
//}
//
//// 合并基本信息和详情
//func mergeBookDetails(bookItems []BookItem, detailResults map[string]*DetailResult) []BookInfo {
// var books []BookInfo
//
// for _, item := range bookItems {
// book := item.Book
//
// // 如果有详情且获取成功,补充详细信息
// if item.HasDetail && item.DetailURL != "" {
// if result, exists := detailResults[item.DetailURL]; exists && result.Error == nil && result.Doc != nil {
// detailsDiv := result.Doc.Find("div.detail-lists.clear-fix")
// if detailsDiv.Length() > 0 {
// selection := detailsDiv.Find("li")
// book.Author = extractNormalDetails(selection, "作者")
// book.Publisher = extractNormalDetails(selection, "出版社")
// detailsTime := extractNormalDetails(selection, "出版时间")
// if detailsTime != "" {
// formats := []string{"2006-01", "2006-01-02", "2006"}
// for _, format := range formats {
// if t, err := time.Parse(format, detailsTime); err == nil {
// book.PublicationTime = t.Unix()
// break
// }
// }
// }
// book.ISBN = extractNormalDetails(selection, "ISBN")
// book.Edition = extractNormalDetails(selection, "版次")
// book.FixPrice = extractNormalDetails(selection, "定价")
// book.BindingLayout = extractNormalDetails(selection, "装帧")
// book.Format = extractNormalDetails(selection, "开本")
// book.Pages = extractNormalDetails(selection, "页数")
// book.Wordage = extractNormalDetails(selection, "字数")
// }
// }
// }
//
// books = append(books, book)
// }
// return books
//}
//
//// 根据url获取单个图书详情信息
//func getUrlBookDetails(fetchMode, proxyType, username, password, machineCode, url string) (books []BookInfo, err error) {
// document, err := fetchDocument(fetchMode, proxyType, username, password, machineCode, url)
// if err != nil {
// return nil, err
// }
//
// fee, err := FetchBookDetailsShippingFee(url)
// if err != nil {
// return nil, err
// }
// book := BookInfo{}
// //书名
// book.BookName = strings.TrimSpace(document.Find("h1.title").Text())
//
// //作者等信息
// topDiv := document.Find("div.keywords-define.keywords-define-1000.clear-fix")
// if topDiv.Length() > 0 {
// topDiv.Find("li").Each(func(i int, li *goquery.Selection) {
// titleSpan := li.Find("span.keywords-define-title")
// contentSpan := li.Find("span.keywords-define-txt")
// if contentSpan.Length() == 0 {
// fmt.Printf("未找到指定的contentSpan信息")
// }
// titleText := strings.TrimSpace(titleSpan.Text())
// contentText := strings.TrimSpace(contentSpan.Text())
// titleText = strings.TrimSpace(titleText)
// if strings.Contains(titleText, "作者") {
// book.Author = cleanString(contentText)
// }
// if strings.Contains(titleText, "出版社") {
// book.Publisher = contentText
// }
// if strings.Contains(titleText, "出版人") {
// book.Publisher = contentText
// }
// if strings.Contains(titleText, "ISBN") {
// book.ISBN = contentText
// }
// if strings.Contains(titleText, "出版时间") {
// book.PublicationTime = validateDateFormat(contentText)
// }
// if strings.Contains(titleText, "版次") {
// book.Edition = contentText
// }
// if strings.Contains(titleText, "装帧") {
// book.BindingLayout = contentText
// }
// if strings.Contains(titleText, "开本") {
// book.Format = contentText
// }
// if strings.Contains(titleText, "页数") {
// book.Pages = contentText
// }
// if strings.Contains(titleText, "字数") {
// book.Wordage = contentText
// }
// if strings.Contains(titleText, "纸张") {
// book.Paper = contentText
// }
// if strings.Contains(titleText, "年代") {
// book.Era = contentText
// }
// if strings.Contains(titleText, "刻印方式") {
// book.EngravingMethod = contentText
// }
// if strings.Contains(titleText, "尺寸") {
// book.Dimensions = contentText
// }
// if strings.Contains(titleText, "册数") {
// book.VolumeNumber = contentText
// }
// })
// } else {
// botDiv := document.Find("div.detail-lists.clear-fix")
// botDiv.Find("li").Each(func(i int, li *goquery.Selection) {
// spanText := strings.TrimSpace(li.Find("span").Text())
// spanText = strings.TrimSpace(spanText)
// if strings.Contains(li.Text(), "作者") {
// book.Author = cleanString(li.Text())
// book.Author = strings.ReplaceAll(book.Author, "作者:", "")
// book.Author = strings.ReplaceAll(book.Author, "著", "")
// }
// if strings.Contains(li.Text(), "出版社") {
// book.Publisher = spanText
// }
// if strings.Contains(li.Text(), "出版时间") {
// book.PublicationTime = validateDateFormat(spanText)
// }
// if strings.Contains(li.Text(), "ISBN") {
// book.ISBN = spanText
// }
// if strings.Contains(li.Text(), "装帧") {
// book.BindingLayout = spanText
// }
// if strings.Contains(li.Text(), "开本") {
// book.Format = spanText
// }
// if strings.Contains(li.Text(), "纸张") {
// book.Paper = spanText
// }
// if strings.Contains(li.Text(), "版次") {
// book.Edition = spanText
// }
// if strings.Contains(li.Text(), "页数") {
// book.Pages = spanText
// }
// if strings.Contains(li.Text(), "字数") {
// book.Wordage = spanText
// }
// })
// }
//
// //图片
// var imgUrls []string
// tpUl := document.Find("ul.lg-list")
// tpUl.Find("img").Each(func(i int, s *goquery.Selection) {
// dataImgUrl, exists := s.Attr("data-imgurl")
// if exists && dataImgUrl != "" {
// imgUrls = append(imgUrls, dataImgUrl)
// }
// })
// book.BookPicS = strings.Join(imgUrls, ",")
// // 售价
// price := document.Find("i.now-price-text").Text()
// priceN := regexp.MustCompile(`(\d+\.?\d*)`)
// if match := priceN.FindStringSubmatch(price); len(match) > 0 {
// book.SellingPrice = match[1]
// }
// // 定价价
// fixPrice := document.Find("span.origin-price-text.clearfix").Text()
// fixPriceN := regexp.MustCompile(`(\d+\.?\d*)`)
// if match := fixPriceN.FindStringSubmatch(fixPrice); len(match) > 0 {
// book.FixPrice = match[1]
// }
// // 品相
// text := document.Find("span.quality-text-cot.clearfix i").Text()
// book.Condition = strings.TrimSpace(text)
// // 快递费
// if fee != "" {
// if fee == "包邮" {
// book.ExpressDeliveryFee = "0"
// } else {
// book.ExpressDeliveryFee = fee
// }
// }
// books = append(books, book)
// return books, nil
//}
//
//// 获取店铺页面的所有快递费用
//func FetchProductInfoWithChromedp(url string) (*ProductResponse, error) {
// // 创建上下文
// opts := append(chromedp.DefaultExecAllocatorOptions[:],
// chromedp.Flag("headless", true),
// chromedp.Flag("disable-gpu", true),
// chromedp.Flag("no-sandbox", true),
// chromedp.Flag("disable-dev-shm-usage", true),
// chromedp.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"),
// // 禁用图片加载,加快速度
// chromedp.Flag("blink-settings", "imagesEnabled=false"),
// )
// // 启动浏览器
// allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
// defer cancel()
// // 创建浏览器上下文
// ctx, cancel := chromedp.NewContext(allocCtx)
// defer cancel()
// // 设置超时
// ctx, cancel = context.WithTimeout(ctx, 60*time.Second)
// defer cancel()
// log.Printf("[CHROMEDP] 开始导航到URL: %s", url)
// // 第一步:先导航到页面并等待完全加载
// err := chromedp.Run(ctx,
// // 导航到目标页面
// chromedp.Navigate(url),
//
// // 等待页面初步加载
// chromedp.WaitReady("body", chromedp.ByQuery),
// chromedp.Sleep(3*time.Second),
//
// // 第二步:刷新页面,重新加载动态内容
// chromedp.Reload(),
//
// // 等待刷新后页面加载
// chromedp.WaitReady("body", chromedp.ByQuery),
// chromedp.Sleep(5*time.Second),
//
// // 等待关键元素出现
// chromedp.WaitVisible(".item.clearfix", chromedp.ByQuery),
//
// // 滚动页面以触发动态加载
// chromedp.Evaluate(`window.scrollTo(0, document.body.scrollHeight / 3)`, nil),
// chromedp.Sleep(2*time.Second),
// chromedp.Evaluate(`window.scrollTo(0, document.body.scrollHeight / 2)`, nil),
// chromedp.Sleep(2*time.Second),
// chromedp.Evaluate(`window.scrollTo(0, document.body.scrollHeight)`, nil),
// chromedp.Sleep(3*time.Second),
// chromedp.Evaluate(`window.scrollTo(0, 0)`, nil),
// chromedp.Sleep(1*time.Second),
// )
// if err != nil {
// log.Printf("[CHROMEDP] 页面导航失败: %v", err)
// return nil, fmt.Errorf("页面导航失败: %v", err)
// }
// log.Printf("[CHROMEDP] 页面导航完成,开始提取数据")
// var evalResult map[string]interface{}
// // 执行任务
// err = chromedp.Run(ctx,
// // 导航到目标页面
// chromedp.Navigate(url),
//
// // 执行 JavaScript 来提取商品信息
// chromedp.Evaluate(`(function() {
// console.log("开始提取商品信息...");
// try {
// let productData = [];
// // 查找所有商品项 - 针对孔夫子旧书网的特定选择器
// const itemSelectors = [
// '.item.clearfix',
// '.list-item',
// '.product-item',
// '.goods-item',
// '[class*="item"]'
// ];
// let items = [];
// for (let selector of itemSelectors) {
// const found = document.querySelectorAll(selector);
// if (found.length > 0) {
// items = found;
// console.log("使用选择器:", selector, "找到项目数:", items.length);
// break;
// }
// }
//
// if (items.length === 0) {
// // 如果没有找到特定选择器,尝试查找任何看起来像商品的项目
// items = document.querySelectorAll('div[class*="item"], li[class*="item"]');
// console.log("使用通用选择器找到项目数:", items.length);
// }
// console.log("总共找到商品项:", items.length);
// // 遍历每个商品项
// items.forEach((item, index) => {
// // 提取 itemid
// let itemId = '';
//
// // 方法1: 从元素属性获取
// if (item.hasAttribute('itemid')) {
// itemId = item.getAttribute('itemid');
// }
//
// // 方法2: 从数据属性获取
// if (!itemId && item.hasAttribute('data-itemid')) {
// itemId = item.getAttribute('data-itemid');
// }
//
// // 方法3: 从ID属性获取
// if (!itemId && item.hasAttribute('id')) {
// const id = item.getAttribute('id');
// if (id.includes('item') || id.includes('product')) {
// itemId = id;
// }
// }
//
// // 方法4: 从链接中提取itemid
// if (!itemId) {
// const links = item.querySelectorAll('a[href*="item"], a[href*="product"]');
// for (let link of links) {
// const href = link.getAttribute('href');
// if (href) {
// const itemMatch = href.match(/(?:item|product)[_-]?(\d+)/i);
// if (itemMatch) {
// itemId = itemMatch[1];
// break;
// }
// }
// }
// }
//
// // 方法5: 从子元素中查找itemid
// if (!itemId) {
// const childWithItemId = item.querySelector('[itemid], [data-itemid]');
// if (childWithItemId) {
// if (childWithItemId.hasAttribute('itemid')) {
// itemId = childWithItemId.getAttribute('itemid');
// } else if (childWithItemId.hasAttribute('data-itemid')) {
// itemId = childWithItemId.getAttribute('data-itemid');
// }
// }
// }
//
// // 提取书名
// let bookName = '';
// const titleSelectors = [
// '.title a',
// '.book-title',
// '.item-title',
// '.name a',
// 'h3 a',
// 'h4 a',
// '.link',
// 'a[title]'
// ];
//
// for (let selector of titleSelectors) {
// const titleEl = item.querySelector(selector);
// if (titleEl) {
// bookName = titleEl.textContent.trim();
// if (bookName && bookName.length > 1) {
// break;
// }
// }
// }
//
// // 如果没找到尝试在item内查找任何文本作为书名
// if (!bookName) {
// const textContent = item.textContent;
// // 尝试提取看起来像书名的文本(较长的文本块)
// const lines = textContent.split('\n').map(line => line.trim()).filter(line => line.length > 5);
// if (lines.length > 0) {
// bookName = lines[0];
// }
// }
//
// // 提取价格
// let price = '';
// const priceSelectors = [
// '.price span',
// '.price .bold',
// '.current-price',
// '.sell-price',
// '.cost',
// '.money',
// '[class*="price"]',
// 'strong'
// ];
//
// for (let selector of priceSelectors) {
// const priceEl = item.querySelector(selector);
// if (priceEl) {
// let priceText = priceEl.textContent.trim();
// // 清理价格文本,保留数字和小数点
// priceText = priceText.replace(/[^\d\.]/g, '');
// if (priceText && !isNaN(parseFloat(priceText))) {
// price = '¥' + priceText;
// break;
// }
// }
// }
//
// // 如果没找到价格,尝试在文本中查找价格模式
// if (!price) {
// const itemText = item.textContent;
// const priceMatch = itemText.match(/[¥¥]?\s*(\d+\.?\d*)/);
// if (priceMatch) {
// price = '¥' + priceMatch[1];
// }
// }
//
// // 提取快递费用
// let shippingFee = '';
// const shippingSelectors = [
// '.ship-fee',
// '.shipping-fee',
// '.express-fee',
// '.freight',
// '.postage',
// '[class*="fee"]',
// '[class*="快递"]',
// '[class*="运费"]'
// ];
//
// for (let selector of shippingSelectors) {
// const shippingEl = item.querySelector(selector);
// if (shippingEl) {
// shippingFee = shippingEl.textContent.trim();
// if (shippingFee) break;
// }
// }
//
// // 如果没找到运费元素,尝试在文本中查找运费关键词
// if (!shippingFee) {
// const itemText = item.textContent;
// const feeMatches = itemText.match(/(运费[:]\s*[^\s\n]+)|(快递[:]\s*[^\s\n]+)|(邮费[:]\s*[^\s\n]+)/);
// if (feeMatches) {
// shippingFee = feeMatches[0];
// } else if (itemText.includes('包邮') || itemText.includes('免运费')) {
// shippingFee = '包邮';
// } else {
// shippingFee = '运费待确认';
// }
// }
//
// // 清理书名(移除过长的文本)
// if (bookName && bookName.length > 100) {
// bookName = bookName.substring(0, 100) + '...';
// }
//
// // 如果还没有itemid生成一个基于索引的ID
// if (!itemId) {
// itemId = 'item_' + (index + 1);
// }
//
// // 添加到数据中
// productData.push({
// itemId: itemId,
// bookName: bookName || '商品${index + 1}',
// price: price || '价格待确认',
// shippingFee: shippingFee
// });
// });
//
// // 过滤掉明显无效的数据
// productData = productData.filter(item =>
// (item.bookName !== '商品1' || item.price !== '价格待确认') &&
// item.bookName && item.bookName.length > 0
// );
//
// console.log("处理后商品数量:", productData.length);
// if (productData.length > 0) {
// console.log("前3个商品示例:", productData.slice(0, 3));
// }
//
// return {
// success: true,
// message: "成功提取商品信息",
// data: productData
// };
//
// } catch(error) {
// console.error("提取商品信息时出错:", error);
// return {
// success: false,
// message: "提取商品信息时出错: " + error.message,
// data: []
// };
// }
// })()`, &evalResult),
// )
//
// if err != nil {
// return nil, fmt.Errorf("chromedp执行失败: %v", err)
// }
//
// // 处理 JavaScript 执行结果
// response := &ProductResponse{}
//
// // 转换结果数据
// if success, ok := evalResult["success"].(bool); ok {
// response.Success = success
// }
// if message, ok := evalResult["message"].(string); ok {
// response.Message = message
// }
// if data, ok := evalResult["data"].([]interface{}); ok {
// for _, item := range data {
// if productMap, ok := item.(map[string]interface{}); ok {
// product := ProductInfo{}
// if itemId, ok := productMap["itemId"].(string); ok {
// product.ItemID = itemId
// }
// if bookName, ok := productMap["bookName"].(string); ok {
// product.BookName = bookName
// }
// if price, ok := productMap["price"].(string); ok {
// product.Price = price
// }
// if shippingFee, ok := productMap["shippingFee"].(string); ok {
// info := extractShippingInfo(shippingFee)
// product.ShippingFee = info
// }
// response.Data = append(response.Data, product)
// }
// }
// }
//
// return response, nil
//}
//
//// 获取详情页的快递费用
//func FetchBookDetailsShippingFee(url string) (string, error) {
// // 创建上下文
// opts := append(chromedp.DefaultExecAllocatorOptions[:],
// chromedp.Flag("headless", true),
// chromedp.Flag("disable-gpu", true),
// chromedp.Flag("no-sandbox", true),
// chromedp.Flag("disable-dev-shm-usage", true),
// chromedp.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"),
// // 禁用图片加载,加快速度
// chromedp.Flag("blink-settings", "imagesEnabled=false"),
// )
// // 启动浏览器
// allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
// defer cancel()
// // 创建浏览器上下文
// ctx, cancel := chromedp.NewContext(allocCtx)
// defer cancel()
// // 设置超时
// ctx, cancel = context.WithTimeout(ctx, 60*time.Second)
// defer cancel()
// log.Printf("[CHROMEDP] 开始导航到URL: %s", url)
// var result string
//
// // 增强的 JavaScript 脚本
// enhancedJSScript := `
// (function() {
// // 查找包含快递费用的元素
// const elements = document.querySelectorAll('*');
// let shippingFee = null;
//
// elements.forEach(element => {
// if (element.textContent.includes('快递¥')) {
// const match = element.textContent.match(/快递¥(\d+\.\d{2})/);
// if (match) {
// shippingFee = match[1];
// console.log('找到快递费用: ¥' + shippingFee);
// }
// }
// // 匹配格式2: 快递:包邮
// else if (element.textContent.includes('快递:包邮') || element.textContent.includes('快递:包邮')) {
// shippingFee = '包邮';
// console.log('找到快递费用: 包邮');
// }
// // 匹配格式3: 快递 包邮 (包含空格变体)
// else if (element.textContent.match(/快递[:\s]包邮/)) {
// shippingFee = '包邮';
// console.log('找到快递费用: 包邮');
// }
// });
//
// if (!shippingFee) {
// // 如果没找到,尝试搜索整个页面
// const pageText = document.body.innerText;
// const match = pageText.match(/快递¥(\d+\.\d{2})/);
// if (match) {
// shippingFee = match[1];
// console.log('找到快递费用: ¥' + shippingFee);
// }
// // 尝试匹配包邮
// else if (pageText.match(/快递[:\s]包邮/)) {
// shippingFee = '包邮';
// console.log('找到快递费用: 包邮');
// }
// // 尝试其他包邮表述
// else if (pageText.includes('包邮') && pageText.includes('快递')) {
// shippingFee = '包邮';
// console.log('找到快递费用: 包邮');
// }
// else {
// console.log('未找到快递费用信息');
// }
// }
// return shippingFee;
// })();`
// // 先导航到页面并等待完全加载
// err := chromedp.Run(ctx,
// // 导航到目标页面
// chromedp.Navigate(url),
// // 刷新页面,重新加载动态内容
// chromedp.Reload(),
// // 等待刷新后页面加载
// chromedp.WaitReady("body", chromedp.ByQuery),
// chromedp.Sleep(8*time.Second),
// // 执行 JavaScript 来提取商品信息
// chromedp.Evaluate(enhancedJSScript, &result),
// )
// if err != nil {
// log.Printf("[CHROMEDP] 页面导航失败: %v", err)
// return "", fmt.Errorf("页面导航失败: %v", err)
// }
// log.Printf("[CHROMEDP] 页面导航完成,开始提取数据")
//
// if err != nil {
// return "", fmt.Errorf("chromedp执行失败: %v", err)
// }
// return result, nil
//}
//
//// 获取孔网实拍图(查询商品列表)
//func getKFZSPTImageURL(proxyType, username, password, machineCode, isbn string) (*BookInfo, error) {
// url := fmt.Sprintf("%s?dataType=0&keyword=%s&page=1&size=%d&sortType=7&actionPath=quality,sortType&quality=85~&quaSelect=2&userArea=13003000000", cf.API.ProductSearchURL, isbn, cf.App.Size)
//
// req := XxProxyRequest(proxyType, username, password, machineCode).
// Get(url).
// Set("User-Agent", cf.App.DefaultUserAgent).
// Set("Accept", "*/*")
// resp, body, errs := req.End()
// log.Printf("[DEBUG] 获取图书列表 URL: %s", url)
//
// // 只在有响应内容时才打印,避免日志过长
// if len(body) > 0 && len(body) < 500 {
// log.Printf("[DEBUG] 获取图书列表响应: %s", body)
// } else if len(body) > 0 {
// log.Printf("[DEBUG] 获取图书列表响应长度: %d 字符", len(body))
// } else {
// log.Printf("[DEBUG] 获取图书列表响应为空")
// }
//
// // 处理请求错误
// if len(errs) > 0 {
// // 检查是否是代理认证失败
// var proxyAuthFailed bool
// for _, e := range errs {
// if strings.Contains(e.Error(), "Proxy Authentication Required") {
// proxyAuthFailed = true
// break
// }
// }
// if proxyAuthFailed {
// return nil, fmt.Errorf("代理认证失败")
// }
// return nil, fmt.Errorf("查询请求失败: %v", errs)
// }
//
// // 检查HTTP状态码
// if resp.StatusCode != http.StatusOK {
// space := strings.TrimSpace(resp.Status)
// return nil, fmt.Errorf("HTTP错误: %s", space)
// }
//
// // 解析响应
// var apiResp struct {
// Status int `json:"status"`
// ErrType string `json:"errType"`
// Message string `json:"message"`
// SystemTime int64 `json:"systemTime"`
// Data struct {
// ItemResponse struct {
// Total int `json:"total"`
// List []struct {
// Title string `json:"title"`
// ImgUrl string `json:"imgUrl"`
// ImgBigUrl string `json:"imgBigUrl"`
// ItemId int64 `json:"itemId"`
// ShopId int64 `json:"shopId"`
// TplRecords []struct {
// Key string `json:"key"`
// Value string `json:"value"`
// } `json:"tplRecords"`
// } `json:"list"`
// } `json:"itemResponse"`
// } `json:"data"`
// }
//
// if err := json.Unmarshal([]byte(body), &apiResp); err != nil {
// return nil, fmt.Errorf("解析JSON失败: %w", err)
// }
//
// // 如果找到商品返回图片URL
// if apiResp.Data.ItemResponse.Total > 0 && len(apiResp.Data.ItemResponse.List) > 0 {
// // 确定起始索引
// var startIndex int
// if cf.App.Size >= apiResp.Data.ItemResponse.Total {
// startIndex = apiResp.Data.ItemResponse.Total - 1
// } else {
// startIndex = cf.App.Size - 1
// }
//
// // 从指定索引开始向前查找有效图片最多重试3次
// for attempt := 0; attempt < 3; attempt++ {
// currentIndex := startIndex - attempt
//
// // 检查索引是否有效
// if currentIndex < 0 || currentIndex >= len(apiResp.Data.ItemResponse.List) {
// log.Printf("[DEBUG] 索引 %d 超出范围,跳过", currentIndex)
// continue
// }
//
// item := apiResp.Data.ItemResponse.List[currentIndex]
//
// // 检查图片URL是否存在
// if item.ImgBigUrl == "" {
// log.Printf("[DEBUG] 索引 %d 的图片URL为空跳过", currentIndex)
// continue
// }
//
// info := &BookInfo{}
// info.BookName = item.Title
// info.BookPicS = item.ImgUrl
// info.ItemId = item.ItemId
// info.ShopId = item.ShopId
//
// // 安全地获取TplRecords中的值
// if len(item.TplRecords) > 0 {
// info.Author = item.TplRecords[0].Value
// }
// if len(item.TplRecords) > 1 {
// info.Publisher = item.TplRecords[1].Value
// }
// if len(item.TplRecords) > 2 {
// info.PublicationTime = validateDateFormat(item.TplRecords[2].Value)
// }
// if len(item.TplRecords) > 3 {
// info.BindingLayout = item.TplRecords[3].Value
// }
//
// // 成功时重置代理失败计数器
// resetProxyFailCount()
// return info, nil
// }
// // 如果所有尝试都失败了,返回错误
// log.Printf("[WARN] 经过3次尝试未找到有效图片")
// return nil, fmt.Errorf("未找到有效图片已尝试3次")
// }
// return nil, nil
//}
//
//// 获取孔网官图(查询图书条目)
//func getKFZGTImageURL(proxyType, username, password, machineCode, isbn string) (*BookInfo, error) {
// url := fmt.Sprintf("%s?keyword=%s", cf.API.BookSearchURL, isbn)
//
// info := &BookInfo{}
//
// req := XxProxyRequest(proxyType, username, password, machineCode).
// Get(url).
// Set("User-Agent", cf.App.DefaultUserAgent).
// Set("Accept", "*/*")
// resp, body, errs := req.End()
// log.Printf("[DEBUG] 获取图书条目 URL: %s", url)
//
// // 只在有响应内容时才打印,避免日志过长
// if len(body) > 0 && len(body) < 500 {
// log.Printf("[DEBUG] 获取图书条目响应: %s", body)
// } else if len(body) > 0 {
// log.Printf("[DEBUG] 获取图书条目响应长度: %d 字符", len(body))
// } else {
// log.Printf("[DEBUG] 获取图书条目响应为空")
// }
//
// // 处理请求错误
// if len(errs) > 0 {
// // 检查是否是代理相关错误
// var isProxyError bool
// var errorDetails []string
// for _, e := range errs {
// errorStr := e.Error()
// errorDetails = append(errorDetails, errorStr)
// if strings.Contains(errorStr, "Proxy Authentication Required") ||
// strings.Contains(errorStr, "connectex: A connection attempt failed") ||
// strings.Contains(errorStr, "connectex: No connection could be made") ||
// strings.Contains(errorStr, "proxyconnect tcp") ||
// strings.Contains(errorStr, "timeout") ||
// strings.Contains(errorStr, "connection refused") {
// isProxyError = true
// }
// }
//
// log.Printf("[ERROR] 请求错误详情: %v", errorDetails)
//
// if isProxyError {
// // 处理代理失败
// return nil, fmt.Errorf("代理连接失败")
// }
//
// return nil, fmt.Errorf("查询请求失败: %v", errs)
// }
//
// //检查HTTP状态码
// if resp.StatusCode != http.StatusOK {
// space := strings.TrimSpace(resp.Status)
// return nil, fmt.Errorf("HTTP错误: %s", space)
// }
//
// // 解析响应
// var apiResp struct {
// Status int `json:"status"`
// ErrType string `json:"errType"`
// Message string `json:"message"`
// SystemTime int64 `json:"systemTime"`
// Data struct {
// ItemResponse struct {
// Total int `json:"total"`
// List []struct {
// BookName string `json:"bookName"`
// Mid int64 `json:"mid"`
// ImgUrlEntity struct {
// BigImgUrl string `json:"bigImgUrl"`
// } `json:"imgUrlEntity"`
// BookShowInfo []string `json:"bookShowInfo"`
// } `json:"list"`
// } `json:"itemResponse"`
// } `json:"data"`
// }
//
// if err := json.Unmarshal([]byte(body), &apiResp); err != nil {
// return nil, fmt.Errorf("解析JSON失败: %w", err)
// }
//
// // 如果找到条目返回图片URL
// if apiResp.Data.ItemResponse.Total > 0 && len(apiResp.Data.ItemResponse.List) > 0 {
// list := apiResp.Data.ItemResponse.List[0]
// info := list.BookShowInfo
//
// bookItem := &BookInfo{
// BookName: list.BookName,
// BookPic: list.ImgUrlEntity.BigImgUrl,
// Mid: list.Mid,
// }
//
// // 根据长度安全填充字段
// if len(info) > 0 {
// bookItem.Author = info[0]
// }
// if len(info) > 1 {
// bookItem.Publisher = info[1]
// }
// if len(info) > 2 {
// bookItem.PublicationTime = validateDateFormat(info[2])
// }
// if len(info) > 3 {
// bookItem.BindingLayout = info[3]
// }
// if len(info) > 4 {
// bookItem.FixPrice = info[4]
// } else {
// log.Printf("[WARN] BookShowInfo 长度不足 (仅 %d 项): %v", len(info), info)
// }
//
// fmt.Println("bookItem: ", bookItem)
// return bookItem, nil
// }
//
// return info, nil
//}
//
//// 替换所有空白字符为空格
//func cleanString(s string) string {
// s = strings.ReplaceAll(s, "\n", "")
// s = strings.ReplaceAll(s, "\r", "")
// s = strings.ReplaceAll(s, "\t", "")
// s = strings.ReplaceAll(s, " ", "")
// return removeDuplicates(s)
//}
//
//// 字符串去重
//func removeDuplicates(s string) string {
// seen := make(map[rune]bool)
// var result strings.Builder
// for _, r := range s {
// if !seen[r] {
// seen[r] = true
// result.WriteRune(r)
// }
// }
// return result.String()
//}
//
//// 检测快递费用格式
//func extractShippingInfo(shippingFee string) string {
// // 匹配 "快递¥数字" 格式
// re1 := regexp.MustCompile(`快递¥(\d+\.?\d*)`)
// // 匹配 "包邮" 格式
// re2 := regexp.MustCompile(`(包邮)`)
//
// if matches := re1.FindStringSubmatch(shippingFee); len(matches) > 1 {
// return matches[1] // 返回数字部分
// }
//
// if matches := re2.FindStringSubmatch(shippingFee); len(matches) > 1 {
// return "0" // 返回"包邮"
// }
//
// return ""
//}
//
//// 改进字段
//func extractNormalDetails(s *goquery.Selection, fieldName string) string {
// var info string
// s.Each(func(i int, selection *goquery.Selection) {
// if strings.Contains(selection.Text(), fieldName) {
// all := strings.ReplaceAll(selection.Text(), "&nbsp;", "")
// all = strings.ReplaceAll(all, "\n", "")
// all = strings.ReplaceAll(all, " ", "")
// split := strings.SplitN(all, ":", 2)
// if len(split) > 1 {
// info = split[1]
// } else {
// return
// }
// }
// })
// return info
//}
//
//// 改进的字段提取函数
//func extractNormalText(s *goquery.Selection, fieldName string) string {
// // 在左右两个分区中查找
// selectors := []string{"div.f_left", "div.f_right"}
// for _, selector := range selectors {
// fieldItem := s.Find(selector + " div.normal-item").FilterFunction(func(i int, sel *goquery.Selection) bool {
// title := sel.Find("span.normal-title").Text()
// return strings.Contains(title, fieldName)
// })
//
// if fieldItem.Length() > 0 {
// text := fieldItem.Find("span.normal-text").Text()
// return strings.TrimSpace(text)
// }
// }
// return ""
//}
//
//// 重置代理失败计数器(成功时调用)
//func resetProxyFailCount() {
// tailProxyMu.Lock()
// defer tailProxyMu.Unlock()
// proxyFailCount = 0
//}
//
//// 验证日期格式
//func validateDateFormat(dateStr string) int64 {
// // 去除前后空格
// dateStr = strings.TrimSpace(dateStr)
//
// // 替换各种分隔符为统一的分隔符"-"
// dateStr = regexp.MustCompile(`[/_\\.,\s]+`).ReplaceAllString(dateStr, "-")
//
// // 处理纯年份格式 (4位数字)
// if regexp.MustCompile(`^\d{4}$`).MatchString(dateStr) {
// dateStr += "-01-01"
// }
//
// // 处理年月格式 (4位数字-1或2位数字)
// if matches := regexp.MustCompile(`^(\d{4})-(\d{1,2})$`).FindStringSubmatch(dateStr); len(matches) == 3 {
// year := matches[1]
// month := matches[2]
// if len(month) == 1 {
// month = "0" + month
// }
// if monthNum, _ := strconv.Atoi(month); monthNum >= 1 && monthNum <= 12 {
// dateStr = year + "-" + month + "-01"
// } else {
// return 0
// }
// }
//
// // 处理年月日格式 (4位数字-1或2位数字-1或2位数字)
// if matches := regexp.MustCompile(`^(\d{4})-(\d{1,2})-(\d{1,2})`).FindStringSubmatch(dateStr); len(matches) >= 4 {
// year := matches[1]
// month := matches[2]
// day := matches[3]
//
// // 标准化月份和日期为两位数
// if len(month) == 1 {
// month = "0" + month
// }
// if len(day) == 1 {
// day = "0" + day
// }
//
// dateStr = year + "-" + month + "-" + day
// }
//
// // 加载上海时区
// loc, err := time.LoadLocation("Asia/Shanghai")
// if err != nil {
// // 如果加载时区失败使用UTC+8作为后备方案
// loc = time.FixedZone("CST", 8*60*60)
// }
//
// // 尝试解析为标准日期格式,并指定上海时区
// parsedTime, err := time.ParseInLocation("2006-01-02", dateStr, loc)
// if err != nil {
// return 0
// }
//
// // 返回秒级时间戳UTC时间但解析时已经考虑了时区偏移
// return parsedTime.Unix()
//}
//
//// 代理请求(小象代理)
//func XxProxyRequest(proxyType, username, password, machineCode string) *gorequest.SuperAgent {
// proxyManagerOnce.Do(func() {
// log.Printf("[INFO] 初始化代理管理器DLL路径: %s", cf.Proxy.ProxyFilePath)
//
// // 检查DLL文件是否存在
// if _, err := os.Stat(cf.Proxy.ProxyFilePath); os.IsNotExist(err) {
// // 尝试在可执行文件目录查找
// exePath, _ := os.Executable()
// exeDir := filepath.Dir(exePath)
// dllPath := filepath.Join(exeDir, cf.Proxy.ProxyFilePath)
//
// if _, err := os.Stat(dllPath); err == nil {
// cf.Proxy.ProxyFilePath = dllPath
// } else {
// proxyManagerInitErr = fmt.Errorf("代理DLL文件不存在: %s (也尝试了: %s)", cf.Proxy.ProxyFilePath, dllPath)
// return
// }
// }
//
// globalProxyManager, proxyManagerInitErr = NewProxyConfigManager(cf.Proxy.ProxyFilePath)
// if proxyManagerInitErr != nil {
// log.Printf("[ERROR] 代理管理器初始化失败: %v", proxyManagerInitErr)
// } else {
// log.Printf("[INFO] 代理管理器初始化成功")
// }
// })
// typeManager, err := globalProxyManager.ProxyTypeManager(
// proxyType,
// username,
// password,
// machineCode,
// )
// if err != nil {
// fmt.Printf("获取代理服务器信息失败: %v", err)
// }
// return gorequest.New().Proxy(typeManager).Timeout(120*time.Second).Retry(2, 3*time.Second)
//}
//
//// 初始化
//func initializeConfig(config Config) {
// // 设置全局配置
// cf = config
//}
//
////export GetKFZShopBookInfo
//func GetKFZShopBookInfo(fetchMode, proxyType, username, password, machineCode, shopId, isImage, bookNum, pageNum, sortType, sort, priceDown, priceUp *C.char) *C.char {
// fetchModeStr := C.GoString(fetchMode)
// proxyTypeStr := C.GoString(proxyType)
// usernameStr := C.GoString(username)
// passwordStr := C.GoString(password)
// machineCodeStr := C.GoString(machineCode)
// shopIdStr := C.GoString(shopId)
// isImageStr := C.GoString(isImage)
// bookNumStr := C.GoString(bookNum)
// pageNumStr := C.GoString(pageNum)
// sortTypeStr := C.GoString(sortType)
// sortStr := C.GoString(sort)
// priceDownStr := C.GoString(priceDown)
// priceUpStr := C.GoString(priceUp)
//
// books, goodsNum, pNum, err := getKFZShopBookInfo(fetchModeStr, proxyTypeStr, usernameStr, passwordStr, machineCodeStr, shopIdStr, isImageStr, bookNumStr, pageNumStr, sortTypeStr, sortStr, priceDownStr, priceUpStr)
// if err != nil {
// result := map[string]interface{}{
// "success": false,
// "error": err.Error(),
// }
// jsonData, _ := json.Marshal(result)
// return C.CString(string(jsonData))
// }
//
// jsonData, err := json.Marshal(APIResponse{
// Success: true,
// Message: "查询成功",
// GoodsNum: goodsNum,
// PNum: pNum,
// Data: books,
// })
// if err != nil {
// errorResult := map[string]interface{}{
// "success": false,
// "error": err.Error(),
// }
// errorJson, _ := json.Marshal(errorResult)
// return C.CString(string(errorJson))
// }
//
// return C.CString(string(jsonData))
//}
//
////export GetUrlBookDetails
//func GetUrlBookDetails(fetchMode, proxyType, username, password, machineCode, url *C.char) *C.char {
// fetchModeStr := C.GoString(fetchMode)
// proxyTypeStr := C.GoString(proxyType)
// usernameStr := C.GoString(username)
// passwordStr := C.GoString(password)
// machineCodeStr := C.GoString(machineCode)
// urlStr := C.GoString(url)
// books, err := getUrlBookDetails(fetchModeStr, proxyTypeStr, usernameStr, passwordStr, machineCodeStr, urlStr)
// if err != nil {
// result := map[string]interface{}{
// "success": false,
// "error": err.Error(),
// }
// jsonData, _ := json.Marshal(result)
// return C.CString(string(jsonData))
// }
// jsonData, err := json.Marshal(APIResponse{
// Success: true,
// Message: "查询成功",
// Data: books,
// })
// if err != nil {
// errorResult := map[string]interface{}{
// "success": false,
// "error": err.Error(),
// }
// errorJson, _ := json.Marshal(errorResult)
// return C.CString(string(errorJson))
// }
// return C.CString(string(jsonData))
//}
//
////export GetKFZSPTImageURL
//func GetKFZSPTImageURL(proxyType, username, password, machineCode, isbn *C.char) *C.char {
// proxyTypeStr := C.GoString(proxyType)
// usernameStr := C.GoString(username)
// passwordStr := C.GoString(password)
// machineCodeStr := C.GoString(machineCode)
// isbnStr := C.GoString(isbn)
//
// bookInfo, err := getKFZSPTImageURL(proxyTypeStr, usernameStr, passwordStr, machineCodeStr, isbnStr)
// if err != nil {
// result := map[string]interface{}{
// "success": false,
// "error": err.Error(),
// }
// jsonData, _ := json.Marshal(result)
// return C.CString(string(jsonData))
// }
//
// result := map[string]interface{}{
// "success": true,
// "bookInfo": bookInfo,
// }
// jsonData, err := json.Marshal(result)
// if err != nil {
// errorResult := map[string]interface{}{
// "success": false,
// "error": err.Error(),
// }
// errorJson, _ := json.Marshal(errorResult)
// return C.CString(string(errorJson))
// }
// return C.CString(string(jsonData))
//}
//
////export GetKFZGTImageURL
//func GetKFZGTImageURL(proxyType, username, password, machineCode, isbn *C.char) *C.char {
// proxyTypeStr := C.GoString(proxyType)
// usernameStr := C.GoString(username)
// passwordStr := C.GoString(password)
// machineCodeStr := C.GoString(machineCode)
// isbnStr := C.GoString(isbn)
//
// bookInfo, err := getKFZGTImageURL(proxyTypeStr, usernameStr, passwordStr, machineCodeStr, isbnStr)
// if err != nil {
// result := map[string]interface{}{
// "success": false,
// "error": err.Error(),
// }
// jsonData, _ := json.Marshal(result)
// return C.CString(string(jsonData))
// }
//
// result := map[string]interface{}{
// "success": true,
// "bookInfo": bookInfo,
// }
// jsonData, err := json.Marshal(result)
// if err != nil {
// errorResult := map[string]interface{}{
// "success": false,
// "error": err.Error(),
// }
// errorJson, _ := json.Marshal(errorResult)
// return C.CString(string(errorJson))
// }
//
// return C.CString(string(jsonData))
//}
//
////export Initialize
//func Initialize(configJSON *C.char) *C.char {
// configStr := C.GoString(configJSON)
// log.Printf("[DEBUG] 接收到的配置JSON: %s", configStr)
//
// var config Config
// if err := json.Unmarshal([]byte(configStr), &config); err != nil {
// return C.CString(fmt.Sprintf(`{"success":false,"message":"配置解析失败: %v"}`, err))
// }
// initializeConfig(config)
//
// return C.CString(`{"success":true,"message":"初始化成功"}`)
//}
//
//// 导出函数释放C字符串内存
////
////export FreeCString
//func FreeCString(str *C.char) {
// C.free(unsafe.Pointer(str))
//}
//
//// 空main函数编译DLL时需要
//func main() {
//
//}