Colly 實(shí)戰(zhàn):抓取 Factbase 演講全文并保存 JSON

2025-07-14 17:46 更新

從 API 列表 → 逐條詳情 → 本地 JSON 文件,一條命令完成 Factbase 演講全文抓取。零基礎(chǔ)也能 5 分鐘跑通!

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

  1. 列表收集器:調(diào) API 分頁拿 slug + 日期
  2. 詳情收集器:根據(jù) slug/transcript/xxx 頁面
  3. 上下文傳遞:把日期/文件名隨請求一起帶過去
  4. 結(jié)果輸出:每條演講保存為一個(gè) <日期>_<slug>.json

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

package main


import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "strconv"


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


// 演講全文結(jié)構(gòu)
type Speech struct {
    Speaker string `json:"speaker"`
    Text    string `json:"text"`
}


func main() {
    const (
        searchAPI   = "https://factba.se/json/json-transcript.php?q=&f=&dt=&p="
        transcript  = "https://factba.se/transcript/"
    )


    // 1. 列表收集器:只訪問 API
    listC := colly.NewCollector(colly.AllowedDomains("factba.se"))


    // 2. 詳情收集器:爬詳情頁
    detailC := listC.Clone()


    // 3. 解析詳情頁 → 保存 JSON
    detailC.OnHTML("body", func(e *colly.HTMLElement) {
        var speech []Speech
        e.ForEach(".topic-media-row", func(_ int, el *colly.HTMLElement) {
            speech = append(speech, Speech{
                Speaker: el.ChildText(".speaker-label"),
                Text:    el.ChildText(".transcript-text-block"),
            })
        })


        date := e.Request.Ctx.Get("date")
        slug := e.Request.Ctx.Get("slug")
        file := colly.SanitizeFileName(date + "_" + slug + ".json")


        data, _ := json.MarshalIndent(speech, "", "  ")
        _ = ioutil.WriteFile(file, data, 0644)
        fmt.Printf("? 已保存 %s 共 %d 段\n", file, len(speech))
    })


    // 4. 解析 API → 觸發(fā)詳情
    stop := false
    listC.OnResponse(func(r *colly.Response) {
        type Resp struct {
            Data []struct {
                Slug string `json:"slug"`
                Date string `json:"date"`
            } `json:"data"`
        }
        var resp Resp
        _ = json.Unmarshal(r.Body, &resp)


        if len(resp.Data) == 0 {
            stop = true
            return
        }


        for _, d := range resp.Data {
            u := transcript + d.Slug
            ctx := colly.NewContext()
            ctx.Put("date", d.Date)
            ctx.Put("slug", d.Slug)
            detailC.Request("GET", u, nil, ctx, nil)
        }
    })


    // 5. 從第 1 頁開始,最多 999 頁
    for i := 1; i < 1000 && !stop; i++ {
        _ = listC.Visit(searchAPI + strconv.Itoa(i))
    }
}

三、3 步跑通

步驟 命令 說明
① 安裝 go mod init factbase && go get github.com/gocolly/colly/v2 一鍵拉庫
② 保存 復(fù)制上方代碼 → main.go 零配置
③ 運(yùn)行 go run main.go 終端實(shí)時(shí)顯示保存進(jìn)度

四、結(jié)果示例

本地生成文件:

2023-10-01_trump-ohio-rally.json
2023-09-30_biden-press-briefing.json
...

打開任意 JSON:

[
  {
    "speaker": "Donald Trump",
    "text": "We are going to make America great again..."
  },
  {
    "speaker": "Reporter",
    "text": "Mr. President, what about..."
  }
]

五、常見問題速查

癥狀 原因 解決
0 條數(shù)據(jù) API 無返回 檢查網(wǎng)絡(luò) / 換代理
文件中文亂碼 Windows 默認(rèn)編碼 用 VS Code 打開即可
403 被攔截 缺 UA 加 colly.UserAgent("Mozilla/5.0...")

六、1 分鐘擴(kuò)展

需求 改動(dòng) 1 行
只爬前 10 頁 i < 11
存 CSV 把 json.MarshalIndent 換成 csv.Writer
存 MongoDB 在 OnHTML 里寫 collection.InsertOne
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號