【爬虫教程】从零开始写一个表情包爬虫二
发布于 7 年前 作者 merrynode 3943 次浏览 来自 分享

第一部分我们已经完成了表情包链接的获取,接下来我们开始批量下载表情包到本地。

下载表情包到本地

观察表情包地址我们发现表情包后面22位就是它完整且唯一的文件名。

我们首先判断本地是否存在这个文件,如果存在则跳过下载,如果不存在, 我们就创建一个可写的文件 stream ,然后请求表情包地址,并 pipestream, 监听 close 事件,触发时完成Promise

function downloadMeMe (url) {
        console.log(`下载: ${url}`);
        let filePath = `./memes/${url.substr(-22)}`;    // 取到后22位作为文件名
        let stream   = fs.createWriteStream(filePath);  // 创建一个可写 stream 对象
        // 请求表情包地址,并 pipe 到刚才创建的 stream 对象
        request.get(url).pipe(stream);
}

限流器

假设我们打开表情包页面,他会同时请求一整页的表情包,所以我们只需要限制批量请求之间的间隔就好。 写个限流器,控制单次请求数,访问频率过快会导致爬虫被发现。你也可以设置随机延时。

function timerChunk(any, fn, limit, wait = 0) {
    let run = async function () {
        if (!any.length) {
            return;
        }

        // 延时等待 这里是随机0到wait毫秒
        await (new Promise((resolve, reject) => setTimeout(resolve, ~~(Math.random() * wait))));

        let params = any.splice(0, limit);              // 每次取出 limit 数量的任务
        params.forEach((param) => fn(param));
        return run();
    }

    return run();
}

组装函数

最后步骤就是搭积木把函数拼起来

(async function crawler() {
    let keyword = '单身狗';
    try {
        // 获取该关键字所有的表情包链接
        let links = await getLinksByPage(keyword, 1);
        // 下载表情包到本地
        await timerChunk(links, downloadMeMe, 5, 3000);
        console.log('完成!');
    } catch (err) {
        console.error(err);
    }
})();

我们来运行下我们的项目

完整代码

回到顶部