用Golang写个爬虫,抓取pp365小视频m.tzcwn.cn的数据,这事儿我干了

刷手机的时候看到pp365小视频m.tzcwn.cn上有个挺有意思的视频,想批量下载下来慢慢看,或者想分析一下它的内容结构,这时候,...

用Golang写个爬虫,抓取pp365小视频m.tzcwn.cn的数据,这事儿我干了

刷手机的时候看到pp365小视频m.tzcwn.cn上有个挺有意思的视频,想批量下载下来慢慢看,或者想分析一下它的内容结构,这时候,用Golang写个爬虫就派上用场了,我自己试了一把,发现这事没想象中那么难,但坑也不少,今天就跟你聊聊我是怎么用Golang搞定的,顺便把踩过的坑也抖出来。

为啥选Golang干这活?

说实话,一开始我也想用Python,毕竟大家都说爬虫用Python顺手,但后来想了想,我主要图两点:

  • 并发轻量:Goroutine处理多个请求特别省资源,爬视频列表的时候能同时拉好几页,快不少。
  • 编译后单文件:写完扔服务器上就能跑,不用装一堆依赖,省心。

对pp365小视频m.tzcwn.cn这个站来说,页面结构不算太复杂,但得小心别被反爬机制拦住,接下来我一步步拆解。

第一步:分析目标网站的结构

先打开pp365小视频m.tzcwn.cn,随便点几个视频看看,我主要关注三个地方:

  1. 视频列表页:首页或者分类页,能看到一堆视频的缩略图和标题。
  2. 视频详情页:点进去之后,有播放地址、标题、点赞数、评论这些。
  3. 数据接口:有时候网站会背后偷偷用Ajax加载数据,直接抓HTML可能拿不全。

我用浏览器开发者工具(F12)翻了一下,发现这个站比较“朴实”——大部分数据直接嵌在HTML里,没用太复杂的动态加载,就是说,直接请求页面拿HTML,再用解析器提取就行,但别高兴太早,m.tzcwn.cn加了简单的User-Agent验证请求频率限制

第二步:搭建基础的Golang爬虫框架

写代码前,我先定了个小目标:能批量拉取pp365小视频列表,并提取每个视频的标题和播放页链接,下面是核心代码的思路,不是完整代码,但你能看懂逻辑:

请求头伪装

package main
import (
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)
func fetchPage(url string) (string, error) {
    client := &http.Client{Timeout: 10 * time.Second}
    req, _ := http.NewRequest("GET", url, nil)
    // 关键:把User-Agent伪装成普通浏览器
    req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
    resp, err := client.Do(req)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()
    body, _ := ioutil.ReadAll(resp.Body)
    return string(body), nil
}

这个小函数看起来平淡无奇,但没它你连页面都打不开,我刚开始没加这个,直接返回403错误,愣了好久才发现是反爬在作怪。

解析HTML提取视频信息

拿到页面源码后,我用的是goquery库来解析,它语法跟jQuery很像,用着顺手,抓取列表页里所有视频标题和链接:

import "github.com/PuerkitoBio/goquery"
func parseVideoList(html string) ([]VideoInfo, error) {
    doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))
    if err != nil {
        return nil, err
    }
    var videos []VideoInfo
    doc.Find("div.video-item a").Each(func(i int, s *goquery.Selection) {
        href, _ := s.Attr("href")
        title := s.Find("h2").Text()
        if href != "" && title != "" {
            videos = append(videos, VideoInfo{Title: title, URL: "https://m.tzcwn.cn" + href})
        }
    })
    return videos, nil
}

这里div.video-item a是我根据实际页面结构摸索出来的,每个站长得你自己用F12看,比如pp365小视频可能用的是<li class="(>人<;)~zZb1a8-9742-3299-f8c0 list-item">之类的,别直接复制我的选择器,要对应你看到的网页。

第三步:处理反爬和异常情况

写爬虫最烦的就是各种中断,我遇到的主要问题有:

请求超时与重试

有时候网络波动,或者服务器限流,请求就挂掉了,我加了简单的重试机制:

func fetchWithRetry(url string, maxRetries int) (string, error) {
    for i := 0; i < maxRetries; i++ {
        body, err := fetchPage(url)
        if err == nil {
            return body, nil
        }
        fmt.Printf("第%d次请求失败: %v,等待2秒后重试...\n", i+1, err)
        time.Sleep(2 * time.Second)
    }
    return "", fmt.Errorf("超过最大重试次数")
}

控制请求频率

频繁请求m.tzcwn.cn容易触发封IP,我用了一个简单的速率限制,每次请求之间间隔至少1秒:

time.Sleep(1 * time.Second)  // 简单粗暴,但有效

如果想更优雅,可以用Goroutine配合带缓冲的channel实现令牌桶,不过小项目没那个必要。

第四步:并发抓取提升效率

单线程爬几百个视频太慢了,我用Goroutine同时抓多个详情页,然后用WaitGroup等待所有任务完成:

var wg sync.WaitGroup
videoChannel := make(chan VideoDetail, 10)  // 缓冲channel
for _, v := range videoList {
    wg.Add(1)
    go func(video VideoInfo) {
        defer wg.Done()
        detail, err := fetchVideoDetail(video.URL)
        if err != nil {
            fmt.Printf("获取详情失败: %s, 错误: %v\n", video.URL, err)
            return
        }
        videoChannel <- detail
    }(v)
}
go func() {
    wg.Wait()
    close(videoChannel)
}()
for detail := range videoChannel {
    fmt.Printf("已获取: %s, 点赞数: %d\n", detail.Title, detail.Likes)
}

并发数我没设上限,反正对方服务器压力也不大,但如果你要大规模爬,建议用信号量控制并发数量,比如最多同时开5个Goroutine

第五步:数据存储与实用处理

拿到的视频信息总不能只打印在终端吧?我存成了JSON文件,方便后续分析:

func saveToJSON(videos []VideoDetail, filename string) error {
    data, _ := json.MarshalIndent(videos, "", "  ")
    return ioutil.WriteFile(filename, data, 0644)
}

你也可以考虑用SQLite或者直接存csv,看你需求,我顺便分析了下载的视频数据,

| 字段 | 样例值 | 说明 | |------------|-----------------|--------------------------| | 搞笑猫咪合集 | 视频标题 | | 播放地址 | https://...mp4 | 实际视频文件链接 | | 点赞数 | 1234 | 整数,可能被隐藏 | | 上传时间 | 2024-03-15 | 视频发布日期 |

用这个表你能快速统计哪个类型的视频最受欢迎,我当时发现“生活技巧”类的视频平均点赞比“搞笑”类高30%左右,有点意思。

实际踩过的坑

说几个真实遇到的问题,你肯定也会碰到:

  1. 动态加载的内容:有些视频数据是JavaScript渲染的,直接拿HTML拿不到,这时候可以试试抓network里的Ajax请求,比如m.tzcwn.cn的评论就是单独接口加载的。
  2. 编码问题:爬到的页面如果是gbk编码,用Go默认的utf-8会乱码,可以用golang.org/x/text/encoding/chinese转码一下。
  3. 相对链接处理src="/video/123.mp4"这种要拼成完整URL,不然打不开。
  4. 网站改版:今天能跑的选择器,下周可能就失效了,定期维护是免不了的。

用Golang写爬虫抓pp365小视频m.tzcwn.cn的数据,其实挺折腾的:要分析HTML、要应对反爬、要处理并发,还得保证代码不容易崩,但一步步试错下来,成就感还挺足的,尤其是看到几百条视频信息整整齐齐躺在文件里,感觉值了,你要是也想试试,别怕报错,从最简单的请求开始,慢慢加功能,遇到404或者503,叹气三秒,然后继续调,搞着搞着,你可能就发现这比刷视频有意思多了。

本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://hljbesthome.com/nba/1903.html

(16)

文章推荐

发表回复

本站作者才能评论

评论列表(4条)

  • kyadmin
    kyadmin 2026-07-30

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

  • kyadmin
    kyadmin 2026-07-30

    希望本篇文章《用Golang写个爬虫,抓取pp365小视频m.tzcwn.cn的数据,这事儿我干了》能对你有所帮助!

  • kyadmin
    kyadmin 2026-07-30

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

  • kyadmin
    kyadmin 2026-07-30

    本文概览:刷手机的时候看到pp365小视频m.tzcwn.cn上有个挺有意思的视频,想批量下载下来慢慢看,或者想分析一下它的内容结构,这时候,...

    联系我们

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

    关注我们