Endless Baidu

去除百度广告和免翻页自动加载搜索结果.

当前为 2020-04-09 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name            Endless Baidu
// @description     去除百度广告和免翻页自动加载搜索结果.
// @author          zhengshangchao
// @namespace       [email protected]
// @icon            https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcQFx1p53_ITBIbIJ01mkd-9whP3CvzIwrNiUKjqeC2G5XvHg2Uk&usqp=CAU
// @include         http://www.baidu.com*
// @include         https://www.baidu.com*
// @run-at          document-start
// @version         0.0.2
// @license         MIT
// @noframes
// ==/UserScript==

// 不能用于百度图片搜索
if (location.href.indexOf("tn=baiduimage") !== -1) {
    return;
}

// 不能运行在iframes内嵌的场景
if (window.top !== window.self) {
    return;
}
// 搜索结果区
const centerElement = "#container";
// 加载窗口的权重值
const loadWindowSize = 1.6
// 尾部的谷歌声明和翻页部分元素
const filtersAll = ["#page","#content_right","#rs", "#rs_top_new", ".head_nums_cont_outer"];
const filtersCol = filtersAll.concat(["#content_bottom"]);
let   msg = "";

const css = `
.page-number {
  position: relative;
  display: flex;
  flex-direction: row-reverse;
  align-items: center;
	margin-bottom: 2em;
	color: #808080;
}
.page-number::before {
  content: "";
  background-color: #ededed;
  height: 1px;
  width: 90%;
  margin: 1em 3em;
}
.endless-msg {
  position:fixed;
  bottom:0;
  left:0;
  padding:5px 10px;
  background: darkred;
  color: white;
  font-size: 11px;
  display: none;
}
.endless-msg.shown {
  display:block;
}
`;

let pageNumber = 0;
let prevScrollY = 0;
let nextPageLoading = false;

function requestNextPage() {
    nextPageLoading = true;
    // 将当前页的超链接作为下一页初始化的值
    let nextPage = new URL(location.href);
    // 如果没有查询参数就直接返回
    if (!nextPage.searchParams.has("wd")) return;
    // 请求下一页的页码
    nextPage.searchParams.set("pn", String(pageNumber * 10));
    !msg.classList.contains("shown") && msg.classList.add("shown");
    // 请求下一页
    fetch(nextPage.href)
        .then(response => response.text())
        // 提取请求下一页的返回结果
        .then(text => {
            // 新建dom解析器
            let parser = new DOMParser();
            // 解析并提取text/html
            let htmlDocument = parser.parseFromString(text, "text/html");
            // 尾页处理
            if (!hasNextPage(htmlDocument.querySelector("#page"))) {
                // 则说明搜索结果不需要再翻页了,移除鼠标滚动事件
                window.removeEventListener("scroll", onScrollDocumentEnd);
                // 翻页的布尔值设置为false
                nextPageLoading = false;
                // 如果包含shown的元素则移除
                msg.classList.contains("shown") && msg.classList.remove("shown");
                return;
            }
            // 解析并提取搜索页的结果
            let content = htmlDocument.documentElement.querySelector(centerElement);
            // 拼接center_col的div的id
            content.id = "col_" + pageNumber;
            // 过滤掉content中不要的元素,比如翻页栏和百度的相关搜索
            filter(content, filtersCol);
            // 新建div元素 作为分页间的分割线
            let pageMarker = document.createElement("div");
            // 设置页码+1
            pageMarker.textContent = String(pageNumber + 1);
            // 设置class
            pageMarker.className = "page-number";
            // 创建div
            let col = document.createElement("div");
            // 设置next-col作为下一页内容的存放容器
            col.className = "next-col";
            // 添加页码分割线作为子元素
            col.appendChild(pageMarker);
            // 添加下一页的内容作为子元素
            col.appendChild(content);
            // 找到centerElement后并添加next-col的div
            document.querySelector(centerElement).appendChild(col);
            // 执行一次页面自增1
            pageNumber++;
            // 下一页翻页置为false
            nextPageLoading = false;
            // 如果包含分割线的样式则移除
            msg.classList.contains("shown") && msg.classList.remove("shown");
        });
}

/**
 * 鼠标滚动事件触发翻页动作
 */
function onScrollDocumentEnd() {
    // 记录当前鼠标滚动的时候的坐标y值
    let y = window.scrollY;
    // 滚动窗口与上个滚动窗口的差值
    let delta = y - prevScrollY;
    // 如果下一页没加载且滚动差值大于0且当前窗口滚动值超过body的高度值则触发翻页
    if (!nextPageLoading && delta > 0 && isDocumentEnd(y)) {
        // 请求下一页
        requestNextPage();
    }
    // 将上一页的窗口y值暂存
    prevScrollY = y;
}

/**
 * 鼠标滚动事件触发翻页动作
 */
function isDocumentEnd(y) {
    // 当窗口内在高度和当前滚动高度值*1.6的和大于浏览器body可见区域的高度
    return y + window.innerHeight * loadWindowSize >= document.body.clientHeight;
}

/**
 * 在指定的div元素中移除不需要的元素
 */
function filter(node, filters) {
    for (let filter of filters) {
        let child = node.querySelector(filter);
        if (child) {
           child.hidden = true;
        }
    }
}

/**
 * 如果翻页显示没有【下一页】的话证明是尾页
 */
function hasNextPage(node) {
    // 是否有下一页
    let hasNextPage = true;
    for (let page of node.children) {
       if(page.textContent.indexOf("下一页") == -1) {
           hasNextPage = false;
       }
       if(page.textContent.indexOf("下一页") == 0) {
           hasNextPage = true;
       }
    }
    return hasNextPage;
}

/**
 * 初始化
 */
function init() {
    // 当前窗口鼠标滚动的高度值
    prevScrollY = window.scrollY;
    // 添加鼠标滚动事件的回调方法
    window.addEventListener("scroll", onScrollDocumentEnd);
    // 过滤掉不需要的元素
    filter(document, filtersAll);
    // 创建样式元素
    let style = document.createElement("style");
    // 指定元素类型为css
    style.type = "text/css";
    // 添加css为文本节点
    style.appendChild(document.createTextNode(css));
    // 将css样式元素添加到document的head元素中
    document.head.appendChild(style);
    // 添加div元素
    msg = document.createElement("div");
    // 新增加载下一页的提醒框
    msg.setAttribute("class", "endless-msg");
    // 添加提醒框的提示语
    msg.innerText = "自动加载下一页...";
    // 将提醒框元素添加到document的body中
    document.body.appendChild(msg);
}

// 初始化DOMContentLoaded监听(html文档完全被加载和解析事件)
document.addEventListener("DOMContentLoaded", init);