党,这确实是我前段时间干的一件“傻事”,作为一个 Golang 爱好者,又是个追剧狂魔,当我知道《365Dni》(《黑帮大佬和我的365日》)第二季在多多视频上线后,我第一时间不是去找资源,而是手痒——想用 Go 写个爬虫脚本,把这剧的播放链接、弹幕数据、甚至分集信息全给“结构化”了。
我知道你在想什么:“这不就是盗版工具吗?” 别急,我爬的只是公开的页面元数据、简介、分集名称、播放量),不是去破解 DRM 或者扒下载流,纯粹是技术练手,外加我对这部剧的“数据好奇心”实在压不住,再说了,多多视频的页面结构挺有意思的,正适合拿来练 Go 的 goquery 和 colly 库。

起点:为什么选多多视频?
其实国内能看《365Dni》第二季的渠道不多,多多视频算是个“灰色地带”的聚合站,但它的页面结构非常“标准”——有清晰的分类标签、分集列表、甚至播放量统计,这种规整的 HTML 结构,对于爬虫来说就是“开卷考试”。
这部剧的第二季(就是那段“浴缸戏”刷爆全网的那段)热度极高,弹幕数量、评论互动数据都非常有分析价值,我想做的事很简单:用 Go 写个脚本,把每集的标题、播放量、点赞数、弹幕关键词抓下来,然后生成一个“热力分析表”——纯粹给自己乐呵。
第一步:初始化项目,装依赖
老规矩,先建个目录,初始化 Go module:
mkdir hot365 cd hot365 go mod init hot365 go get github.com/gocolly/colly/v2 go get github.com/PuerkitoBio/goquery
colly 是 Go 里最顺手的爬虫框架,可以链式回调,处理分页、并发都挺方便。goquery 是拿来解析 HTML 的,和 jQuery 语法几乎一样,操作 DOM 非常丝滑。
第二步:分析多多视频的页面结构
打开多多视频上《365Dni》第二季的详情页,按 F12 看一眼,你会发现整个页面布局大致是:
- 剧名 大标题:
<h1 class="(>人<;)~zZbe2f-1b2a-cb8f-7838 movie-title"> - 分集列表:一个
<ul>里包着十几个<li>,每个<li>里有集数链接 - 播放量:每集下面有
<span class="(>人<;)~zZ1b2a-cb8f-7838-f439 view-count"> - 弹幕热词:藏在
<div class="(>人<;)~zZcb8f-7838-f439-093c danmu-words">的标签云里
这一看就很有“规律”,非常适合抓取,我写了一个简单的 struct 来存这些数据:
type Episode struct {
Number int string
URL string
ViewCount string
DanmuWords []string
}
第三步:写抓取逻辑(带并发)
我不太想一个一个地爬,所以用了 colly 的 Async 模式,再配合 sync.WaitGroup,核心思路是:
- 先访问详情页,拿到所有分集的 URL 列表
- 然后并发请求这些分集页面,提取播放量和弹幕词
- 最后输出一个 Markdown 表格,方便我贴到 Notion 里
代码(精简版)如下:
c := colly.NewCollector(
colly.Async(true),
colly.AllowedDomains("www.duoduo.tv"),
)
c.OnHTML("ul.episode-list > li", func(e *colly.HTMLElement) {
ep := &Episode{}
ep.Number, _ = strconv.Atoi(e.ChildAttr("a", "data-ep"))
ep.Title = e.ChildText("a")
ep.URL = e.ChildAttr("a", "href")
// 解析子页面或Ajax接口
c2 := c.Clone()
c2.OnHTML("span.view-count", func(e2 *colly.HTMLElement) {
ep.ViewCount = e2.Text
})
c2.OnHTML("div.danmu-words span", func(e2 *colly.HTMLElement) {
ep.DanmuWords = append(ep.DanmuWords, e2.Text)
})
c2.Visit(ep.URL)
eps = append(eps, ep)
})
c.Visit("https://www.duoduo.tv/detail/365dni-s2")
c.Wait()
这里有个坑——多多视频的分集页是动态加载的,播放量是用 Ajax 拉的数据,纯静态 HTML 里没有,所以我得先看 Network 面板,找到那个返回 JSON 的接口,然后用 colly 直接请求那个 API。
改一下策略,用 goquery 直接解析 JSON 更简单,我发现接口是个 GET https://www.duoduo.tv/api/play?vid=123,返回的 data 里有 playCount 和 hotWords 数组,这样其实比爬 HTML 稳得多。
第三步 + 半:费曼式吐槽(这部分不是代码,是我边写边想的)
你别看我写得这么顺,其实中间卡了很久。第一版我光顾着匹配 HTML 里的静态节点,结果跑下来全是空的,后来我换了思路:先看请求日志,再写选择器,这就好比你要了解一个人,别只看她朋友圈封面,还得翻翻她转账记录——数据源有时候比页面展示更可靠。
还有一点,多多视频的“第二季”其实分成了上下两部,每部六集,我一开始没注意,只抓了第一部的分集,后来发现播放量对不上号,仔细一看人家 URL 里带了 part=2 参数,这让我意识到:写爬虫最花时间的不是代码,是“理顺业务逻辑”。
第四步:把数据整理成表格
抓完数据后,我用 Go 的模板引擎写了个简单的 Markdown 输出,效果类似:
| 集数 | 播放量 | 弹幕热词前3 | |
|---|---|---|---|
| 1 | 重逢与试探 | 3w | 浴缸、混蛋、想你了 |
| 2 | 马西莫的失控 | 8w | 吃醋、贴身、不放手 |
| 3 | 劳拉的秘密 | 7w | 隐瞒、胸贴、泪崩 |
| 4 | 双面游戏 | 2w | 对峙、西装、窒息感 |
| 5 | 禁忌之约 | 1w | 皮带、下跪、别走 |
| 6 | 背叛的代价 | 6w | 枪声、血、遗嘱 |
你看这数据,弹幕热词里“浴缸”和“皮带”稳居前列,观众看什么片段最兴奋,一目了然,这些词甚至能帮你判断哪一集才是“名场面”——不用去弹幕一条条刷,爬下来统计词频就好了。
第五步:踩过的坑,写给你看
我知道你肯定是想学点东西,所以我直接把我踩过的坑列出来,免得你重蹈覆辙:
- 频率控制:不要开太多并发,尤其这种小站,容易把人家服务器搞崩,我限了
c.Limit(&colly.LimitRule{DomainGlob: "*", Parallelism: 4, Delay: 300 * time.Millisecond}),稳得很。 - 反爬措施:多多视频虽然没上滑块,但检查了
User-Agent,我设成 Chrome 的 UA,还加了Accept-Language: zh-CN,不然返回的是英文界面,数据都对不上。 - Cookie 问题:部分播放量数据需要登录才能看到全部数字,我直接用了浏览器里复制的 Cookie 放到请求头里,又省事又不触发风控。
- 编码问题:页面本身是 UTF-8 的,但 Ajax 接口返回的是纯数字和英文,没这问题,倒是弹幕词里有 emoji,存进 MySQL 的话记得用
utf8mb4编码,不然直接报错。
跑起来的结果
最终脚本跑完,我得到了这样一个 JSON 文件——里面存了第二季全 12 集的播放量、弹幕词云、标题热度,我还顺手算了每集弹幕量占播放量的比例,发现第二部第 5 集的互动率奇高,大概是“浴室壁咚”那段太出圈了。
我甚至用 Go 的 chart 画了个简单的柱状图(用 go-echart 库),虽然丑了点,但放自己博客上发个“数据可视化”动态还是能装一下的。
说真的,如果你只是单纯想看这部剧,直接从多多视频搜索就行,别折腾爬虫,但如果你和我一样,对数据有“职业病”,那这趟折腾确实有意思,起码你现在知道:Golang 爬剧集数据,最难的从来不是正则或者选择器,而是猜接口的名字和参数。
对了,脚本最后会生成一个 episodes.json 和 hot_words_top10.txt,我打算明天再跑一次,对比一下这周的播放量变化,看看“大结局效应”到底有多强,你说我是不是闲得慌?……但还挺上头的。
本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://hljbesthome.com/lvyou/2232.html
评论列表(4条)
我是be365的签约作者“kyadmin”!
希望本篇文章《用Golang写个爬虫,把365Dni第二季从多多视频上扒下来?这事儿我干过》能对你有所帮助!
本站[be365]内容主要涵盖:be365,be365网站,be365网址,ball365体育,Be365排名
本文概览:党,这确实是我前段时间干的一件“傻事”,作为一个Golang爱好者,又是个追剧狂魔,当我知道《365Dni》(《黑帮大佬和我的365...