300 lines
8.6 KiB
Go
300 lines
8.6 KiB
Go
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
|
|
//}
|