当前位置: 首页 > news >正文

使用chromedp 来做人工模拟操作爬取数据方法

package mainimport ("context""fmt""log""os""time""github.com/chromedp/chromedp"
)// DramaData 结构体:用于存储抓取到的数据
type DramaData struct {ID    intTitle stringLink  string
}func main() {// 1. 基础配置:设定存储路径,实现“登录一次,永久有效”storageDir := "D:\\temp\\spider_chrome"if err := os.MkdirAll(storageDir, 0755); err != nil {log.Fatal(err)}opts := append(chromedp.DefaultExecAllocatorOptions[:],chromedp.NoFirstRun,chromedp.NoDefaultBrowserCheck,chromedp.Flag("headless", false),           // 设置为 false 才能看到浏览器并手动操作chromedp.Flag("user-data-dir", storageDir), // 指定 Cookie 存储目录
    )// 2. 初始化 contextallocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)defer cancel()ctx, cancel := chromedp.NewContext(allocCtx)defer cancel()// 目标 URLtargetURL := "https://www.changdupingtai.com/sale/short-play/list?search_type=2&sort_type=1&sort_field=8&aweme_user_new_version=true&page_index=1&page_size=10"// 3. 执行主流程fmt.Println(">>> 正在启动浏览器...")err := chromedp.Run(ctx,chromedp.Navigate(targetURL),// 登录检查逻辑chromedp.ActionFunc(func(ctx context.Context) error {// 如果页面出现了“登录”字样或者特定的登录框类名var html = "登录"chromedp.OuterHTML("body", &html).Do(ctx)// 简单的逻辑判断:如果包含登录关键词,则进入手工模式if isLoginPage(html) {fmt.Println(" [!] 检测到未登录或验证码。")fmt.Println(" [!] 请在浏览器窗口完成登录/验证,直到页面进入剧目列表...")// 阻塞:直到当前 URL 变成了目标列表页 URLfor {var currentURL stringchromedp.Location(&currentURL).Do(ctx)if currentURL == "https://www.changdupingtai.com/sale/announcement-center" {fmt.Println(" [√] 登录成功,开始操作页面")// 1 点击全部渠道err := chromedp.Run(ctx,chromedp.WaitVisible(`//div[contains(@class,'arco-select-view') and contains(.,'全部渠道')]`, chromedp.BySearch),chromedp.ScrollIntoView(`//div[contains(@class,'arco-select-view') and contains(.,'全部渠道')]`, chromedp.BySearch),chromedp.Click(`//div[contains(@class,'arco-select-view') and contains(.,'全部渠道')]`, chromedp.BySearch),
                        )if err != nil {return err}fmt.Println("点击 全部渠道 完成")// 2 等待 dropdownerr = chromedp.Run(ctx,chromedp.WaitVisible(`//li[contains(@class,'arco-select-option') and contains(.,'主管账号')]`, chromedp.BySearch),
                        )if err != nil {return err}time.Sleep(1 * time.Second)// 3 点击主管账号err = chromedp.Run(ctx,chromedp.ScrollIntoView(`//li[contains(@class,'arco-select-option') and contains(.,'主管账号')]`, chromedp.BySearch),chromedp.Click(`//li[contains(@class,'arco-select-option') and contains(.,'主管账号')]`, chromedp.BySearch),
                        )if err != nil {return err}fmt.Println("点击 主管账号 完成")time.Sleep(1 * time.Second)// 4 点击推广中心err = chromedp.Run(ctx,chromedp.WaitVisible(`//span[contains(.,'推广中心')]`, chromedp.BySearch),chromedp.ScrollIntoView(`//span[contains(.,'推广中心')]`, chromedp.BySearch),chromedp.Click(`//span[contains(.,'推广中心')]`, chromedp.BySearch),
                        )if err != nil {return err}time.Sleep(1 * time.Second)// 5 点击漫剧列表err = chromedp.Run(ctx,chromedp.WaitVisible(`//span[contains(.,'漫剧列表')]`, chromedp.BySearch),chromedp.ScrollIntoView(`//span[contains(.,'漫剧列表')]`, chromedp.BySearch),chromedp.Click(`//span[contains(.,'漫剧列表')]`, chromedp.BySearch),
                        )if err != nil {return err}fmt.Println(" [√] 已进入漫剧列表")break}time.Sleep(2 * time.Second)}}return nil}),// 等待列表加载完成
)if err != nil {log.Fatalf("初始化失败: %v", err)}err = chromedp.Run(ctx,chromedp.WaitVisible(`.arco-table-content-inner`, chromedp.ByQuery),)time.Sleep(2 * time.Second)// 4. 遍历列表处理详情页// 注意:这里建议先获取所有剧目的 ID 或点击索引,避免页面刷新导致 DOM 失效var rowCount intchromedp.Run(ctx, chromedp.Evaluate(`document.querySelectorAll("tbody tr").length`, &rowCount)) // 假设行类名为 .list-row
fmt.Printf(">>> 发现 %d 条剧目,开始提取数据...\n", rowCount)for i := 0; i < rowCount; i++ {var d DramaDatad.ID = i + 1// 模拟点击进入详情页,抓取后再返回err := chromedp.Run(ctx,// 通过 JS 索引精确点击第 i 个按钮chromedp.Click(fmt.Sprintf(`(document.querySelectorAll(".text-button"))[%d]`, i), chromedp.ByJSPath),// 等待详情页关键元素chromedp.WaitVisible(`.detail-title`, chromedp.ByQuery),// 获取数据chromedp.Text(`.detail-title`, &d.Title, chromedp.ByQuery),chromedp.Location(&d.Link),// 返回上一页
            chromedp.NavigateBack(),// 必须等待列表重新加载,否则下一次循环找不到元素chromedp.WaitVisible(`.list-container`, chromedp.ByQuery),)if err != nil {fmt.Printf(" [×] 第 %d 行抓取失败: %v\n", i+1, err)continue}// 5. 落库
        saveToDB(d)}fmt.Println(">>> 任务完成!")
}// 简单的登录判断逻辑
func isLoginPage(html string) bool {// 你可以根据页面是否有 "登录" 二字或者特定类名判断// 这是一个非常通用的判断方案return len(html) < 2000 || (len(html) > 0 && (hasString(html, "login") || hasString(html, "请登录")))
}func hasString(source, target string) bool {return (len(source) > 0 && len(target) > 0)
}// 模拟落库函数
func saveToDB(data DramaData) {// 这里可以替换成 GORM 操作fmt.Printf(" [SUCCESS] 已入库: ID=%d, 标题=%s, 链接=%s\n", data.ID, data.Title, data.Link)
}

 

http://www.jsqmd.com/news/489988/

相关文章:

  • 龙虾搭玩不明白?你缺的不是技巧,是底层认知
  • SecGPT-14B快速部署教程:Docker Compose一键启停vLLM+Gradio双服务
  • AI辅助开发新体验:通过快马让AI自动生成集成Bing智能搜索的问答应用
  • 与AI结对编程:深度体验快马平台如何用大模型重构应用开发工作流
  • 【限时解禁】Docker 27低代码容器化内参白皮书(Moby项目组内部版V2.7.3):含未公开API文档、低代码DSL语法树规范及12个生产环境绕过限制的合规方案
  • 2026年昆明挖机配件优选推荐:官渡区吴思思挖掘机配件店 - 2026年企业推荐榜
  • AI 办公成职场标配,别再用错拖后腿!7 套书教你精准用 AI 提效
  • Mellanox网卡show_gids缺失的应急解决方案:从mlnx-tools源码到实战应用
  • MiniCPM-o-4.5-nvidia-FlagOS部署指南:Windows系统Python环境配置与模型调用
  • STM32 HAL_I2C_Mem_Read踩坑实录:为什么你的M24C64读取总失败?
  • KMS_VL_ALL_AIO终极激活方案:从困境到解决方案的完整路径
  • 【H5 前端开发笔记】第 04 期:HTML超文本标记语言 相对路径 和 绝对路径 详解
  • AsrTools:零门槛语音转文字解决方案,让音频处理效率提升10倍
  • 影墨·今颜实战教程:结合ControlNet实现手部姿态精准控制
  • 探秘:CN 470-510MHz频段在LoRaWAN网络中的部署与优化
  • 3个步骤让受损音频重获新生:AI语音修复工具VoiceFixer全攻略
  • ruoyi-cloud 集成 mybatis-plus 多租户插件:从配置到实战避坑指南
  • 开箱即用!Fish-Speech-1.5镜像部署,无需代码基础
  • Flutter Camera插件实战:如何避免全屏预览画面变形(附完整代码)
  • 【H5 前端开发笔记】第 05 期:HTML常用标签 (1) 文档定义标签
  • 个人相册色彩修复:cv_unet_image-colorization 工具实测与使用技巧
  • Qwen-Ranker Pro与Kubernetes集成:云原生部署实践
  • Win10系统下N卡1070显卡深度学习环境配置:CUDA8.0/9.1与cuDNN5.1/7.0共存指南
  • 【ROS进阶】- tf核心函数实战解析:从坐标查询到点云转换
  • 【H5 前端开发笔记】第 06 期:HTML常用标签 (2) 文本标签、图片标签
  • DA14585开发实战:从Keil5编译到SmartSnippets Toolbox烧录全解析
  • Qwen3.5-27B多模态落地:跨境电商商品图→多语言描述→合规性检查
  • Colmap在AutoDL云服务器上的完整安装指南(含常见报错解决方案)
  • 企业级工单管理零成本解决方案:osTicket从部署到精通指南
  • 实战Node.js实时应用,基于快马平台快速构建Socket.io聊天室后端