Colly 實戰(zhàn):5 分鐘爬取 Google Groups 郵件列表

2025-07-14 17:51 更新

Google Groups 郵件太多不想手動復制?用 Colly 把主題、作者、正文一次性打包成 JSON!官方 80+ 行示例已被精簡為 30 行中文注釋版,新手也能秒懂。

一、整體思路(先背下來)

  1. 線程收集器:翻 /forum/ 頁面,拿“主題列表”
  2. 郵件收集器:進每個主題,爬所有郵件
  3. 結果輸出:一個主題 = 一個數(shù)組,直接生成 JSON

二、精簡中文代碼(30 行)

package main


import (
    "encoding/json"
    "flag"
    "log"
    "os"
    "strings"


    "github.com/gocolly/colly/v2"
)


// 單封郵件結構
type Mail struct {
    Title   string `json:"標題"`
    Link    string `json:"鏈接"`
    Author  string `json:"作者"`
    Date    string `json:"日期"`
    Message string `json:"正文"`
}


func main() {
    // 1. 命令行參數(shù):-group=hspbp 可換任意組名
    group := flag.String("group", "hspbp", "Google Groups 組名")
    flag.Parse()


    // 2. 雙收集器:線程 + 郵件
    threadC := colly.NewCollector()
    mailC   := colly.NewCollector()


    threads := make(map[string][]Mail)


    /* ---------- 線程收集器:翻主題 ---------- */
    threadC.OnHTML("tr", func(e *colly.HTMLElement) {
        ch   := e.DOM.Children()
        author := strings.TrimSpace(ch.Eq(1).Text())
        if author == "" { return } // 被刪除的主題


        title := strings.TrimSpace(ch.Eq(0).Text())
        link, _ := ch.Eq(0).Children().Eq(0).Attr("href")
        // 替換為純 HTML 版本
        link = strings.Replace(link, ".com/d/topic", ".com/forum/?_escaped_fragment_=topic", 1)
        date := strings.TrimSpace(ch.Eq(2).Text())


        log.Printf("發(fā)現(xiàn)主題:%s %s", title, link)
        mailC.Visit(link)
    })


    // 翻頁
    threadC.OnHTML("body > a[href]", func(e *colly.HTMLElement) {
        e.Request.Visit(e.Attr("href"))
    })


    /* ---------- 郵件收集器:爬正文 ---------- */
    mailC.OnHTML("body", func(e *colly.HTMLElement) {
        subject := e.ChildText("h2")
        if _, ok := threads[subject]; !ok {
            threads[subject] = []Mail{}
        }


        e.ForEach("table tr", func(_ int, el *colly.HTMLElement) {
            threads[subject] = append(threads[subject], Mail{
                Title:   strings.TrimSpace(el.ChildText("td:nth-of-type(1)")),
                Link:    el.ChildAttr("td:nth-of-type(1)", "href"),
                Author:  strings.TrimSpace(el.ChildText("td:nth-of-type(2)")),
                Date:    strings.TrimSpace(el.ChildText("td:nth-of-type(3)")),
                Message: strings.TrimSpace(el.ChildText("td:nth-of-type(4)")),
            })
        })


        // 翻郵件下一頁
        if href, ok := e.DOM.Find("> a[href]").Attr("href"); ok {
            e.Request.Visit(href)
        } else {
            log.Printf("主題 [%s] 完成", subject)
        }
    })


    // 3. 啟動
    startURL := "https://groups.google.com/forum/?_escaped_fragment_=forum/" + *group
    threadC.Visit(startURL)


    // 4. 輸出漂亮 JSON
    enc := json.NewEncoder(os.Stdout)
    enc.SetIndent("", "  ")
    _ = enc.Encode(threads)
}

三、3 步運行

步驟 命令 說明
① 安裝 go mod init gg && go get github.com/gocolly/colly/v2 一鍵拉庫
② 保存 復制上方代碼 → main.go 零配置
③ 運行 go run main.go -group=hspbp > hspbp.json 生成主題 JSON

四、結果預覽(hspbp.json

{
  "How to use Colly with Google Groups": [
    {
      "標題": "Re: How to use Colly with Google Groups",
      "鏈接": "...",
      "作者": "Alice",
      "日期": "May 20",
      "正文": "You can use OnHTML to extract..."
    }
  ]
}

五、常見問題速查

癥狀 原因 解決
0 條數(shù)據(jù) 組名錯誤或反爬 換組名 + 加 User-Agent
正文亂碼 換行符未處理 用 strings.TrimSpace
403 被攔截 缺代理/限速 加 Limit 或代理

六、1 分鐘擴展

需求 改動 1 行
爬其他組 -group=golang-nuts
存 CSV 把 JSON 編碼換成 csv.NewWriter
存 MongoDB 在 mailC.OnHTML 里寫 collection.InsertOne
以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號