下载新浪博客全部博文的油猴浏览器脚本

2024-02-18 中文

技术

浏览器脚本

使用此文章的几个脚本,可以获取单个新浪博客用户的博文列表,并全部下载,再合并成一个PDF,可包含图片和目录。

前言

本篇文章会介绍如何下载新浪博客文章到PDF,下载内容包括图片,可带目录。

需要有一定的前端编程和浏览器知识,如果没有的话,建议找一个会的朋友帮你下载。

获取文章列表,存入localStorage

在新浪博客找到要保存的用户的主页,在主页点击“博文目录”,在此页按下 F12 打开 console ,输入以下代码。

var list = document.querySelectorAll("div.articleCell.SG_j_linedot1");
var articles = [];
for (let i = 0; i < list.length; i++) {
    let pList = list[i].querySelectorAll("p");
    let a = pList[0].querySelector(".atc_title a");
    let b = pList[1].querySelector(".atc_tm.SG_txtc");
    let obj = {
        title: a.innerHTML,
        link: a.href,
        time: b.innerHTML
    };
    articles.push(obj);
}
console.log(JSON.stringify(articles))

然后 console 里面会显示拿到的本页的博文的清单,如果博主的博文超过50篇,那接下来就要点击“下一页”以保存下一页的博文清单。

请自己翻页,然后每一页执行一次,再手动合并成一个 Array ,如果你不会这一步,可能这篇教学不太适合你。

//把文章列表写成JSON
articleJSON = {list: [
  {
    title: "文章标题",
    link: "文章链接",
    time: "发表时间"
  },
  {
    title: "文章标题",
    link: "文章链接",
    time: "发表时间"
  },
  ...
];
//存入localStorage
localStorage.setItem("articleJSON", JSON.stringify(articleJSON));
localStorage.setItem("curArticleNum", 0);

设置下载文件夹,关闭浏览器询问

新建一个文件夹,把浏览器的默认下载文件夹设置成这个文件夹,然后关闭“每次下载都询问保存位置”。

此外,在执行下一部分代码的时候,浏览器一定会提示“已阻止网站自动下载”,此时需要眼疾手快地点开提示,改成“允许下载”。

遍历文章列表,下载每一篇文章

打开博主的最新一篇博文详情页,不要打开其他新浪博客域名的页面,放在这里别动。

在tampermonkey新建脚本,输入以下代码并保存。

// ==UserScript==
// @name         Download Sina blog
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://blog.sina.com.cn/s/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=sina.com.cn
// @grant        none
// ==/UserScript==

//参考文章
//https://blog.csdn.net/qq_45677671/article/details/125905454
//【JS】将字符串保存成文件到本地(.txt、.json、.md...)

(function() {
    'use strict';
//如果准备好了,就把这个return注释掉,脚本就会执行了
return;
var articleJSON = localStorage.getItem("articleJSON");
articleJSON = JSON.parse(articleJSON);
var articleList = articleJSON.list;
var curArticleNum = localStorage.getItem("curArticleNum");
var curArticle = articleList[curArticleNum];
//间隔3秒下载一篇
setTimeout(function() {
  //获取标题
    var title = document.querySelector("h2");
    var stringData = `<h2>${title.innerHTML}</h2>\n<p>${curArticle.time}</p><div>`;
  //获取正文
    stringData += document.querySelector("#sina_keyword_ad_area2").innerHTML +"\n</div>\n";
    //stringData 表示要转换的字符串数据,type 表示要转换的数据格式
    const blob = new Blob([stringData], {
        type: "text/plain;charset=utf-8"
    });
    // 根据 blob生成 url链接
    const objectURL = URL.createObjectURL(blob);
    // 创建一个 a 标签Tag
    const aTag = document.createElement('a');
    // 设置文件的下载地址
    aTag.href = objectURL;
    // 设置保存后的文件名称
  //padStart用来给文件名前面补0,想要几位数,就在第一个参数写几
  //但是padStart只能作用于字符串,所以要先toString()
  //以下是三位数字的例子,eg:001.txt, 002.txt
    var fileName = (curArticleNum+1).toString();
    aTag.download = fileName.padStart(3, '0')+".txt";
    // 给 a 标签添加点击事件
    aTag.click();
    // 释放一个之前已经存在的、通过调用 URL.createObjectURL() 创建的 URL 对象。
    // 当你结束使用某个 URL 对象之后,应该通过调用这个方法来让浏览器知道不用在内存中继续保留对这个文件的引用了。
    URL.revokeObjectURL(objectURL);
  //在localStorage更新进度
  curArticleNum++;
    localStorage.setItem("curArticleNum", curArticleNum);
  //全下载完了就return
  if(curArticleNum==articleList.length)return;
  //没下载完则进入下一篇的页面
  var nextArticle = articleList[curArticleNum];
  window.location = nextArticle.link;
}, 3000);
})();

刷新刚才的博文详情页,代码就会开始执行,遍历文章列表,下载所有文章的html为txt,保存到你的电脑上。

执行完之后记得把脚本的return的注释删掉,或者直接把整个脚本关掉,不然下次打开任何一个新浪博客的页面,它又会自动执行。

合并文章为一个txt文件

使用命令行将所有txt文件合并成一个txt文件。

type *.txt>index.txt

有的人可能会想,为什么不直接累加保存在localStorage里,最后再存成一个txt,10篇以内也许可以,再多我就建议你不要这么做哈。

复制html到浏览器,替换图片链接

打开新浪博客的任意一个页面,在 console 里面输入

document.querySelector("body").innerHTML = "";

清除该页body里的所有HTML之后,再点开 elements ,把合并后的TXT文件里的html复制粘贴到该页的body里面。

为什么要这样做呢?因为新浪博客的图片链接只能在新浪博客的页面才能显示图片,为了能把图片也下载下来,我们需要用这种方式。

此时有些图片不显示,这是因为之前我们设置的每一篇的下载间隔为3秒,如果该篇博客包含了很多图片,3秒可能不够全部加载,此时新浪博客有一个缓冲加载图片的机制,会导致我们下载下来的html里面的图片不显示,解决办法是从图片标签里获取到真正的图片链接,并替换缓冲的图片链接。

var allImg = document.querySelectorAll("img");
for (let i = 0; i < allImg.length; i++) {
    let real_src = allImg[i].getAttribute("real_src");
    allImg[i].src = real_src;
}

然后图片就能显示了。

给文章标题添加id

var h2All = document.querySelectorAll("h2");
for (let j = 0; j < h2All.length; j++) {
    let num = (j+1).toString();
    h2All[j].id = num.padStart(3, '0');
}

给整个页面添加博客目录功能区

var articleJSON = localStorage.getItem("articleJSON");
articleJSON = JSON.parse(articleJSON);
var list = articleJSON.list;
var html = `<style>html,body{width:800px;font-size:16px;word-break:break-all;}body{margin:0 10px;}img{max-width:680px;}</style><div id="menu"><style>#menu a{font-weight:bold;text-decoration:none;}#menu span{font-size: 14px;color:silver;}</style><h3>目录</h3>`;
for (let i = 0; i < list.length; i++) {
    let num = (i+1).toString();
    html += `<p><a href="#${num.padStart(3, '0')}" target="_self">${list[i].title}</a><br><span>${list[i].time}</span></p>`;
}
html+="</div>"
var container = document.createElement("div");
container.innerHTML = html;
document.querySelector("body").prepend(container);

经过测试,超过一百篇的时候,需要几秒钟的时间,等一等就好。

保存整个页面为PDF

使用浏览器自带的“打印到PDF”功能,我们可以保存整页为PDF,完成。

经过测试,文章数量多,且包含的图片多的时候,打印预览窗口弹出的速度会比较慢,等一等就可以了。

全文完。

Load Comments