一个用node.js写的爬虫脚本--爬取普通话练习朗读60篇

最近练习普通话,于是在网上搜了一下普通话练习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'});
    });
}

上面的代码虽然已经能够完成任务,但是看起来还是有些不够漂亮,而且提示信息也不够清晰,于是进行了一次修改,干脆用一下asyncawait吧。然后在修改过程中遇到了一个生成指定数量元素的数组的问题,搜了一下,找到了一种看起来非常简练的方法。 另外为了在所有下载完毕后输出一个提示,使用了**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();
updatedupdated2022-09-022022-09-02