daShangDao_kfzgw-info/main_so.go

3332 lines
110 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
///*
//#cgo LDFLAGS: -ldl
//
//#include <dlfcn.h>
//#include <stdlib.h>
//#include <stdio.h>
//*/
//import "C"
//import (
// "context"
// "database/sql"
// "encoding/json"
// "fmt"
// "io"
// "log"
// "math/rand"
// "net/http"
// "net/url"
// "os"
// "path/filepath"
// "regexp"
// "strconv"
// "strings"
// "sync"
// "time"
// "unsafe"
//
// "github.com/PuerkitoBio/goquery"
// "github.com/chromedp/chromedp"
// _ "github.com/go-sql-driver/mysql"
// "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"`
//
// Database struct {
// Username string `ini:"database.username" json:"username" default:"newAdmin"`
// Password string `ini:"database.password" json:"password" default:"bYPp8SbBe5F7nz2i"`
// Host string `ini:"database.host" json:"host" default:"146.56.227.42:3306"`
// Name string `ini:"database.name" json:"name" default:"newadmin"`
// } `ini:"database" json:"database"`
//}
//
//// 条目详情结构体
//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
// DetailUrl string `json:"detail_url"` // 商品详情url
//}
//
//// API响应结构
//type APIResp 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"`
//}
//
//// APIResponse
//type APIResponse struct {
// Success bool `json:"success"`
// Message string `json:"message,omitempty"`
// Data interface{} `json:"data,omitempty"`
//}
//
//// 账号凭证结构
//type AccountCredential struct {
// ID int64
// Username string
// Password string
// Token string
//}
//
//// 全局变量
//var (
// cf Config // 配置信息
// tailProxyMu sync.Mutex // 互斥锁
// proxyFailCount int
// mu sync.RWMutex // 数据库锁
//
// // 全局代理管理器
// 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 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"`
//}
//
//type UserInfo struct {
// UserID int64 `json:"userId"`
// Nickname string `json:"nickname"`
// Mobile string `json:"mobile"`
//}
//
//// 店铺快递费参数
//type ParamsInfo struct {
// Params []Param `json:"params"`
// Area string `json:"area"`
//}
//
//type Param struct {
// UserId string `json:"userId"`
// ItemId string `json:"itemId"`
//}
//
//// ProxyConfigManager 代理配置SO管理器
//type ProxyConfigManager struct {
// handle unsafe.Pointer
//}
//
//func NewProxyConfigManager(soPath string) (*ProxyConfigManager, error) {
// cSoPath := C.CString(soPath)
// defer C.free(unsafe.Pointer(cSoPath))
//
// handle := C.dlopen(cSoPath, C.RTLD_LAZY)
// if handle == nil {
// err := C.dlerror()
// if err != nil {
// return nil, fmt.Errorf("加载代理配置SO失败: %s", C.GoString(err))
// }
// return nil, fmt.Errorf("加载代理配置SO失败: 未知错误")
// }
// return &ProxyConfigManager{handle: handle}, nil
//}
//
//func (m *ProxyConfigManager) Close() {
// if m.handle != nil {
// C.dlclose(m.handle)
// m.handle = nil
// }
//}
//
//// ProxyTypeManager 调用代理类型管理器
//func (m *ProxyConfigManager) ProxyTypeManager(proxyType, username, password, machineCode string) (string, error) {
// // 查找 ProxyTypeManager 函数
// cFuncName := C.CString("ProxyTypeManager")
// defer C.free(unsafe.Pointer(cFuncName))
//
// proc := C.dlsym(m.handle, cFuncName)
// if proc == nil {
// err := C.dlerror()
// if err != nil {
// return "", fmt.Errorf("找不到函数 ProxyTypeManager: %s", C.GoString(err))
// }
// return "", fmt.Errorf("找不到函数 ProxyTypeManager")
// }
//
// // 准备参数
// cProxyType := C.CString(proxyType)
// cUsername := C.CString(username)
// cPassword := C.CString(password)
// cMachineCode := C.CString(machineCode)
// defer func() {
// C.free(unsafe.Pointer(cProxyType))
// C.free(unsafe.Pointer(cUsername))
// C.free(unsafe.Pointer(cPassword))
// C.free(unsafe.Pointer(cMachineCode))
// }()
//
// // 定义函数类型
// type ProxyTypeManagerFunc func(proxyType, username, password, machineCode *C.char) *C.char
//
// // 转换函数指针
// proxyFunc := *(*ProxyTypeManagerFunc)(unsafe.Pointer(&proc))
//
// // 调用函数
// result := proxyFunc(cProxyType, cUsername, cPassword, cMachineCode)
// if result == nil {
// return "", fmt.Errorf("ProxyTypeManager 返回空结果")
// }
//
// goResult := C.GoString(result)
//
// // 查找并调用 FreeCString 函数
// cFreeName := C.CString("FreeCString")
// defer C.free(unsafe.Pointer(cFreeName))
//
// freeProc := C.dlsym(m.handle, cFreeName)
// if freeProc != nil {
// type FreeCStringFunc func(str *C.char)
// freeFunc := *(*FreeCStringFunc)(unsafe.Pointer(&freeProc))
// freeFunc(result)
// } else {
// // 如果找不到 FreeCString使用 C.free
// C.free(unsafe.Pointer(result))
// }
//
// return goResult, nil
//}
//
//// 登录
//func outLogin(username, password string) (string, error) {
// if username == "" || password == "" {
// return "", fmt.Errorf("请输入用户名和密码!")
// }
// formData := map[string]string{
// "loginName": username,
// "loginPass": password,
// "returnUrl": "http://user.kongfz.com/",
// }
// resp, body, errs := gorequest.New().
// Post(cf.API.LoginURL).
// Set("Content-Type", "application/x-www-form-urlencoded").
// Set("User-Agent", cf.App.DefaultUserAgent).
// Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8").
// Send(formData).
// Timeout(15 * time.Second).End()
// if len(errs) > 0 {
// return "", fmt.Errorf("登录请求失败: %v", errs)
// }
// // 检查HTTP状态码
// if resp.StatusCode != http.StatusOK {
// return "", fmt.Errorf("登录失败(HTTP状态码: %d)", resp.StatusCode)
// }
// // 提取Cookie
// cookie := resp.Header.Get("Set-Cookie")
// if strings.Contains(body, "window.location.href='https://login.kongfz.cn/Pc/Session/rsync") {
// if cookie == "" {
// return "", fmt.Errorf("登录成功但未获取到Cookie")
// }
// // 登录成功
// if strings.Contains(cookie, "PHPSESSID=") {
// token := strings.Split(strings.Split(cookie, "PHPSESSID=")[1], ";")[0]
// return token, nil
// }
// return "", fmt.Errorf("登录失败: 未找到PHPSESSID")
// }
// // 错误信息
// var res struct {
// Status bool `json:"status"`
// ErrCode int `json:"errCode"`
// ErrInfo string `json:"errInfo"`
// }
// if err := json.Unmarshal([]byte(body), &res); err == nil {
// if res.ErrCode == 1001 || res.ErrCode == 1005 {
// return "", fmt.Errorf("账号或密码错误!")
// }
// if res.ErrInfo != "" {
// return "", fmt.Errorf("登录失败: %s", res.ErrInfo)
// }
// }
// return "", fmt.Errorf("登录失败,未知错误!")
//}
//
//// 获取用户信息(带有Out的都非官方标准接口)
//func outGetUserMsg(token string) (*UserInfo, error) {
// url := "https://user.kongfz.com/User/Index/getUserInfo/"
// resp, body, errs := gorequest.New().
// Get(url).
// Set("Cookie", fmt.Sprintf("PHPSESSID=%s", token)).
// 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").
// Set("Accept", "application/json, text/plain, */*").
// Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
// Timeout(15 * time.Second).
// End()
// if len(errs) > 0 {
// return nil, fmt.Errorf("查询请求失败: %v", errs)
// }
// //检查HTTP状态码
// if resp.StatusCode != http.StatusOK {
// return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
// }
// var userInfo struct {
// Status bool `json:"status"`
// Data struct {
// UserID int64 `json:"userId"`
// Nickname string `json:"nickname"`
// Mobile string `json:"mobile"`
// }
// }
// if err := json.Unmarshal([]byte(body), &userInfo); err != nil {
// return nil, fmt.Errorf("解析JSON失败: %w", err)
// }
// user := &UserInfo{}
// if !userInfo.Status {
// return nil, fmt.Errorf("获取用户失败!")
// }
// user.UserID = userInfo.Data.UserID
// user.Nickname = userInfo.Data.Nickname
// user.Mobile = userInfo.Data.Mobile
// return user, nil
//}
//
//// 获取商品模版
//func outGetGoodsTplMsg(token, itemId, proxy string) (map[string]interface{}, error) {
// if token == "" {
// return nil, fmt.Errorf("请先登录获取Token")
// }
// url := fmt.Sprintf("https://seller.kongfz.com/pc/itemInfo/getTplFields?itemId=%s&isClone=1&v=%d",
// itemId, time.Now().Unix())
// // 创建HTTP客户端
// request := gorequest.New()
// // 设置代理如果有提供代理URL
// if proxy != "" {
// request.Proxy(proxy)
// }
// resp, body, errs := request.Get(url).
// Set("Cookie", fmt.Sprintf("PHPSESSID=%s", token)).
// 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").
// Set("Accept", "application/json, text/plain, */*").
// Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
// Set("Referer", "https://seller.kongfz.com/").
// Set("Origin", "https://seller.kongfz.com").
// Timeout(15 * time.Second).
// End()
// if errs != nil {
// // 检查是否是代理相关错误
// 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 {
// return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
// }
// var data map[string]interface{}
// if err := json.Unmarshal([]byte(body), &data); err != nil {
// return nil, fmt.Errorf("解析JSON失败: %w", err)
// }
// if val, ok := data["status"].(float64); ok && val == 1 {
// return data, nil
// }
// return nil, fmt.Errorf("API返回错误: %+v", data)
//}
//
//// 获取商品列表
//func outGetGoodsListMsgFromSelfShop(token string, proxy string, itemSn string, priceMin string, priceMax string, startCreateTime int,
// endCreateTime int, requestType string, isItemSnEqual int, page int, size int) (map[string]interface{}, error) {
// if token == "" {
// return nil, fmt.Errorf("请先登录获取Token")
// }
// url := "https://seller.kongfz.com/pc-gw/book-manage-service/client/pc/goods/unSold/list"
// formData := struct {
// ItemSn string `json:"itemSn"`
// PriceMin string `json:"priceMin"`
// PriceMax string `json:"priceMax"`
// StartCreateTime int `json:"startCreateTime"`
// EndCreateTime int `json:"endCreateTime"`
// RequestType string `json:"requestType,omitempty"`
// IsItemSnEqual int `json:"isItemSnEqual,omitempty"`
// Page int `json:"page,omitempty"`
// Size int `json:"size,omitempty"`
// }{
// ItemSn: itemSn,
// PriceMin: priceMin,
// PriceMax: priceMax,
// StartCreateTime: startCreateTime,
// EndCreateTime: endCreateTime,
// RequestType: requestType,
// IsItemSnEqual: isItemSnEqual,
// Page: page,
// Size: size,
// }
// request := gorequest.New()
// if proxy != "" {
// request.Proxy(proxy)
// }
// resp, body, errs := request.Post(url).
// Set("Cookie", fmt.Sprintf("PHPSESSID=%s", token)).
// 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").
// Set("Accept", "application/json, text/plain, */*").
// Send(formData).
// Timeout(15 * time.Second).
// End()
// if errs != nil {
// // 检查是否是代理相关错误
// 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 {
// return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
// }
// var data map[string]interface{}
// if err := json.Unmarshal([]byte(body), &data); err != nil {
// return nil, fmt.Errorf("解析JSON失败: %w", err)
// }
// if _, ok := data["status"]; ok {
// return data, nil
// }
// return nil, fmt.Errorf("API返回错误: %+v", data)
//}
//
//// 删除商品-已登的店铺(带有Out的都非官方标准接口)
//func outDelGoodsFromSelfShop(token, proxy, itemId string) (map[string]interface{}, error) {
// if token == "" {
// return nil, fmt.Errorf("请先登录获取Token")
// }
// url := "https://seller.kongfz.com/pc-gw/book-manage-service/client/pc/goods/quickUpdate"
// formData := map[string]string{
// "itemId": itemId,
// "updateType": "delete",
// "value": "1",
// }
// request := gorequest.New()
// if proxy != "" {
// request.Proxy(proxy)
// }
// resp, body, errs := request.Post(url).
// Set("Cookie", fmt.Sprintf("PHPSESSID=%s", token)).
// 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").
// Set("Accept", "application/json, text/plain, */*").
// Send(formData).
// Timeout(15 * time.Second).
// End()
// if errs != nil {
// // 检查是否是代理相关错误
// 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 {
// return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
// }
// var data map[string]interface{}
// if err := json.Unmarshal([]byte(body), &data); err != nil {
// return nil, fmt.Errorf("解析JSON失败: %w", err)
// }
// if status, ok := data["status"].(bool); ok && status {
// return data, nil
// }
// if status, ok := data["status"].(float64); ok && status == 1 {
// return data, nil
// }
// return nil, fmt.Errorf("API返回错误: %+v", data)
//}
//
//// 新增商品(带有Out的都非官方标准接口)
//func outAddGoods(token, proxy, formData string) (map[string]interface{}, error) {
// if token == "" {
// return nil, fmt.Errorf("请先登录获取Token")
// }
// url := "https://seller.kongfz.com/pc/itemInfo/add"
// request := gorequest.New()
// if proxy != "" {
// request.Proxy(proxy)
// }
// resp, body, errs := request.Post(url).
// Set("Cookie", fmt.Sprintf("PHPSESSID=%s", token)).
// 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").
// Set("Accept", "application/json, text/plain, */*").
// Send(formData).
// Timeout(15 * time.Second).
// End()
// if errs != nil {
// // 检查是否是代理相关错误
// 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 {
// return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
// }
// var data map[string]interface{}
// if err := json.Unmarshal([]byte(body), &data); err != nil {
// return nil, fmt.Errorf("解析JSON失败: %w", err)
// }
// if val, ok := data["status"]; ok && val == 1 {
// return data, nil
// }
// return nil, fmt.Errorf("API返回错误: %+v", data)
//}
//
//// 获取图片URL(官图和拍图)带有店铺过滤
//func outGetImageFilterShopId(token string, isbn string, shopId int, proxy string, isLiveImage int, isReturnMsg int) (map[string]string, error) {
// fmt.Println("[DEBUG] 使用的ISBN: ", isbn)
// if isLiveImage == 0 {
// gtUrl := fmt.Sprintf("%s?keyword=%s", cf.API.BookSearchURL, isbn)
// request := gorequest.New()
// if proxy != "" {
// request.Proxy(proxy)
// }
// resp, body, errs := request.Get(gtUrl).
// Set("Cookie", fmt.Sprintf("PHPSESSID=%s", token)).
// 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").
// Set("Accept", "application/json, text/plain, */*").
// Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
// Set("Referer", "https://item.kongfz.com/").
// Timeout(30 * time.Second).
// End()
// 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 {
// return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
// }
// // 解析响应
// var apiGtResp 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"`
// Isbn string `json:"isbn"`
// BookShowInfo []string `json:"bookShowInfo"`
// } `json:"list"`
// } `json:"itemResponse"`
// } `json:"data"`
// }
// if err := json.Unmarshal([]byte(body), &apiGtResp); err != nil {
// return nil, fmt.Errorf("解析JSON失败: %w", err)
// }
// if apiGtResp.ErrType == "102" {
// return nil, fmt.Errorf("错误信息: %w状态码: %s", apiGtResp.Message, apiGtResp.ErrType)
// }
// var info map[string]string
// // 如果找到条目返回图片URL
// if apiGtResp.Data.ItemResponse.Total > 0 && len(apiGtResp.Data.ItemResponse.List) > 0 {
// list := apiGtResp.Data.ItemResponse.List[0]
// info = map[string]string{
// "book_name": list.BookName,
// "book_pic": list.ImgUrlEntity.BigImgUrl,
// "isbn": list.Isbn,
// }
// }
// return info, nil
// }
// if isLiveImage == 1 {
// // 实拍图
// sptUrl := 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)
// //创建HTTP客户端
// requestSpt := gorequest.New()
// //设置代理(如果有提供代理URL)
// if proxy != "" {
// requestSpt.Proxy(proxy)
// }
// // 发送请求
// respSpt, bodySpt, errsSpt := requestSpt.Get(sptUrl).
// Proxy(proxy).
// Set("Cookie", token).
// 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").
// Set("Accept", "application/json, text/plain, */*").
// Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
// Set("Referer", "https://item.kongfz.com/").
// Timeout(30 * time.Second).
// End()
// // 错误处理
// if len(errsSpt) > 0 {
// return nil, fmt.Errorf("请求失败: %v", errsSpt)
// }
// // 检查HTTP状态码
// if respSpt.StatusCode != http.StatusOK {
// return nil, fmt.Errorf("HTTP错误: %s", respSpt.Status)
// }
// // 解析响应
// var apiSptResp 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 {
// ItemId int64 `json:"itemId"`
// Title string `json:"title"`
// ImgUrl string `json:"imgUrl"`
// ImgBigUrl string `json:"imgBigUrl"`
// Author string `json:"author"`
// PubDateText string `json:"pubDateText"`
// Isbn string `json:"isbn"`
// Press string `json:"press"`
// ShopId int64 `json:"shopId"`
// TplRecords []struct {
// Key string `json:"key"`
// Value string `json:"value"`
// } `json:"tplRecords"`
// } `json:"list"`
// } `json:"itemResponse"`
// } `json:"data"`
// }
// // 解析JSON
// if err := json.Unmarshal([]byte(bodySpt), &apiSptResp); err != nil {
// return nil, fmt.Errorf("解析JSON失败: %w", err)
// }
// if apiSptResp.ErrType == "102" {
// return nil, fmt.Errorf("错误信息: %w状态码: %s", apiSptResp.Message, apiSptResp.ErrType)
// }
// var info map[string]string
// if apiSptResp.Data.ItemResponse.Total > 0 && len(apiSptResp.Data.ItemResponse.List) > 0 {
// // 确定起始索引
// var startIndex int
// if cf.App.Size >= apiSptResp.Data.ItemResponse.Total {
// startIndex = apiSptResp.Data.ItemResponse.Total - 1
// } else {
// startIndex = cf.App.Size - 1
// }
// for attempt := 0; attempt < 3; attempt++ {
// currentIndex := startIndex - attempt
// // 检查索引是否有效
// if currentIndex < 0 || currentIndex >= len(apiSptResp.Data.ItemResponse.List) {
// log.Printf("[DEBUG] 索引 %d 超出范围,跳过", currentIndex)
// continue
// }
// randomNum := rand.Intn(currentIndex + 1)
// item := apiSptResp.Data.ItemResponse.List[randomNum]
// // 检查图片URL是否存在
// if item.ImgBigUrl == "" {
// log.Printf("[DEBUG] 索引 %d 的图片URL为空跳过", randomNum)
// continue
// }
// // 过滤店铺
// if item.ShopId == int64(shopId) {
// log.Printf("[DEBUG] 索引 %d 的店铺ID需要过滤跳过", randomNum)
// continue
// }
// info = map[string]string{
// "book_name": item.Title,
// "book_pic": item.ImgUrl,
// "isbn": item.Isbn,
// }
// return info, nil
// }
// }
// }
// return nil, nil
//}
//
//// 获取图片URL(官图和拍图)
//func outGetImageByIsbn(token string, isbn string, proxy string, isLiveImage int, isReturnMsg int) (*BookInfo, error) {
// fmt.Println("[DEBUG] 使用的ISBN: ", isbn)
// // isLiveImage 1实拍图 0官图 isReturnMsg 0商品信息
// bookInfo := &BookInfo{}
// if isLiveImage == 0 {
// // 孔网官图请求
// gtUrl := fmt.Sprintf("%s?keyword=%s", cf.API.BookSearchURL, isbn)
// // 创建HTTP客户端
// requestGt := gorequest.New()
// // 设置代理(如果有提供代理URL)
// if proxy != "" {
// requestGt.Proxy(proxy)
// }
// // 发送请求
// respGt, bodyGt, errsGt := requestGt.Get(gtUrl).
// Set("Cookie", fmt.Sprintf("PHPSESSID=%s", token)).
// 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").
// Set("Accept", "application/json, text/plain, */*").
// Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
// Set("Referer", "https://item.kongfz.com/").
// Timeout(30 * time.Second).
// End()
// if len(errsGt) > 0 {
// // 检查是否是代理相关错误
// var isProxyError bool
// var errorDetails []string
// for _, e := range errsGt {
// 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", errsGt)
// }
// //检查HTTP状态码
// if respGt.StatusCode != http.StatusOK {
// return nil, fmt.Errorf("HTTP错误: %s", respGt.Status)
// }
// // 解析响应
// var apiGtResp 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"`
// Isbn string `json:"isbn"`
// BookShowInfo []string `json:"bookShowInfo"`
// } `json:"list"`
// } `json:"itemResponse"`
// } `json:"data"`
// }
// if err := json.Unmarshal([]byte(bodyGt), &apiGtResp); err != nil {
// return nil, fmt.Errorf("解析JSON失败: %w", err)
// }
// if apiGtResp.ErrType == "102" {
// return nil, fmt.Errorf("错误信息: %w状态码: %s", apiGtResp.Message, apiGtResp.ErrType)
// }
// // 如果找到条目返回图片URL
// if apiGtResp.Data.ItemResponse.Total > 0 && len(apiGtResp.Data.ItemResponse.List) > 0 {
// list := apiGtResp.Data.ItemResponse.List[0]
// bookShowInfo := list.BookShowInfo
// bookInfo.BookName = list.BookName
// bookInfo.BookPic = list.ImgUrlEntity.BigImgUrl
// bookInfo.ISBN = list.Isbn
// // 根据长度安全填充字段
// if isReturnMsg == 0 {
// if len(bookShowInfo) > 0 {
// bookInfo.Author = bookShowInfo[0]
// }
// if len(bookShowInfo) > 1 {
// bookInfo.Publisher = bookShowInfo[1]
// }
// if len(bookShowInfo) > 2 {
// bookInfo.PublicationTime = validateDateFormat(bookShowInfo[2])
// }
// if len(bookShowInfo) > 3 {
// bookInfo.BindingLayout = bookShowInfo[3]
// }
// if len(bookShowInfo) > 4 {
// bookInfo.FixPrice = bookShowInfo[4]
// } else {
// log.Printf("[WARN] BookShowInfo 长度不足 (仅 %d 项): %v", len(bookShowInfo), bookShowInfo)
// }
// }
// }
// return bookInfo, nil
// }
// if isLiveImage == 1 {
// // 实拍图
// sptUrl := 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)
// //创建HTTP客户端
// requestSpt := gorequest.New()
// //设置代理(如果有提供代理URL)
// if proxy != "" {
// requestSpt.Proxy(proxy)
// }
// // 发送请求
// respSpt, bodySpt, errsSpt := requestSpt.Get(sptUrl).
// Proxy(proxy).
// Set("Cookie", token).
// 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").
// Set("Accept", "application/json, text/plain, */*").
// Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
// Set("Referer", "https://item.kongfz.com/").
// Timeout(30 * time.Second).
// End()
// // 错误处理
// if len(errsSpt) > 0 {
// return nil, fmt.Errorf("请求失败: %v", errsSpt)
// }
// // 检查HTTP状态码
// if respSpt.StatusCode != http.StatusOK {
// return nil, fmt.Errorf("HTTP错误: %s", respSpt.Status)
// }
// // 解析响应
// var apiSptResp 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 {
// ItemId int64 `json:"itemId"`
// Title string `json:"title"`
// ImgUrl string `json:"imgUrl"`
// ImgBigUrl string `json:"imgBigUrl"`
// Author string `json:"author"`
// PubDateText string `json:"pubDateText"`
// Isbn string `json:"isbn"`
// Press string `json:"press"`
// ShopId int64 `json:"shopId"`
// TplRecords []struct {
// Key string `json:"key"`
// Value string `json:"value"`
// } `json:"tplRecords"`
// } `json:"list"`
// } `json:"itemResponse"`
// } `json:"data"`
// }
// // 解析JSON
// if err := json.Unmarshal([]byte(bodySpt), &apiSptResp); err != nil {
// return nil, fmt.Errorf("解析JSON失败: %w", err)
// }
// if apiSptResp.ErrType == "102" {
// return nil, fmt.Errorf("错误信息: %w状态码: %s", apiSptResp.Message, apiSptResp.ErrType)
// }
// if apiSptResp.Data.ItemResponse.Total > 0 && len(apiSptResp.Data.ItemResponse.List) > 0 {
// // 确定其实索引
// var startIndex int
// if cf.App.Size >= apiSptResp.Data.ItemResponse.Total {
// startIndex = apiSptResp.Data.ItemResponse.Total - 1
// } else {
// startIndex = cf.App.Size - 1
// }
// for attempt := 0; attempt < 3; attempt++ {
// currentIndex := startIndex - attempt
// // 检查索引是否有效
// if currentIndex < 0 || currentIndex >= len(apiSptResp.Data.ItemResponse.List) {
// log.Printf("[DEBUG] 索引 %d 超出范围,跳过", currentIndex)
// continue
// }
// randomNum := rand.Intn(currentIndex + 1)
// item := apiSptResp.Data.ItemResponse.List[randomNum]
// // 检查图片URL是否存在
// if item.ImgBigUrl == "" {
// log.Printf("[DEBUG] 索引 %d 的图片URL为空跳过", randomNum)
// continue
// }
// // 响应信息
// bookInfo.BookPicS = item.ImgUrl
// bookInfo.ISBN = item.Isbn
// if bookInfo.BookName == "" {
// bookInfo.BookName = item.Title
// if isReturnMsg == 0 {
// // 安全地获取TplRecords中的值
// if len(item.TplRecords) > 0 {
// bookInfo.Author = item.TplRecords[0].Value
// }
// if len(item.TplRecords) > 1 {
// bookInfo.Publisher = item.TplRecords[1].Value
// }
// if len(item.TplRecords) > 2 {
// bookInfo.PublicationTime = validateDateFormat(item.TplRecords[2].Value)
// }
// if len(item.TplRecords) > 3 {
// bookInfo.BindingLayout = item.TplRecords[3].Value
// }
// }
// }
// return bookInfo, nil
// }
// }
// }
// return nil, fmt.Errorf("查询失败,没有数据!")
//}
//
//// 获取商品列表通过店铺ID
//func outGetGoodsListMsgByShopId(shopId int, proxy string, retPrice int, isImage int, sortType string, sort string, priceMin float32, priceMax float32, pageNum, returnNum int) (books []BookInfo, goodsNum string, pNum string, err error) {
// // 判断店铺ID
// if shopId == 0 {
// return nil, "", "", fmt.Errorf("店铺编码为空!")
// }
// // 判断是否有图片设置默认值0
// var isImageStr string
// if isImage == 0 {
// isImageStr = "0"
// } else {
// isImageStr = "1"
// }
// // 判断一页图书数量设置默认值100
// if returnNum == 0 {
// returnNum = 100
// }
// // 判断页数设置默认值1
// if pageNum == 0 {
// pageNum = 1
// }
// // 判断排序类型设置默认值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)
// }
// }
// var url string
// var pMin int
// pMin = 0
// var pMax int
// pMax = 0
// // 判断价格下限设置默认值0
// if priceMin == 0 && priceMax == 0 {
// // 调用的url
// url = fmt.Sprintf("https://shop.kongfz.com/%d/all/%s_%d_0_0_%d_%s_%s_%d_%d",
// shopId, isImageStr, returnNum, pageNum, sortType, sort, pMin, pMax)
// } else if priceMin == 0 {
// url = fmt.Sprintf("https://shop.kongfz.com/%d/all/%s_%d_0_0_%d_%s_%s_%d_%.2f",
// shopId, isImageStr, returnNum, pageNum, sortType, sort, pMin, priceMax)
// } else if priceMax == 0 {
// url = fmt.Sprintf("https://shop.kongfz.com/%d/all/%s_%d_0_0_%d_%s_%s_%.2f_%d",
// shopId, isImageStr, returnNum, pageNum, sortType, sort, priceMin, pMax)
// } else {
// url = fmt.Sprintf("https://shop.kongfz.com/%d/all/%s_%d_0_0_%d_%s_%s_%.2f_%.2f",
// shopId, isImageStr, returnNum, pageNum, sortType, sort, priceMin, priceMax)
// }
// // 发送请求
// response, err := fetchResponse(url, proxy)
// if err != nil {
// return nil, "", "", err
// }
// body, err := io.ReadAll(response.Body)
// if err != nil {
// return nil, "", "", err
// }
// doc, err := goquery.NewDocumentFromReader(strings.NewReader(string(body)))
// // 全部商品数量
// 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")
// var params ParamsInfo
// if infoDiv.Length() > 0 {
// item := infoDiv.Find("div.item.clearfix")
// for i := 0; i < item.Length(); i++ {
// s := item.Eq(i)
// book := BookInfo{}
// // 书名
// book.BookName = strings.TrimSpace(s.Find("div.title a.link").Text())
// // 提取ISBN
// book.ISBN = strings.TrimSpace(s.AttrOr("isbn", ""))
// // 店铺ID
// shopid, _ := strconv.Atoi(strings.TrimSpace(s.AttrOr("shopid", "")))
// book.ShopId = int64(shopid)
// // 商品ID
// itemid, _ := strconv.Atoi(strings.TrimSpace(s.AttrOr("itemid", "")))
// book.ItemId = int64(itemid)
// // 详情URL
// book.DetailUrl = s.Find("div.item-img a.img-box").AttrOr("href", "")
// // 价格
// if retPrice == 0 {
// book.SellingPrice = s.Find("div.f_right.red.price").Find("span.bold").Text()
// params.Params = append(params.Params, struct {
// UserId string `json:"userId"`
// ItemId string `json:"itemId"`
// }{UserId: strings.TrimSpace(s.AttrOr("userid", "")), ItemId: strings.TrimSpace(s.AttrOr("itemid", ""))})
// }
// books = append(books, book)
// }
// if params.Params != nil {
// params.Area = "13003000000"
// dataItem, err := getGoodsListShippingFee(params, proxy)
// if err != nil {
// return nil, "", "", err
// }
// for i := 0; i < len(books); i++ {
// itemId := fmt.Sprintf("%d", books[i].ItemId)
// for _, data := range dataItem {
// if itemId == data.ItemID {
// books[i].ExpressDeliveryFee = data.Fee[0].TotalFee
// }
// }
// }
// }
// }
// return books, goodsNum, pNum, nil
//}
//
//// 定义对应的结构体
//type FeeInfo struct {
// ShippingID string `json:"shippingId"`
// ShippingName string `json:"shippingName"`
// TotalFee string `json:"totalFee"`
// ShippingText string `json:"shippingText"`
// FilterTotalFee string `json:"filterTotalFee"`
//}
//
//type DataItem struct {
// Fee []FeeInfo `json:"fee"`
// IsSeller bool `json:"isSeller"`
// ItemID string `json:"itemId"`
// UserID string `json:"userId"`
//}
//
//type ResponseStruct struct {
// Status bool `json:"status"`
// Data []DataItem `json:"data"`
// Message string `json:"message"`
// ErrType string `json:"errType"`
//}
//
//// 获取店铺里商品的快递费(定位到河南)
//func getGoodsListShippingFee(params ParamsInfo, proxy string) ([]DataItem, error) {
// if params.Params == nil {
// return nil, fmt.Errorf("没有商品信息!")
// }
// paramsJSON, err := json.Marshal(params)
// if err != nil {
// return nil, fmt.Errorf("参数序列化失败: %v", err)
// }
// // URL 编码参数
// encodedParams := url.QueryEscape(string(paramsJSON))
// url := fmt.Sprintf("https://shop.kongfz.com/book/shopsearch/getShippingFee?params=%s", encodedParams)
// request := gorequest.New()
// if proxy != "" {
// request.Proxy(proxy)
// }
// // 发送请求
// resp, body, errs := request.Get(url).
// 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").
// Set("Accept", "application/json, text/plain, */*").
// Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
// End()
// // 错误处理
// if len(errs) > 0 {
// return nil, fmt.Errorf("请求失败: %v", errs)
// }
// // 检查HTTP状态码
// if resp.StatusCode != http.StatusOK {
// return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
// }
// responseStruct := ResponseStruct{}
// err = json.Unmarshal([]byte(body), &responseStruct)
// if err != nil {
// return nil, fmt.Errorf("解析JSON失败: %v", err)
// }
// var dataItem []DataItem
// for i := range responseStruct.Data {
// dataItem = append(dataItem, responseStruct.Data[i])
// }
// return dataItem, nil
//}
//
//// 获取商品信息通过商品详情链接
//func outGetGoodsMsgByDetailUrl(detailUrl, proxy string) (*BookInfo, error) {
// response, err := fetchResponse(detailUrl, proxy)
// if err != nil {
// return nil, err
// }
// body, err := io.ReadAll(response.Body)
// if err != nil {
// return nil, err
// }
// // 解析HTML文档
// document, err := goquery.NewDocumentFromReader(strings.NewReader(string(body)))
// if err != nil {
// return nil, err
// }
// // 获取商品信息的快递费
// fee, err := getBookDetailShippingFee(detailUrl, proxy)
// 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)
// // 快递费
// book.ExpressDeliveryFee = fee
// return &book, nil
//}
//
//// 获取商品信息的快递费(定位到河南)
//func getBookDetailShippingFee(url, proxy string) (string, error) {
// compile := regexp.MustCompile(`kongfz\.com/(\d+)/(\d+)`)
// match := compile.FindStringSubmatch(url)
// var shippingFee string
// var shopId int
// var itemId int
// if len(match) == 3 {
// firstNum, err := strconv.Atoi(match[1]) // 店铺ID
// if err != nil {
// return "", fmt.Errorf("无效的店铺编码: %s", match[1])
// }
// shopId = firstNum
// secondNum, err := strconv.Atoi(match[2]) // 图书ID
// if err != nil {
// return "", fmt.Errorf("无效的图书编码: %s", match[2])
// }
// itemId = secondNum
// }
// shippingFeeUrl := fmt.Sprintf("https://book.kongfz.com/store-web/pc/v1/mould/calculateFee?area=13003000000&itemId=%d&shopId=%d", itemId, shopId)
// // 创建HTTP客户端
// request := gorequest.New()
// // 设置代理如果有提供代理URL
// if proxy != "" {
// request.Proxy(proxy)
// }
// // 设置超时和其他配置
// request.Timeout(30 * time.Second)
// // 发送请求
// resp, body, errs := request.Get(shippingFeeUrl).
// 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").
// Set("Accept", "application/json, text/plain, */*").
// Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
// End()
// // 错误处理
// if len(errs) > 0 {
// return "", fmt.Errorf("请求失败: %v", errs)
// }
// // 检查HTTP状态码
// if resp.StatusCode != http.StatusOK {
// return "", fmt.Errorf("HTTP错误: %s", resp.Status)
// }
// calculateFee := struct {
// ErrCode int `json:"errCode"`
// ErrMessage string `json:"errMessage"`
// Result struct {
// FeeList []struct {
// FreeCondition string `json:"freeCondition"`
// ShippingID string `json:"shippingId"`
// ShippingName string `json:"shippingName"`
// ShippingValue string `json:"shippingValue"`
// } `json:"feeList"`
// FeeText string `json:"feeText"`
// } `json:"result"`
// Status bool `json:"status"`
// }{}
//
// err := json.Unmarshal([]byte(body), &calculateFee)
// if err != nil {
// return "", fmt.Errorf("解析JSON失败: %v", err)
// }
// for _, fee := range calculateFee.Result.FeeList {
// shippingFee = fee.ShippingValue
// }
// return shippingFee, nil
//}
//
//// 公用发送请求方法
//func fetchResponse(url, proxy string) (*http.Response, error) {
// log.Printf("调用的URL: %s", url)
// maxRetries := cf.App.MaxRetryTimes
// var detailsResp *http.Response
// var errors []error
// 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 proxy != "" {
// detailsResp, _, errors = gorequest.New().
// Get(url).
// Proxy(proxy).
// 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()
// }
// if proxy == "" {
// 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()
// }
// // 检查是否需要重试
// 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)
// }
// return detailsResp, nil
//}
//
//// 获取销量榜商品列表(带有Out的都非官放标准接口)
//func outGetTopGoodsListMsg(catId int, proxy string) ([]string, error) {
// // 构建请求URL
// url := fmt.Sprintf("https://item.kongfz.com/api/pc/getSellWellListDetail?page=1&pageSize=100&timeRank=2&catId=%d", catId)
// // 创建HTTP客户端
// request := gorequest.New()
// // 设置代理如果有提供代理URL
// if proxy != "" {
// request.Proxy(proxy)
// }
// // 设置超时和其他配置
// request.Timeout(30 * time.Second)
// // 发送请求
// resp, body, errs := request.Get(url).
// 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").
// Set("Accept", "application/json, text/plain, */*").
// Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
// Set("Referer", "https://item.kongfz.com/").
// End()
// // 错误处理
// if len(errs) > 0 {
// return nil, fmt.Errorf("请求失败: %v", errs)
// }
// // 检查HTTP状态码
// if resp.StatusCode != http.StatusOK {
// return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
// }
// var bookDetailResponse BookDetailResponse
// err := json.Unmarshal([]byte(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)
// }
//
// var isbnList []string
// for _, item := range bookDetailResponse.Result.Data {
// if item.Isbn != "" {
// isbnList = append(isbnList, item.Isbn)
// }
// }
// isbnList = removeDuplicateISBNs(isbnList)
// return isbnList, 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
//}
//
//// 获取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) {
// log.Printf("[DEBUG] ", isbn, " 获取图书ISBN: %s", isbn)
// 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
//}
//
//// 连接数据库(选品)
//func connectDBXP() (*sql.DB, error) {
// db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
// cf.Database.Username, cf.Database.Password, cf.Database.Host, cf.Database.Name))
// if err != nil {
// return nil, fmt.Errorf("打开数据库连接失败: %v", err)
// }
// // 设置连接池参数
// db.SetMaxOpenConns(20) // 最大打开连接数
// db.SetMaxIdleConns(10) // 最大空闲连接数
// err = db.Ping()
// if err != nil {
// return nil, fmt.Errorf("数据库连接测试失败: %v", err)
// }
// return db, nil
//}
//
//// 从数据库随机获取一个可用账号
//func getRandomAccount() (*AccountCredential, error) {
// mu.RLock()
// defer mu.RUnlock()
// // sql语句
// query := `
// SELECT id, credential_account, credential_password, token
// FROM t_credential
// WHERE credential_type = 'KWCredential'
// AND status = 0
// AND is_del = 0
// ORDER BY RAND()
// LIMIT 1`
//
// db, err := connectDBXP()
// if err != nil {
// return nil, err
// }
// var ac AccountCredential
// err = db.QueryRow(query).Scan(&ac.ID, &ac.Username, &ac.Password, &ac.Token)
// if err != nil {
// if err == sql.ErrNoRows {
// return nil, fmt.Errorf("没有可用的账号")
// }
// return nil, fmt.Errorf("查询账号失败: %v", err)
// }
// return &ac, nil
//}
//
//// 修改账号为不可用
//func updateAccountInvalid(id int64) error {
// mu.RLock()
// defer mu.RUnlock()
// db, err := connectDBXP()
// if err != nil {
// return err
// }
// query := `UPDATE t_credential SET is_del = 1 WHERE id = ?`
// _, err = db.Exec(query, id)
// return fmt.Errorf("更新失败: %v", err)
//}
//
//// 修改账号为需要验证
//func updateAccountNeedVerify(id int64) error {
// mu.RLock()
// defer mu.RUnlock()
// db, err := connectDBXP()
// if err != nil {
// return err
// }
// query := `UPDATE t_credential SET status = 1 WHERE id = ?`
// _, err = db.Exec(query, id)
// return err
//}
//
//// 更新账号token
//func updateAccountToken(id int64, token string) error {
// mu.RLock()
// defer mu.RUnlock()
// db, err := connectDBXP()
// if err != nil {
// return err
// }
// query := `UPDATE t_credential SET token = ? WHERE id = ?`
// _, err = db.Exec(query, token, id)
// return err
//}
//
//// 登录(带有Out的都非官方标准接口)
////
////export OutLogin
//func OutLogin(username, password *C.char) *C.char {
// goUsername := C.GoString(username)
// goPassword := C.GoString(password)
// respToken, err := outLogin(goUsername, goPassword)
// resp := struct {
// Token string `json:"token"`
// }{
// Token: respToken,
// }
// var apiResponse APIResponse
// if err != nil {
// apiResponse = APIResponse{
// Success: false,
// Message: err.Error(),
// }
// } else {
// apiResponse = APIResponse{
// Success: true,
// Data: resp,
// }
// }
// // 转换为JSON字符串
// jsonData, marshalErr := json.Marshal(apiResponse)
// if marshalErr != nil {
// // 如果JSON序列化失败返回错误信息
// apiResponse = APIResponse{
// Success: false,
// Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
// }
// errorJson, _ := json.Marshal(apiResponse)
// return C.CString(string(errorJson))
// }
// return C.CString(string(jsonData))
//}
//
//// 获取用户信息(带有Out的都非官方标准接口)
////
////export OutGetUserMsg
//func OutGetUserMsg(token *C.char) *C.char {
// goToken := C.GoString(token)
// userInfo, err := outGetUserMsg(goToken)
// var apiResponse APIResponse
// if err != nil {
// apiResponse = APIResponse{
// Success: false,
// Message: err.Error(),
// }
// } else {
// apiResponse = APIResponse{
// Success: true,
// Data: userInfo,
// }
// }
// // 转换为JSON字符串
// jsonData, marshalErr := json.Marshal(apiResponse)
// if marshalErr != nil {
// // 如果JSON序列化失败返回错误信息
// apiResponse = APIResponse{
// Success: false,
// Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
// }
// errorJson, _ := json.Marshal(apiResponse)
// return C.CString(string(errorJson))
// }
// return C.CString(string(jsonData))
//}
//
//// 获取商品模版(带有Out的都非官方标准接口)
////
////export OutGetGoodsTplMsg
//func OutGetGoodsTplMsg(token, itemId, proxy *C.char) *C.char {
// goToken := C.GoString(token)
// goItemId := C.GoString(itemId)
// goProxy := C.GoString(proxy)
// info, err := outGetGoodsTplMsg(goToken, goItemId, goProxy)
// var apiResponse APIResponse
// if err != nil {
// apiResponse = APIResponse{
// Success: false,
// Message: err.Error(),
// }
// } else {
// apiResponse = APIResponse{
// Success: true,
// Data: info,
// }
// }
// // 转换为JSON字符串
// jsonData, marshalErr := json.Marshal(apiResponse)
// if marshalErr != nil {
// // 如果JSON序列化失败返回错误信息
// apiResponse = APIResponse{
// Success: false,
// Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
// }
// errorJson, _ := json.Marshal(apiResponse)
// return C.CString(string(errorJson))
// }
// return C.CString(string(jsonData))
//}
//
//// 获取商品列表-已登的店铺(带有Out的都非官方标准接口)
////
////export OutGetGoodsListMsgFromSelfShop
//func OutGetGoodsListMsgFromSelfShop(token, proxy, itemSn, priceMin, priceMax *C.char, startCreateTime C.int,
// endCreateTime C.int, requestType *C.char, isItemSnEqual C.int, page C.int, size C.int) *C.char {
// goToken := C.GoString(token)
// goProxy := C.GoString(proxy)
// goItemSn := C.GoString(itemSn)
// goPriceMin := C.GoString(priceMin)
// goPriceMax := C.GoString(priceMax)
// goStartCreateTime := int(startCreateTime)
// goEndCreateTime := int(endCreateTime)
// goRequestType := C.GoString(requestType)
// goIsItemSnEqual := int(isItemSnEqual)
// goPage := int(page)
// goSize := int(size)
// info, err := outGetGoodsListMsgFromSelfShop(goToken, goProxy, goItemSn, goPriceMin, goPriceMax, goStartCreateTime, goEndCreateTime, goRequestType, goIsItemSnEqual, goPage, goSize)
// var apiResponse APIResponse
// if err != nil {
// apiResponse = APIResponse{
// Success: false,
// Message: err.Error(),
// }
// } else {
// apiResponse = APIResponse{
// Success: true,
// Data: info,
// }
// }
// // 转换为JSON字符串
// jsonData, marshalErr := json.Marshal(apiResponse)
// if marshalErr != nil {
// // 如果JSON序列化失败返回错误信息
// apiResponse = APIResponse{
// Success: false,
// Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
// }
// errorJson, _ := json.Marshal(apiResponse)
// return C.CString(string(errorJson))
// }
// return C.CString(string(jsonData))
//}
//
//// 删除商品-已登的店铺(带有Out的都非官方标准接口)
////
////export OutDelGoodsFromSelfShop
//func OutDelGoodsFromSelfShop(token, proxy, itemId *C.char) *C.char {
// goToken := C.GoString(token)
// goProxy := C.GoString(proxy)
// goItemId := C.GoString(itemId)
// info, err := outDelGoodsFromSelfShop(goToken, goProxy, goItemId)
// var apiResponse APIResponse
// if err != nil {
// apiResponse = APIResponse{
// Success: false,
// Message: err.Error(),
// }
// } else {
// apiResponse = APIResponse{
// Success: true,
// Data: info,
// }
// }
// // 转换为JSON字符串
// jsonData, marshalErr := json.Marshal(apiResponse)
// if marshalErr != nil {
// // 如果JSON序列化失败返回错误信息
// apiResponse = APIResponse{
// Success: false,
// Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
// }
// errorJson, _ := json.Marshal(apiResponse)
// return C.CString(string(errorJson))
// }
// return C.CString(string(jsonData))
//}
//
//// 新增商品(带有Out的都非官方标准接口)
////
////export OutAddGoods
//func OutAddGoods(token, proxy, formData *C.char) *C.char {
// goToken := C.GoString(token)
// goProxy := C.GoString(proxy)
// goFormData := C.GoString(formData)
// info, err := outAddGoods(goToken, goProxy, goFormData)
// var apiResponse APIResponse
// if err != nil {
// apiResponse = APIResponse{
// Success: false,
// Message: err.Error(),
// }
// } else {
// apiResponse = APIResponse{
// Success: true,
// Data: info,
// }
// }
// // 转换为JSON字符串
// jsonData, marshalErr := json.Marshal(apiResponse)
// if marshalErr != nil {
// // 如果JSON序列化失败返回错误信息
// apiResponse = APIResponse{
// Success: false,
// Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
// }
// errorJson, _ := json.Marshal(apiResponse)
// return C.CString(string(errorJson))
// }
// return C.CString(string(jsonData))
//}
//
//// 获取图片URL(官图和拍图)带有店铺过滤
////
////export OutGetImageFilterShopId
//func OutGetImageFilterShopId(token, isbn *C.char, shopId C.int, proxy *C.char, isLiveImage C.int, isReturnMsg C.int) *C.char {
// goToken := C.GoString(token)
// goIsbn := C.GoString(isbn)
// goShopId := int(shopId)
// goProxy := C.GoString(proxy)
// goIsLiveImage := int(isLiveImage)
// goIsReturnMsg := int(isReturnMsg)
// info, err := outGetImageFilterShopId(goToken, goIsbn, goShopId, goProxy, goIsLiveImage, goIsReturnMsg)
// var apiResponse APIResponse
// if err != nil {
// apiResponse = APIResponse{
// Success: false,
// Message: err.Error(),
// }
// } else {
// apiResponse = APIResponse{
// Success: true,
// Data: info,
// }
// }
// // 转换为JSON字符串
// jsonData, marshalErr := json.Marshal(apiResponse)
// if marshalErr != nil {
// // 如果JSON序列化失败返回错误信息
// apiResponse = APIResponse{
// Success: false,
// Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
// }
// errorJson, _ := json.Marshal(apiResponse)
// return C.CString(string(errorJson))
// }
// return C.CString(string(jsonData))
//}
//
//// 获取商品图片(带有Out的都非官方标准接口)
////
////export OutGetImageByIsbn
//func OutGetImageByIsbn(token, isbn, proxy *C.char, isLiveImage C.int, isReturnMsg C.int) *C.char {
// goToken := C.GoString(token)
// goIsbn := C.GoString(isbn)
// goProxy := C.GoString(proxy)
// goIsLiveImage := int(isLiveImage)
// goIsReturnMsg := int(isReturnMsg)
// bookInfo, err := outGetImageByIsbn(goToken, goIsbn, goProxy, goIsLiveImage, goIsReturnMsg)
// var apiResponse APIResponse
// if err != nil {
// apiResponse = APIResponse{
// Success: false,
// Message: err.Error(),
// }
// } else {
// apiResponse = APIResponse{
// Success: true,
// Data: bookInfo,
// }
// }
// // 转换为JSON字符串
// jsonData, marshalErr := json.Marshal(apiResponse)
// if marshalErr != nil {
// // 如果JSON序列化失败返回错误信息
// apiResponse = APIResponse{
// Success: false,
// Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
// }
// errorJson, _ := json.Marshal(apiResponse)
// return C.CString(string(errorJson))
// }
// return C.CString(string(jsonData))
//}
//
//// 获取商品列表通过店铺ID(带有Out的都非官方标准接口)
////
////export OutGetGoodsListMsgByShopId
//func OutGetGoodsListMsgByShopId(shopId C.int, proxy *C.char, retPrice C.int, isImage C.int, sortType *C.char, sort *C.char, priceMin C.float, priceMax C.float, pageNum, returnNum C.int) *C.char {
// goShopId := int(shopId)
// goProxy := C.GoString(proxy)
// goRetPrice := int(retPrice)
// goIsImage := int(isImage)
// goSortType := C.GoString(sortType)
// goSort := C.GoString(sort)
// goPriceMin := float32(priceMin)
// goPriceMax := float32(priceMax)
// goPageNum := int(pageNum)
// goReturnNum := int(returnNum)
// books, num, pNum, err := outGetGoodsListMsgByShopId(goShopId, goProxy, goRetPrice, goIsImage, goSortType, goSort, goPriceMin, goPriceMax, goPageNum, goReturnNum)
// // 构建统一格式的响应
// bookInfo := struct {
// GoodsNum string `json:"goods_num,omitempty"`
// PNum string `json:"pnum,omitempty"`
// Data interface{} `json:"data,omitempty"`
// }{
// GoodsNum: num,
// PNum: pNum,
// Data: books,
// }
// var apiResponse APIResponse
// if err != nil {
// apiResponse = APIResponse{
// Success: false,
// Message: err.Error(),
// }
// } else {
// apiResponse = APIResponse{
// Success: true,
// Data: bookInfo,
// }
// }
// // 转换为JSON字符串
// jsonData, marshalErr := json.Marshal(apiResponse)
// if marshalErr != nil {
// // 如果JSON序列化失败返回错误信息
// apiResponse = APIResponse{
// Success: false,
// Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
// }
// errorJson, _ := json.Marshal(apiResponse)
// return C.CString(string(errorJson))
// }
// return C.CString(string(jsonData))
//}
//
//// 获取商品信息通过商品详情链接(带有0ut的都非官方标准接口)
////
////export OutGetGoodsMsgByDetailUrl
//func OutGetGoodsMsgByDetailUrl(detailUrl, proxy *C.char) *C.char {
// goDetailUrl := C.GoString(detailUrl)
// goProxy := C.GoString(proxy)
// response, err := outGetGoodsMsgByDetailUrl(goDetailUrl, goProxy)
// // 构建统一格式的响应
// var apiResponse APIResponse
// if err != nil {
// apiResponse = APIResponse{
// Success: false,
// Message: err.Error(),
// }
// } else {
// apiResponse = APIResponse{
// Success: true,
// Data: response,
// }
// }
// // 转换为JSON字符串
// jsonData, marshalErr := json.Marshal(apiResponse)
// if marshalErr != nil {
// // 如果JSON序列化失败返回错误信息
// apiResponse = APIResponse{
// Success: false,
// Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
// }
// errorJson, _ := json.Marshal(apiResponse)
// return C.CString(string(errorJson))
// }
// return C.CString(string(jsonData))
//}
//
//// 获取销量榜商品列表(带有Out的都非官放标准接口)
////
////export OutGetTopGoodsListMsg
//func OutGetTopGoodsListMsg(catId C.int, proxy *C.char) *C.char {
// goCatId := int(catId)
// goProxy := C.GoString(proxy)
// response, err := outGetTopGoodsListMsg(goCatId, goProxy)
// // 构建统一格式的响应
// var apiResponse APIResponse
// if err != nil {
// apiResponse = APIResponse{
// Success: false,
// Message: err.Error(),
// }
// } else {
// apiResponse = APIResponse{
// Success: true,
// Data: response,
// }
// }
// // 转换为JSON字符串
// jsonData, marshalErr := json.Marshal(apiResponse)
// if marshalErr != nil {
// // 如果JSON序列化失败返回错误信息
// apiResponse = APIResponse{
// Success: false,
// Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
// }
// errorJson, _ := json.Marshal(apiResponse)
// 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() {
//}