package main import ( "database/sql" "fmt" "regexp" "strings" _ "github.com/go-sql-driver/mysql" ) // func main() { // // 构建数据库连接字符串 // dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", // "root", "Long6166@@", "nj-cynosdbmysql-grp-1v6vxn5f.sql.tencentcdb.com", "26247", "book_center") // // 连接数据库 // db, err := sql.Open("mysql", dsn) // if err != nil { // log.Fatal("数据库连接失败:", err) // } // defer db.Close() // // // 测试数据库连接 // err = db.Ping() // if err != nil { // log.Fatal("数据库连接测试失败:", err) // } // fmt.Println("数据库连接成功") // // // 查询包含"影印版"或"(影印版)"的书名 // books, err := queryBooksWithCopyVersion(db) // if err != nil { // log.Fatal("查询失败:", err) // } // // fmt.Printf("找到 %d 本包含'影印版'或'(影印版)'的书\n", len(books)) // // if len(books) == 0 { // fmt.Println("没有找到需要更新的图书") // return // } // // // 更新书名,删除"影印版"和"(影印版)" // updatedCount, err := updateBookNames(db, books) // if err != nil { // log.Fatal("更新失败:", err) // } // // fmt.Printf("成功更新 %d 本书的书名\n", updatedCount) // } // // Book 结构体对应 book_center 表 type Book struct { ID int64 BookName string ISBN string } // queryBooksWithCopyVersion 查询包含"影印版"或"(影印版)"的书名 func queryBooksWithCopyVersion(db *sql.DB) ([]Book, error) { query := ` SELECT id, book_name, isbn FROM book_center WHERE book_name LIKE '%影印版%' AND del_flag = 0 ` rows, err := db.Query(query) if err != nil { return nil, err } defer rows.Close() var books []Book for rows.Next() { var book Book err := rows.Scan(&book.ID, &book.BookName, &book.ISBN) if err != nil { return nil, err } books = append(books, book) } return books, nil } // cleanBookName 清理书名,删除所有影印版相关文字 func cleanBookName(bookName string) string { // 定义需要删除的模式 patterns := []string{ "(影印版)", // 全角括号 "(影印版)", // 半角括号 "影印版", // 无括号 "【影印版】", // 方头括号 "[影印版]", // 方括号 } newName := bookName // 逐个删除模式 for _, pattern := range patterns { newName = strings.ReplaceAll(newName, pattern, "") } // 删除多余的空格 newName = strings.TrimSpace(newName) newName = regexp.MustCompile(`\s+`).ReplaceAllString(newName, " ") return newName } // updateBookNames 更新书名,删除所有影印版相关文字 func updateBookNames(db *sql.DB, books []Book) (int, error) { tx, err := db.Begin() if err != nil { return 0, err } defer tx.Rollback() updateStmt, err := tx.Prepare(` UPDATE book_center SET book_name = ?, update_time = UNIX_TIMESTAMP() WHERE id = ? AND isbn = ? `) if err != nil { return 0, err } defer updateStmt.Close() updatedCount := 0 for _, book := range books { // 清理书名 newBookName := cleanBookName(book.BookName) // 如果书名没有变化,跳过更新 if newBookName == book.BookName { fmt.Printf("跳过: 书名无变化 (ID: %d, ISBN: %s)\n", book.ID, book.ISBN) continue } // 如果书名超过字段长度限制,截断 if len(newBookName) > 400 { newBookName = newBookName[:400] fmt.Printf("警告: 书名超长,已截断 (ID: %d)\n", book.ID) } result, err := updateStmt.Exec(newBookName, book.ID, book.ISBN) if err != nil { fmt.Printf("更新失败 (ID: %d): %v\n", book.ID, err) continue } rowsAffected, err := result.RowsAffected() if err != nil { fmt.Printf("获取影响行数失败 (ID: %d): %v\n", book.ID, err) continue } if rowsAffected > 0 { updatedCount++ fmt.Printf("更新成功: ID=%d, ISBN=%s\n", book.ID, book.ISBN) fmt.Printf(" 原书名: %s\n", book.BookName) fmt.Printf(" 新书名: %s\n", newBookName) fmt.Println(" ---") } } err = tx.Commit() if err != nil { return 0, err } return updatedCount, nil } // 没用了 //// 获取销量榜所有分类中图书的isbn //func GetAllCategoryBooks() ([]string, error) { // // 1. 获取分类列表 // categories, err := GetSalesBookInfo() // if err != nil { // return nil, fmt.Errorf("获取分类列表失败: %v", err) // } // // 初始化返回的ISBN数组 // var allISBNs []string // // for i, category := range categories { // fmt.Printf("\n=== 正在处理分类 %d/%d: %s (ID: %d) ===\n", i+1, len(categories), category.Key, category.Value) // // 根据分类ID获取图书详情 // bookDetails, err := GetBookDetailsByCategory(category.Value) // if err != nil { // fmt.Printf("获取分类 %s 的图书信息失败: %v\n", category.Key, err) // continue // } // // 将当前分类的图书数据添加到结果map中 // if bookDetails != nil && bookDetails.Result.Data != nil { // for _, book := range bookDetails.Result.Data { // if book.Isbn != "" { // allISBNs = append(allISBNs, book.Isbn) // fmt.Printf("添加到ISBN列表: %s\n", book.Isbn) // } // } // fmt.Printf("分类 %s 获取到 %d 本图书\n", category.Key, len(bookDetails.Result.Data)) // } else { // fmt.Printf("分类 %s 没有获取到图书数据\n", category.Key) // } // time.Sleep(500 * time.Microsecond) // } // // 去重处理(可选) // allISBNs = removeDuplicateISBNs(allISBNs) // // 打印统计信息 // fmt.Printf("\n=== 总计: %d 个分类, %d 个唯一ISBN ===\n", len(categories), len(allISBNs)) // return allISBNs, nil //} // //// 获取销量榜的图书信息 //func GetSalesBookInfo() ([]SalesCategory, error) { // // 构建请求URL // url := "https://item.kongfz.com/api/Pc/getSellWellCatList" // // 创建HTTP客户端 // client := &http.Client{ // Timeout: 30 * time.Second, // } // // 创建请求 // req, err := http.NewRequest("GET", url, nil) // if err != nil { // return nil, fmt.Errorf("创建请求失败: %v", err) // } // // 设置请求头,模拟浏览器请求 // req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36") // req.Header.Set("Accept", "application/json, text/plain, */*") // req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8") // req.Header.Set("Referer", "https://item.kongfz.com/") // // 发送请求 // resp, err := client.Do(req) // if err != nil { // return nil, fmt.Errorf("请求失败: %v", err) // } // defer resp.Body.Close() // // 检查HTTP状态码 // if resp.StatusCode != http.StatusOK { // return nil, fmt.Errorf("HTTP错误: %s", resp.Status) // } // // 读取响应体 // body, err := io.ReadAll(resp.Body) // if err != nil { // return nil, fmt.Errorf("读取响应失败: %v", err) // } // // 解析JSON响应 // var salesCategoryResponse SalesCategoryResponse // err = json.Unmarshal(body, &salesCategoryResponse) // if err != nil { // return nil, fmt.Errorf("解析JSON失败: %v", err) // } // return salesCategoryResponse.Result, nil //} // //// 根据分类ID获取图书详情 //func GetBookDetailsByCategory(catId int) (*BookDetailResponse, error) { // // 构建请求URL // url := fmt.Sprintf("https://item.kongfz.com/api/pc/getSellWellListDetail?page=1&pageSize=100&timeRank=2&catId=%d", catId) // // 创建HTTP客户端 // client := &http.Client{ // Timeout: 30 * time.Second, // } // // 创建请求 // req, err := http.NewRequest("GET", url, nil) // if err != nil { // return nil, fmt.Errorf("创建请求失败: %v", err) // } // // 设置请求头,模拟浏览器请求 // req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36") // req.Header.Set("Accept", "application/json, text/plain, */*") // req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8") // req.Header.Set("Referer", "https://item.kongfz.com/") // // 发送请求 // resp, err := client.Do(req) // if err != nil { // return nil, fmt.Errorf("请求失败: %v", err) // } // defer resp.Body.Close() // // 检查HTTP状态码 // if resp.StatusCode != http.StatusOK { // return nil, fmt.Errorf("HTTP错误: %s", resp.Status) // } // // 读取响应体 // body, err := io.ReadAll(resp.Body) // if err != nil { // return nil, fmt.Errorf("读取响应失败: %v", err) // } // var bookDetailResponse BookDetailResponse // err = json.Unmarshal(body, &bookDetailResponse) // if err != nil { // return nil, fmt.Errorf("解析JSON失败: %v", err) // } // if !bookDetailResponse.Status { // return nil, fmt.Errorf("API返回错误: %s (代码: %d)", bookDetailResponse.ErrMessage, bookDetailResponse.ErrCode) // } // return &bookDetailResponse, nil //}