我的回忆

校园民谣“同桌的你”于1994年由老狼演唱,1995年春节联欢晚会后红遍大江南北,我那时还不到10岁,不确定我当时有没有追上时髦,反正在我还小的年纪(初中?)是很熟悉这首歌的,不过我个人对音乐并没有特别喜欢(五音不全,家里也没有这个氛围),更不知道高晓松是这首歌的作者。

在90年代,还是磁带机的时代,我人生中的第一个磁带机应该是在初中,买磁带机的由头当然是学习英语啦。(新概念英语?) 买磁带机时还买了几盘磁带,现在回想起来,应该有张洪量、张震岳,印象最深的歌曲是《思念是一种病》。

但是查阅资料发现张震岳的《思念是一种病》是2007年才发行的专辑,可能我还是记错了。

如果你也是在这个年代的人,欢迎留言交流。

回过头来,咱们继续说高晓松。

在工作很久以后,随着我的通勤时间增加,总要学习娱乐两不误,所以就找来了高晓松的脱口秀节目,从「晓说」追到「晓松奇谈」。

后来在书店闲逛,又看到了高晓松出版的「鱼羊野史」,翻过几页(到现在也没有继续)。

想听「晓年鉴」

我大概是在2019年年末的时候知道了高晓松联合蜻蜓FM做了一档付费的年鉴类节目「晓年鉴」。

因为要付费就没有听成,不过最近无意之中在微信公众号上发现了免费的音频版本,所以再次激发我的收听兴趣。

「晓年鉴」1969-2019年音频合集(完整版) 该公众号将「晓年鉴」的音频内容放出,可能涉及到版权问题,大家仅供学习交流吧。

每次收听都要去微信公众号上选择某一集再播放,实在是太不方便了。

后面我发现微信读书上也有「晓年鉴」,但是只有前面 25 集。

我能不能把他们下载后导入到 QQ 音乐等音乐播放器中呢?

答案是可以的。

接下来我就分享一下我的解决方案。

怎么听?

听我来给你讲讲操作步骤吧。

  1. 脚本工具(见后文)爬取「晓年鉴」1969-2019年音频合集(完整版)
  2. 解析第一步的页面,得到每一集的链接;
  3. 再通过脚本工具爬取每一集的链接;
  4. 解析第三步的页面,得到每一集的资源ID;
  5. 分析微信公众号的音频文件播放下载资源为一个链接;
  6. 根据第2步、第4步和第5步,得到每一集的资源链接;
  7. 批量下载所有的资源;
  8. 将 mp3 资源通过 airdrop 发送到 iPhone 手机;
  9. 通过 QQ 音乐打开(导入),创建歌单即可播放全集。

脚本工具

通过 Chrome Inspect 获取页面请求的 curl

以下代码通过 https://mholt.github.io/curl-to-go 生成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
func fetchWeChatPage(u string) *http.Response {
	// Generated by curl-to-Go: https://mholt.github.io/curl-to-go
	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		// handle err
		log.Fatal(err)
	}
	req.Header.Set("Authority", "mp.weixin.qq.com")
	req.Header.Set("Cache-Control", "max-age=0")
	req.Header.Set("Upgrade-Insecure-Requests", "1")
	// ... 还有 cookie 什么的,请用你自己的配置
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		// handle err
	}
	return resp
}

func fetchFileID() {
	doc, err := goquery.NewDocumentFromReader(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	doc.Find(".list-paddingleft-2 li p").Each(func(i int, selection *goquery.Selection) {
		href, _ := selection.Find("a").Attr("href")
		txt := selection.Find("a").Text()
		resp2 := fetchWeChatPage(href)
		defer resp2.Body.Close()
		if resp2.StatusCode != 200 {
			log.Fatalf("status code error: %d %s", resp2.StatusCode, resp2.Status)
		}
		doc2, err := goquery.NewDocumentFromReader(resp2.Body)
		if err != nil {
			log.Fatal(err)
		}
		fileid, _ := doc2.Find("mpvoice").Attr("voice_encode_fileid")
		// 这个连接也是查看得到的
		fileURL := fmt.Sprintf("https://res.wx.qq.com/voice/getvoice?mediaid=%s", fileid)
		log.Printf("%s https://res.wx.qq.com/voice/getvoice?mediaid=%s", txt, fileid)
		filepath := fmt.Sprintf("./%s.mp3", txt)
		err = downloadFile(filepath, fileURL)
		if err != nil {
			log.Fatal(err)
		}
		// 避免请求太频繁被封
		<-time.After(1 * time.Second)
	})
}

func downloadFile(filepath, fileURL string) error {
	out, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer out.Close()

	resp := fetchWeChatPage(url)
	defer resp.Body.Close()

	_, err = io.Copy(out, resp.Body)
	if err != nil {
		return err
	}
	return nil
}

代码都很简单,反正能达到目的就可以了嘛。

看看我的实际运行结果:

后续想法

我其实很想把「晓年鉴」中提到的大事,以及电影、音乐都罗列出来,然后再配合我的记忆做一下回顾,但是这个工程量实在是太大了。 纯粹通过收听和笔记的方式太耗时间了,我又开脑洞了,能否通过 Speech To Text 技术批量转换?

如果有人也对此有兴趣的话,欢迎联系我。

我就先来给大家看看识别的结果吧。

以下内容识别自「晓年鉴」发刊词:人类一大步,我的一“晓”步:

1
2
3
4
5
6
7
8
9
"蜻蜓FM的听众大家好我是告诉有日子没在这跟大家聊天了因为忙着各种各样的事情忙得四脚朝天但是在忙呢我心里一直有一个点就是我要忙到这个点就可以了这个店是什么点呢但是个时(confidence=0.959294)
"你披荆斩棘都是在寻找一条前进的道路不知道最后能到哪里吧也许到山顶一到31也许到河边但是总要去看看总要奋斗到自己力所能及的地方不是最后呢其实在干嘛就要干一件事情下所有景50岁以后后腿无所以前追赶时代无水后有个时代没关系我而且我也觉得这些年追赶时代有点迷失了很多东西所以在过另一种人生之前总" (confidence=0.967376)
"总结一下自己这50年的生活以及自己生活的这个世界这个国家就城市周围的这些人想来想去说弄的什么东西呢把它都记录下来趁着自己还能回忆真的自己还没老葫芦还没老年痴呆所以突起个名字就是小所以什么都是小的小说这个小年间小书馆这都是我做的那些小小的事情所以小年鉴燎的是什么呢当然就是小小的我的眼睛看见的世界以及" (confidence=0.967831)
"自己的成长比如说我出生的那一年1969年那一年有一句咏载人类史册的话就这是我个人的一小步但却是全人类的一大步这句话不是我说的是那一年人类第1次登上了月亮那是划时代的人朗走出登月舱所说的Power plant and Equipment也是我走的一小步来我找一下不不是人类的一大步往就是我从我妈的肚子里走到了这个人世间那个时候我小的时候世界也还没了那时候世(confidence=0.968329)
"在革命者不但是学生们在革命这年轻人们在革命者在反站在歌唱而且科技在那个时候也埋下了一条重要的线索就是Internet互联网的鼻祖那时候叫阿爸爸arpanet的一次成功的从大学时50年我的小眼睛看见的世界跟大家好好的聊一聊那一年的我觉得对我以及可能对人类有重大影响的事情已经每年的我觉得最值得纪念的比如也许是一张唱片也是一本书" (confidence=0.971529)
"电影也许诞生了一个人1967年诞生很多人访问上也是哪一年生雷军也是哪年生的那天还去世了很多人还是哈维尔是哪年去世的所以也不一定每年都要讲些什么也许这一年不讲人不讲出生我的国家我的世界我的时代我所生活的这些我看见的东西但是我觉得更有意思的是我们的小年前如果能有好多好多个小我慢慢的拼起来可能拼成一个非常有意思的民间的一个年间" (confidence=0.968801)
"就是明天我讲了之后就特别希望大家也能分分的把自己身边的故事那一年可能你还是个奇葩当然你的爸妈估计是认识了或者一些还没认识你的父亲还年少或者是你们家乡发生了什么非常试的给大家一起把它写出来说出来一起变成一个逐渐出现拼图一样的把这个国家这个世界的每个角落都拼起来让人们来听这个节目同时看到这个节目带来的整个的大家的记忆之后变成我们领先的一个记忆的宝库我觉得这才是这个节目最后我决心来做的更壮的原因因为其实我也很想看我也很想在我说完了我" (confidence=0.965269)
"眼睛看到的世界以后看看各位朋友们只因们的记忆当然我还会参与啊也许用说话的方式去评论因为如果我打字评论人就可能说话是不是处理不是我自己就会亲自去看一起去评论跟大家来也不会在做什么节目我要开始一段崭新的人生所以这可能是最后一个我自己非常想做的一档节目他们从10月14号开始陪伴大家聊一年微信搜索公众号向年间免费收听最新节目内容" (confidence=0.964405)
"你长那么多人没有一个当年的朋友说我曾经让他们纷纷去仁爱的小鸟它的隔壁老王问他清楚地看到那么多人想对你说起张不开口就让我随你去" (confidence=0.961338)

看起来效果一般般,未完待续。。。


背景知识

晓年鉴

《晓年鉴》,由蜻蜓FM与高晓松联合出品首档穿越体漫谈音频节目。 2018年11月5日,高晓松出现在蜻蜓FM内容生态发布会上,宣布与蜻蜓FM联合推出其全新的付费音频节目《晓年鉴》。该节目将于2018年11月14日,即高晓松本人49岁生日当天正式在蜻蜓FM独家开播。 2019年12月4日,《晓年鉴》推出最后一期《尾声》,《晓年鉴》宣告结束。

高晓松家世背景

关系 姓名 备注
外公 张维 深圳大学首任校长、中国工程院院士、中国科学院院士、瑞典皇家工程科学院外籍院士
外婆 陆士嘉 北京航空学院筹建者之一,世界流体力学权威普朗特教授唯一的中国籍博士
外舅公 施今墨 中医临床家、教育家、改革家
舅舅 张克潜 物理电子学与光电子学科学家、清华大学教授兼博导
祖父 高景德 清华大学校长、中国科学院院士、电机工程专家
父亲 高立人 清华大学教授
母亲 张克群 清华大学毕业,师从梁思成,中国著名建筑学家和建筑教育家
继父 黄二陶 毕业于清华大学机械系。开国副总理黄炎培之孙,水利大师黄万里之子

晓说

  • 2012年12月11日 《晓说》
  • 2013年5月10日 《晓说.2》
  • 2014年3月10日 《晓说.3》
  • 2014年7月1日 《晓说.4》

鱼羊野史

  • 2014年3月27日 《鱼羊野史(第一卷)》
  • 2014年8月10日 《鱼羊野史(第二卷)》
  • 2015年4月19日 《鱼羊野史(第三卷)》
  • 2015年8月26日 《鱼羊野史(第四卷)》
  • 2016年1月1日 《鱼羊野史(第五卷)》

晓松奇谈

首创脱口秀讲述模式。

  • 2015年7月1日 《晓松奇谈(第一卷)》
  • 2016年1月1日 《晓松奇谈(第二卷)》

茶歇驿站

一个可以让你停下来看一看,在茶歇之余给你帮助的小站,这里的内容主要是后端技术,个人管理,团队管理,以及其他个人杂想。