用 Golang 写一个365家常菜小视频的爬虫与推荐引擎

你刷着“365家常菜小视频”的时候,会不会想:这些视频到底怎么被推荐到我首页的?或者更实际点——我想在本地用代码把所有家常菜视频的标题...

你刷着“365家常菜小视频”的时候,会不会想:这些视频到底怎么被推荐到我首页的? 或者更实际点——我想在本地用代码把所有家常菜视频的标题、热度、标签扒下来,然后按季节、按口味分类,能不能自己写个程序实现?

能,而且用 Go 语言(Golang)来写特别顺手,它快、部署简单、并发强,咱不用像 Python 那样处理一堆库依赖,也不怕跑着跑着内存爆了,今天我就边想边写,带你撸一个能爬取并分析“365家常菜小视频”信息的命令行工具。

为什么是 Golang 而不是 Python?

说实话,我当初也习惯用 Python 写爬虫,但跑“365家常菜小视频”这种每天更新上百条的密集数据时,Python 的 GIL 锁全局解释器 就成了瓶颈,Golang 天然支持 goroutine,每个视频的请求可以开一个轻量级线程,几千个请求同时发出去,CPU 占用几乎没动。

特性 Python Golang
并发方式 多线程/协程(需要手动管理锁) goroutine + channel(内置并发原语)
部署 需要解释器 + 一堆 .py 文件 编译成一个二进制,扔服务器就能跑
依赖管理 pip + virtualenv(容易冲突) go mod(版本锁定,干净)
执行效率 慢(尤其密集计算) 接近 C 的速度

比如说你想要的 365 天每天一道家常菜小视频,如果按天爬取每个视频的播放量、点赞数、菜系标签,Python 可能要跑 20 分钟,Go 优化后 3 分钟搞定。

Step 1:定义数据结构

我们先把“365家常菜小视频”里每条视频抽象成结构体,打开终端,go mod init cooker365,然后写模型:

type Video struct {
    ID        int       `json:"id"`    string    `json:"title"`      // 红烧肉的家常做法”
    CookType  string    `json:"cook_type"`  // 炒、炖、蒸、烤
    Duration  int       `json:"duration"`   // 视频时长(秒)
    Plays     int64     `json:"plays"`      // 播放量
    Likes     int64     `json:"likes"`      // 点赞数
    Tags      []string  `json:"tags"`       // [家常菜, 快手菜, 无酱油]
    PublishAt time.Time `json:"publish_at"` // 发布日期
}

这里用了 JSON 标签,方便后面转存成文件或直接写数据库,其实上个月我看“365家常菜小视频”时注意到,他们的视频标题经常带 “无需放油”“电饭锅也能做” 这类高点击词汇,所以单独拎一个 CookType 字段,方便后面按烹饪方式聚类。

Step 2:并发爬取,别让 CPU 闲着

爬“365家常菜小视频”这类站点,最怕的就是 一个一个请求 发送——第一个返回了才发第二个,Golang 的 sync.WaitGroup + goroutine 直接把速度拉满。

核心代码大概这样(不用全部写完,咱们理解思路就行):

func crawlVideos(page int) ([]Video, error) {
    // 假设 API 是 https://api.cooker365.com/videos?page=%d
    url := fmt.Sprintf("https://api.cooker365.com/videos?page=%d", page)
    resp, err := http.Get(url)
    // ... 解析 JSON 到 []Video
}
func main() {
    var wg sync.WaitGroup
    for i := 1; i <= 50; i++ { // 抓取前50页
        wg.Add(1)
        go func(page int) {
            defer wg.Done()
            videos, err := crawlVideos(page)
            if err != nil {
                log.Printf("Page %d failed: %v", page, err)
                return
            }
            // 存储到文件或数据库
            saveVideos(videos)
        }(i)
    }
    wg.Wait()
    fmt.Println("完成!所有视频已爬取并存为JSON文件")
}

注意看那个 log.Printf——失败是正常的,365家常菜小视频”的接口会返回 503 或限流,所以一定要加重试,我用了一个指数退避(exponential backoff),遇到 429 就睡 2秒、4秒、8秒……最多再试 3 次,基本能绕过。

Step 3:过滤与推荐——找出你真正关心的菜

数据爬下来不能直接扔硬盘里吃灰,按照 费曼学习法 的说法,你要能 用自己的话 解释这个系统——那咱就做一个简单推荐引擎。

比如你只喜欢 素菜清蒸低盐 这三种标签的视频,那从所有“365家常菜小视频”里筛出来就行了:

func recommend(videos []Video, targetTags []string) []Video {
    result := []Video{}
    for _, v := range videos {
        if containsAll(v.Tags, targetTags) {
            result = append(result, v)
        }
    }
    return result
}
func containsAll(tags, target []string) bool {
    tagSet := make(map[string]bool, len(tags))
    for _, t := range tags {
        tagSet[t] = true
    }
    for _, t := range target {
        if !tagSet[t] {
            return false
        }
    }
    return true
}

但这还是太死板了,如果我想看“夏天开胃的菜”呢?那可以把 季节因子 作为权重,比如六月份就提高“凉拌”“冰镇”类标签视频的推荐分,你可以在结构体里增加一个字段 SeasonScore

type Video struct {
    // ... 前面的字段
    SeasonScore float64 `json:"season_score"`
}

在筛选循环里,根据当前月份给视频加权,再排序输出 Top 10,Golang 自带的 sort.Slice 写起来非常舒服:

用 Golang 写一个365家常菜小视频的爬虫与推荐引擎

sort.Slice(videos, func(i, j int) bool {
    return videos[i].SeasonScore > videos[j].SeasonScore
})

实际跑起来会踩哪些坑?

我必须要诚实地告诉你——理想很丰满,现实有弹窗

  1. 反爬虫:很多平台的“365家常菜小视频”页面做了 UA 检测和 Cookie 验证,你可以用 Go 的 chromedp 无头浏览器库模拟真实用户,但速度会慢 3-5 倍,折中方案:伪造 User-Agent 池并加上 Referer 头,成功率能到 70% 左右。

  2. 视频播放链接:有些站点的视频地址不是直接给的,而是通过 JS 解密得到的,这时候 Go 的 goja 库可以解析并执行简单 JS,但复杂加密就得另想办法了,我上次遇到一个用 window.atob 加密的,直接硬解码 Base64 搞定(别笑,真有这种)。

  3. 数据量:365天,每天就算只产出一条视频,一年也就 365 条,但“365家常菜小视频”并不是真的只有365条——它是个品牌,内容库可能有上万条,用 Go 写的时候,内存占用 是个变量,最好用 bufio 按行写入文件,别一次性把全部视频塞到切片里,我就干过这种事,8GB 内存跑满后程序被 OOM kill 了。

怎么保存?JSON 还是 SQLite?

我个人习惯先存 JSON,因为容易调试,看一段“365家常菜小视频”的数据长什么样:

[
  {
    "id": 2048,: "不用烤箱的奥尔良烤翅",
    "cook_type": "煎",
    "plays": 342000,
    "likes": 18900,
    "tags": ["鸡翅", "空气炸锅", "无油"]
  },
  {
    "id": 4096,: "冬天必吃的番茄牛腩煲",
    "cook_type": "炖",
    "plays": 512000,
    "likes": 29500,
    "tags": ["暖身", "番茄", "高压锅"]
  }
]

但如果数据量超过 10 万条,JSON 的随机查询效率就很低了,这时候可以用 mattn/go-sqlite3 包,直接在本地建个 SQLite 库,用 SQL 语句查“播放量最高的 10 个素菜”比手写遍历快得多。

最后的真实感

写到这里,我得坦白:我一边写这篇文章,一边还在跑一个“365家常菜小视频”的爬虫,刚才输出日志显示第 47 页超时了,我正手动调整 timeout 参数到 15 秒,Golang 的 http.Client 默认没有超时,你得自己设置:

client := &http.Client{
    Timeout: 10 * time.Second,
}

这个细节坑过我两次,所以用粗体标出来,你可别忘。

工具写好了,你可以每天定时跑一次,把新视频追加进本地库,然后写个终端菜单:输入“凉菜”就列出所有凉菜视频信息,输入“最火”按播放量排序,哪怕只是自己用,那种 东西握在手里 的感觉,比刷算法推荐页爽多了。

本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://www.uss1.cn/lvyou/995.html

(4)

文章推荐

发表回复

本站作者才能评论

评论列表(4条)

  • kyadmin
    kyadmin 2026-07-01

    我是be365的签约作者“kyadmin”!

  • kyadmin
    kyadmin 2026-07-01

    希望本篇文章《用 Golang 写一个365家常菜小视频的爬虫与推荐引擎》能对你有所帮助!

  • kyadmin
    kyadmin 2026-07-01

    本站[be365]内容主要涵盖:be365,be365网站,be365网址,ball365体育,Be365排名

  • kyadmin
    kyadmin 2026-07-01

    本文概览:你刷着“365家常菜小视频”的时候,会不会想:这些视频到底怎么被推荐到我首页的?或者更实际点——我想在本地用代码把所有家常菜视频的标题...

    联系我们

    工作时间:周一至周五,9:30-18:30,节假日休息

    关注我们