最近练习普通话,于是在网上搜了一下普通话练习60篇,但是没有方便直接下载的,索性就想自己动手抓一下。
在以往我都是用php来爬取的,这次想尝试下用node.js。
于是就开始动手,分析了一下网页源码,发现非常有规律,60篇文章的 url 都是按序号递增的,这就非常简单了,直接用一个循环就可以生成所有的 url 了。
拿到地址后就是获取网页代码,因为现在 node.js 已经支持了fetch, 所以就直接用 fetch 来获取网页源码。这一步骤非常顺利。
拿到源码后就是解析,获取正文了。node.js 应该有县城的 dom 包,于是搜索了一下,找到了jsdom这个强大的包。这样获取内容就不是问题了。于是第一版就完成了,很快就下载好了60篇文章。
每一篇文章都提供了专业的示范朗读音频,我想也应该吧音频下载回来。我想既然使用了 fetch, 那么下载音频文件也用它好了。但是折腾了很久没搞定,最终放弃使用他了。
那就在搜一下看看 node.js 有什么用于下载的包吧。很快搜到了一个叫做download的包,看了下说明,非常简单,就用他好了。
下载音频一切顺利。
于是完整的爬取代码就完成了,普通话练习的60篇文章和示范朗读音频也就自然的搞定了。
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
const fs = require('fs');
const jsdom = require('jsdom');
const download = require('download');
const baseURL = '未知链接http://www.pthxx.com/b_audio/01_langdu_1/';
for(let i = 1; i <= 60; i++) {
let id = i < 10 ? '0' + i : i.toString();
fetch(`${baseURL}${id}.html`)
.then((res) => {return res.text();})
.then((res) => {
const d = new jsdom.JSDOM(res).window.document;
let title = d.querySelector('h2').textContent.trim();
title = title.replace(/《(.+)》示范朗读/, '$1');
let content = d.querySelector('#main2').textContent;
fs.writeFileSync('txt/' + id + title + '.txt', title + content, 'utf8');
console.log(id + title);
let mp3URL = d.querySelector('audio source').src;
console.log(mp3URL);
download(`${baseURL}${mp3URL}`, 'audio', {filename: id + title + '.mp3'});
});
}
|
上面的代码虽然已经能够完成任务,但是看起来还是有些不够漂亮,而且提示信息也不够清晰,于是进行了一次修改,干脆用一下async和await吧。然后在修改过程中遇到了一个生成指定数量元素的数组的问题,搜了一下,找到了一种看起来非常简练的方法。
另外为了在所有下载完毕后输出一个提示,使用了**Promise.all()**方法。
最终的代码如下:
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
|
const fs = require('fs');
const jsdom = require('jsdom');
const download = require('download');
const baseURL = 'http://www.pthxx.com/b_audio/01_langdu_1/';
const main = async function main() {
let ids = Array.from({length: 60}, (_, i) => (i < 9 ? '0' : '') + (i + 1));
await Promise.all(ids.map(async (id) => { return await getContent(id);}));
console.log('全部下载完毕。');
};
const getContent = async function getContent(id) {
let res = await download(`${baseURL}${id}.html`);
const d = new jsdom.JSDOM(res).window.document;
let title = d.querySelector('h2').textContent.trim();
title = title.replace(/《(.+)》示范朗读/, '$1');
let content = d.querySelector('#main2').textContent;
fs.writeFileSync('txt/' + id + title + '.txt', title + content, 'utf8');
console.log(`${id + title}.txt以保存`);
let mp3URL = d.querySelector('audio source').src;
console.log(`开始下载:${id + title}.mp3`);
await download(`${baseURL}${mp3URL}`, 'audio', {filename: id + title + '.mp3'});
console.log(`${id + title}.mp3以保存`);
};
main();
|