爬虫新姿势——使用Chrome Devtools写一个小说爬虫

目前,绝大部分的爬虫教程都是基于Python和Node.js。其实,只要有Chrome浏览器,使用Chrome F12打开的的Devtools就能随时随地轻轻松松写一个爬虫,完全不用装其它语言环境。今天就介绍一下只使用Chrome Devtools来爬取网站www.biqudu.com/31_31729/小说并保存为文本文件的爬虫。

如何在Chrome Devtools里面写爬虫代码

Devtools提供了Snippets功能让我们可以在这里写JavaScript代码,步骤参考下图:

步骤说明

  1. 打开source标签

  2. 左侧选择Snippets标签

  3. 点击New Snippets新建一个Snippets

  4. 开始写代码

  5. 点击运行代码

  6. 查看控制台输出


准备爬虫工具函数

1.加载第三方库

根据Url加载一个第三方库,可以用这个函数加载jquery,underscore等工具库,加载完成后就可以在代码中使用这些库了,本例中使用这个函数加载async异步并发控制库。

复制代码
async function loadLibrary(url) {
    return new Promise((resolve, reject) => {
        let script = document.createElement('script');
        script.onload = resolve;
        script.onerror = reject;
        script.src = url;
        document.body.appendChild(script);
    });
}

2.下载文件到本地

将string下载到文本文件

复制代码
function saveFile(string, fileName) {
    var a = document.createElement('a');
    a.download = fileName;
    var blob = new Blob([string], {
        type: 'text/plain'
    });
    a.href = window.URL.createObjectURL(blob);
    a.click();
}

3.下载HTML

使用了Fetch api,根据url下载一个html文本文件并转换成DOM元素后返回,返回的元素具有DOM api,例如 querySelector,方便对节点的提取和分析。

复制代码
async function getHtml(url) {
    let response = await fetch(url);
    let htmlText = await response.text();
    let html = document.createElement('html');
    html.innerHTML = htmlText;
    return html;
}

准备爬虫业务函数

1.获取小说的所有章节信息

分析小说主页www.biqudu.com/31_31729/,

通过document.querySelectorAll('#list dd a') 可以获取包含所有章节名称和链接的a标签元素。

复制代码
async function getDirectory(url) {
    let page = await getHtml(url);
    let directory = Array.from(page.querySelectorAll('#list dd a'));
    //去除顶部最新12个章节
    return directory.slice(12);
}

2.获取一个章节的内容

分析小说章节 www.biqudu.com/31_31729/21...,章节内容位于ID为content的DIV元素中

复制代码
async function getSection({ href, innerText: title }) {
    console.log(`开始获取 ${title}`);
    let html = await getHtml(href);
    let content = html.querySelector('#content');
    Array.from(content.querySelectorAll('script')).forEach(scriptTag => content.removeChild(scriptTag));
    var text = title + '\r\n' + content.innerText + '\r\n';
    return text;
}

完整代码

因为小说有几百几千章节,不可能一个一个章节下载,那样速度太慢了。也不能一下子全下载。所以

爬取时使用了async异步并发控制库(这个async和async function里面的async只是名字一样而已),并发数量为6,设置大了也没用因为Chrome浏览器对同一域名下的同时请求数量是6。

完整代码运行步骤

  1. Chrome浏览器打开小说主页如:www.biqudu.com/31_31729/

  2. 在小说主页页面打开Devtools 新建snippets并将下面的完整代码粘贴进去

  3. 点击运行代码开始爬取小说

    (async function () {
    // https://www.biqudu.com/31_31729/
    async function loadLibrary(url) {
    return new Promise((resolve, reject) => {
    let script = document.createElement('script');
    script.onload = resolve;
    script.onerror = reject;
    script.src = url;
    document.body.appendChild(script);
    });
    }

    复制代码
     function saveFile(string, fileName) {
         var a = document.createElement('a');
         a.download = fileName;
         var blob = new Blob([string], {
             type: 'text/plain'
         });
         a.href = window.URL.createObjectURL(blob);
         a.click();
     }
    
     async function getHtml(url) {
         let response = await fetch(url);
         let htmlText = await response.text();
         let html = document.createElement('html');
         html.innerHTML = htmlText;
         return html;
     }
    
     async function getDirectory(url) {
         let page = await getHtml(url);
         let directory = Array.from(page.querySelectorAll('#list dd a'));
         //去除顶部最新12个章节
         return directory.slice(12);
     }
    
     async function getSection({ href, innerText: title }) {
         console.log(`开始获取 ${title}`);
         let html = await getHtml(href);
         let content = html.querySelector('#content');
         Array.from(content.querySelectorAll('script')).forEach(scriptTag => content.removeChild(scriptTag));
         var text = title + '\r\n' + content.innerText + '\r\n';
         return text;
     }
    
     async function run() {
         let asyncLibUrl = 'https://cdn.bootcss.com/async/2.1.4/async.js';
         await loadLibrary(asyncLibUrl);
         let directory = await getDirectory(location.href);
         let q = window.async.queue(async function (section, taskDone) {
             try {
                 section.text = await getSection(section);
             } catch (e) {
                 console.error(e);
                 section.text = "章节下载失败:" + e;
             } finally {
                 taskDone();
             }
         }, 6);//并发送设成6
    
         q.drain = function () {
             let name = document.querySelector('#maininfo h1').innerText + '.txt';
             console.log(`小说《${name}》下载完成`);
             let content = "";
             directory.forEach(function ({ text }) {
                 content += text;
             });
             saveFile(content, name);
         }
    
         q.push(directory);
     }
    
     await run();

    }());

相关推荐
谈不譚网安4 分钟前
CSRF请求伪造
前端·网络安全·csrf
夜夜敲码6 分钟前
C语言教程(十六): C 语言字符串详解
c语言·开发语言
帅云毅8 分钟前
Web3.0的认知补充(去中心化)
笔记·学习·web3·去中心化·区块链
豆豆8 分钟前
day32 学习笔记
图像处理·笔记·opencv·学习·计算机视觉
TT模板10 分钟前
苹果cmsV10主题 MXonePro二开优化修复开源版
前端·html5
拖孩11 分钟前
【Nova UI】十一、组件库中 Icon 组件的测试、使用与全局注册全攻略
前端·javascript·vue.js·ui·sass
爱吃泡芙的小白白11 分钟前
爬虫学习——使用HTTP服务代理、redis使用、通过Scrapy实现分布式爬取
redis·分布式·爬虫·http代理·学习记录
宋康13 分钟前
C语言结构体和union内存对齐
c语言·开发语言
去伪存真16 分钟前
不用动脑,手把手跟着我做,就能掌握Gitlab+Jenkins提交代码自动构部署
前端·jenkins
逢生博客18 分钟前
使用 Python 项目管理工具 uv 快速创建 MCP 服务(Cherry Studio、Trae 添加 MCP 服务)
python·sqlite·uv·deepseek·trae·cherry studio·mcp服务