Go爬虫开发学习记录

Go爬虫开发学习记录

基础篇:使用net/http库

Go的标准库net/http提供了完善的HTTP客户端功能,是构建爬虫的基石:

go 复制代码
package main

import (
    "fmt"
    "io"
    "net/http"
)

func fetchPage(url string) string {
    // 创建自定义HTTP客户端
    client := &http.Client{}
    
    // 构建GET请求
    req, _ := http.NewRequest("GET", url, nil)
    
    // 设置请求头模拟浏览器
    req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
    req.Header.Add("Cookie", "example_cookie=value")
    
    // 发送请求
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("请求错误:", err)
        return ""
    }
    defer resp.Body.Close()  // 确保关闭响应体
    
    // 检查状态码
    if resp.StatusCode != 200 {
        fmt.Println("状态码错误:", resp.StatusCode)
        return ""
    }
    
    // 读取响应内容
    body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("读取失败:", err)
        return ""
    }
    return string(body)
}

func main() {
    url := "https://www.runoob.com/go/go-tutorial.html"
    htmlContent := fetchPage(url)
    fmt.Println(htmlContent)
}

解析:

  1. 自定义HTTP客户端 :通过&http.Client{}创建可配置的客户端实例
  2. 请求头设置:添加User-Agent和Cookie模拟浏览器行为
  3. 错误处理:全面处理网络请求、状态码和读取错误
  4. 资源清理:使用defer确保响应体正确关闭

进阶篇:HTML解析与内容提取

获取HTML只是第一步,关键是从中提取有价值的信息:

go 复制代码
import (
    "golang.org/x/net/html"
    "strings"
)

func parseHTML(htmlStr string) (title, content string) {
    // 解析HTML文档
    doc, err := html.Parse(strings.NewReader(htmlStr))
    if err != nil {
        fmt.Println("解析错误:", err)
        return
    }
    
    // 递归查找标题
    var findTitle func(*html.Node)
    findTitle = func(n *html.Node) {
        if n.Type == html.ElementNode && n.Data == "title" {
            for c := n.FirstChild; c != nil; c = c.NextSibling {
                if c.Type == html.TextNode {
                    title = c.Data
                    return
                }
            }
        }
        for c := n.FirstChild; c != nil; c = c.NextSibling {
            findTitle(c)
        }
    }
    findTitle(doc)
    
    // 提取所有文本内容
    var extractText func(*html.Node)
    extractText = func(n *html.Node) {
        if n.Type == html.TextNode {
            trimmed := strings.TrimSpace(n.Data)
            if trimmed != "" {
                content += trimmed + "\n"
            }
        }
        for c := n.FirstChild; c != nil; c = c.NextSibling {
            extractText(c)
        }
    }
    extractText(doc)
    
    return
}

func main() {
    htmlContent := fetchPage("https://www.runoob.com/go/go-tutorial.html")
    title, content := parseHTML(htmlContent)
    fmt.Println("标题:", title)
    fmt.Println("内容:\n", content)
}

解析:

  1. 递归遍历DOM树:深度优先搜索(DFS)遍历所有节点
  2. 节点类型判断
    • ElementNode:HTML元素节点(标签)
    • TextNode:文本内容节点
  3. 内容清洗strings.TrimSpace去除空白字符
  4. 精确提取 :通过标签名(title)定位特定内容

高效篇:使用Colly+GoQuery框架

对于复杂爬取任务,Colly+GoQuery组合提供更强大的解决方案:

go 复制代码
package main

import (
    "fmt"
    "log"
    "strings"
    "time"
    "bytes"
    
    "github.com/gocolly/colly"
    "github.com/PuerkitoBio/goquery"
)

func main() {
    // 1. 创建Collector实例
    c := colly.NewCollector(
        colly.AllowedDomains("runoob.com", "www.runoob.com"),
        colly.UserAgent("Mozilla/5.0..."),
        colly.Async(true), // 启用异步
    )
    
    // 2. 设置爬取规则
    c.Limit(&colly.LimitRule{
        DomainGlob:  "*runoob.com*",
        Parallelism: 2, // 并发数
        Delay:       1 * time.Second,
        RandomDelay: 1 * time.Second,
    })
    
    // 3. 注册回调函数
    c.OnRequest(func(r *colly.Request) {
        fmt.Println("访问:", r.URL)
    })
    
    c.OnError(func(_ *colly.Response, err error) {
        log.Println("错误:", err)
    })
    
    // 4. 使用GoQuery解析
    c.OnHTML("html", func(e *colly.HTMLElement) {
        doc, err := goquery.NewDocumentFromReader(bytes.NewReader(e.Response.Body))
        if err != nil {
            log.Println("解析失败:", err)
            return
        }
        
        // 提取标题
        title := doc.Find("title").Text()
        fmt.Println("页面标题:", title)
        
        // 提取导航菜单
        doc.Find("#leftcolumn a").Each(func(i int, s *goquery.Selection) {
            fmt.Printf("菜单%d: %s\n", i+1, strings.TrimSpace(s.Text()))
        })
        
        // 提取文章内容
        doc.Find("div.article").Each(func(i int, s *goquery.Selection) {
            section := s.Find("h1").Text()
            content := strings.TrimSpace(s.Text())
            fmt.Printf("\n章节%d: %s\n内容: %s\n", i+1, section, content)
        })
    })
    
    // 5. 开始爬取
    c.Visit("https://www.runoob.com/go/go-tutorial.html")
    c.Wait() // 等待异步任务
    fmt.Println("爬取完成")
}

Colly核心优势:

  1. 智能限速控制

    • 自动延迟请求
    • 随机延迟避免检测
    • 并发控制保护服务器
  2. 强大的选择器

    • CSS选择器语法
    • 链式调用
    • 支持复杂嵌套选择
  3. 异步高性能

    • 协程并发处理
    • 自动队列管理
    • 高效资源利用
  4. 扩展性强

    • 中间件支持
    • 自定义存储后端
    • 请求重试机制

可视化爬虫工具:易采集EasySpider

对于非技术人员或快速原型开发,可视化爬虫工具是绝佳选择:
无代码可视化爬虫

易采集EasySpider 核心特点:

  • 零代码可视化操作
  • 浏览器自动化录制
  • 智能数据提取
  • 定时任务调度
  • 云存储支持

适用场景:快速数据采集原型、非技术用户、简单爬取任务

爬虫开发最佳实践

  1. 遵守Robots协议

    robots.txt 复制代码
    User-agent: *
    Allow: /public/
    Disallow: /private/
  2. 道德规范

    • 尊重网站版权声明
    • 避免高频请求
    • 不爬取敏感信息
  3. 反爬虫对策

    • 轮换User-Agent
    • 使用代理IP池
    • 模拟人类操作间隔
    • 处理验证码机制
  4. 错误处理

    • 网络异常重试
    • 状态码处理
    • 超时控制
  5. 数据存储

    • 结构化数据:MySQL/PostgreSQL
    • 半结构化:MongoDB/Elasticsearch
    • 文件存储:CSV/JSON/Parquet

总结与学习路径

Go爬虫开发技术栈演进:
基础 net/http HTML解析 Colly框架 分布式爬虫 云原生部署

学习建议:

  1. 掌握基础:熟练使用net/http和HTML解析
  2. 框架实践:深入Colly+GoQuery组合应用
  3. 项目实战:构建完整爬虫系统
  4. 拓展进阶:研究分布式爬虫架构
  5. 工具互补:了解可视化工具辅助开发

资源推荐:

相关推荐
花酒锄作田7 天前
Gin 框架中的规范响应格式设计与实现
golang·gin
西岸行者7 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意7 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码7 天前
嵌入式学习路线
学习
毛小茛7 天前
计算机系统概论——校验码
学习
babe小鑫7 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms7 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下7 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。7 天前
2026.2.25监控学习
学习
im_AMBER7 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode