
刷手机的时候看到pp365小视频m.tzcwn.cn上有个挺有意思的视频,想批量下载下来慢慢看,或者想分析一下它的内容结构,这时候,用Golang写个爬虫就派上用场了,我自己试了一把,发现这事没想象中那么难,但坑也不少,今天就跟你聊聊我是怎么用Golang搞定的,顺便把踩过的坑也抖出来。
为啥选Golang干这活?
说实话,一开始我也想用Python,毕竟大家都说爬虫用Python顺手,但后来想了想,我主要图两点:
- 并发轻量:Goroutine处理多个请求特别省资源,爬视频列表的时候能同时拉好几页,快不少。
- 编译后单文件:写完扔服务器上就能跑,不用装一堆依赖,省心。
对pp365小视频m.tzcwn.cn这个站来说,页面结构不算太复杂,但得小心别被反爬机制拦住,接下来我一步步拆解。
第一步:分析目标网站的结构
先打开pp365小视频m.tzcwn.cn,随便点几个视频看看,我主要关注三个地方:
- 视频列表页:首页或者分类页,能看到一堆视频的缩略图和标题。
- 视频详情页:点进去之后,有播放地址、标题、点赞数、评论这些。
- 数据接口:有时候网站会背后偷偷用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%左右,有点意思。
实际踩过的坑
说几个真实遇到的问题,你肯定也会碰到:
- 动态加载的内容:有些视频数据是JavaScript渲染的,直接拿HTML拿不到,这时候可以试试抓network里的Ajax请求,比如m.tzcwn.cn的评论就是单独接口加载的。
- 编码问题:爬到的页面如果是gbk编码,用Go默认的utf-8会乱码,可以用
golang.org/x/text/encoding/chinese转码一下。 - 相对链接处理:
src="/video/123.mp4"这种要拼成完整URL,不然打不开。 - 网站改版:今天能跑的选择器,下周可能就失效了,定期维护是免不了的。
用Golang写爬虫抓pp365小视频m.tzcwn.cn的数据,其实挺折腾的:要分析HTML、要应对反爬、要处理并发,还得保证代码不容易崩,但一步步试错下来,成就感还挺足的,尤其是看到几百条视频信息整整齐齐躺在文件里,感觉值了,你要是也想试试,别怕报错,从最简单的请求开始,慢慢加功能,遇到404或者503,叹气三秒,然后继续调,搞着搞着,你可能就发现这比刷视频有意思多了。
本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://hljbesthome.com/nba/1903.html
评论列表(4条)
我是be365的签约作者“kyadmin”!
希望本篇文章《用Golang写个爬虫,抓取pp365小视频m.tzcwn.cn的数据,这事儿我干了》能对你有所帮助!
本站[be365]内容主要涵盖:be365,be365网站,be365网址,ball365体育,Be365排名
本文概览:刷手机的时候看到pp365小视频m.tzcwn.cn上有个挺有意思的视频,想批量下载下来慢慢看,或者想分析一下它的内容结构,这时候,...