BaiduHelper

去除百度搜索结果中的广告并对页面进行美化

// ==UserScript==
// @name         BaiduHelper
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  去除百度搜索结果中的广告并对页面进行美化
// @author       ipuppet
// @run-at       document-start
// @match        https://www.baidu.com/s?*
// @match        https://www.baidu.com/
// @match        https://zhidao.baidu.com/search?*
// @grant        none
// ==/UserScript==
class Helper {
    static randomString(len = 32) {
        let chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz'
        let maxPos = chars.length
        let pwd = ''
        for (let i = 0; i < len; i++) {
            pwd += chars.charAt(Math.floor(Math.random() * maxPos))
        }
        return pwd
    }
}

//TODO: 右侧仪表盘
class Panel {
    panelId = ''

    constructor() {
        this.panelId = Helper.randomString(8)
    }
}

class ADController {
    count = 0
    displayEleId = ''

    constructor() {
        this.displayEleId = Helper.randomString(8)
    }

    /**
     * 显示过滤结果
     */
    display() {
        let box = document.querySelector('.s_tab_inner')
        let content = '已过滤:' + this.count + ' 条广告'
        let ele = document.querySelector('#' + this.displayEleId)
        if (ele) {
            if (ele.innerText.trim() !== content)
                ele.innerText = content
        } else {
            let container = document.createElement('span')
            container.style = 'float:right;margin-right:10px'
            container.id = this.displayEleId
            container.innerText = content
            if (box) box.appendChild(container)
        }
    }

    /**
     * 获取广告元素
     * @returns {[]}
     */
    getAdElements() {
        let ads = []
        //左侧
        let left = document.querySelectorAll('#content_left>div')
        if (left) {
            for (let element of left) {
                let spanList = element.getElementsByTagName('span')
                for (let span of spanList) {
                    if (span.innerText.trim() === '广告') {
                        ads.push(element)
                        break
                    }
                }
            }
        }
        return ads
    }

    /**
     * 其他需要去掉的内容
     */
    getMoreElement() {
        let more = []
        more.push(document.querySelector('::shadow div'))//shadow
        more.push(document.querySelector('#rs'))//底部相关搜索
        more.push(document.querySelector('#content_right'))//右侧内容
        return more
    }

    /**
     * 清除广告
     */
    remove(time = 50) {
        let ads = this.getAdElements()
        let more = this.getMoreElement()
        //去除广告元素
        if (ads.length > 0) {
            for (let element of ads) {
                element.remove()
                this.count++
            }
        }
        //去除其他相关内容
        for (let element of more) {
            if (element) element.remove()
        }
        this.display()
        setTimeout(() => {
            this.remove(time)
        }, time)
    }
}

class BeautifyController {
    style = {
        'body': {
            'width': '100vw',
            'min-width': '10px',
            'margin-left': 'calc(100% - 100vw)',//calc(100vw - 100%)滚动条宽度,反过来就是负数,将整个页面左移
            'background-color': '#f2f2f2',
        },
        '#head': {
            'margin-left': 'calc(100vw - 100%)',
            'background-color': '#f2f2f2',
        },
        '#s_tab': {
            'padding-top': '94px',
        },
        '#container': {
            'width': '100%',
        },
        '#content_left': {
            'padding-left': '140px',
            'padding-right': '140px',
        },
        '.c-container': {//搜索结果条目容器
            'width': 'calc(100% - 60px)',
            'padding': '20px 30px',
            'overflow': 'hidden',
            'border-radius': '10px',
            'background': '#f2f2f2',
            'transition': 'all 100ms cubic-bezier(0.175, 0.885, 0.32, 1.275);',
            'box-shadow': '0px -6px 10px rgba(255, 255, 255, 1), 0px 4px 15px rgba(0, 0, 0, 0.15);',
        },
        '.c-container:hover': {//搜索结果条目容器
            'box-shadow': 'inset 0px -2px 5px white, inset 0px 2px 5px rgba(0, 0, 0, 0.15);',
        },
        '.c-container:not(:first-child)': {//搜索结果条目容器
            'margin-top': '30px',
        },
        '.c-container a:not(.OP_LOG_LINK)': {//搜索结果条目内链接
            'color': '#66ace0',
            'text-decoration': 'none',
        },
        '.c-container a em': {//搜索关键字
            'color': '#d24e6e',
            'text-decoration': 'none',
        },
        '.c-container a:hover': {//搜索结果条目标题
            'text-decoration': 'underline',
        },
        '.c-border': {//翻译等框框
            'width': 'calc(100% - 20px)',
            'border-radius': '10px',
        },
        //品牌广告样式
        '.ec-pl-container': {
            'width': 'calc(100% - 60px)',
            'padding': '20px 30px',
            'overflow': 'hidden',
            'border-radius': '10px',
            'background': '#f2f2f2',
            'box-shadow': '4px 4px 4px 0px #d1d9e6 inset, -4px -4px 4px 0px #ffffff inset;',
        },
        '.ec-pl-container:not(:first-child)': {
            'margin-top': '30px',
        },
        '.ec-pl-container a:not(.OP_LOG_LINK)': {//链接
            'color': '#66ace0',
            'text-decoration': 'none',
        },
        '.ec-pl-container a em': {
            'color': '#d24e6e',
            'text-decoration': 'none',
        },
        '.ec-pc_title h2': {
            'text-decoration': 'none',
        },
        '.ec-pc_title a:hover': {
            'text-decoration': 'underline',
        },
        //页脚翻页
        '#page': {
            'background-color': '#f2f2f2',
        },
        '#foot': {
            'background-color': '#f2f2f2',
        },
        '#help': {
            'background-color': '#f2f2f2',
        },
        //百度图片
        /*'.op-img-address-divide-high': {
            //'float': 'right',
        },*/
    }
    detailStyle = {//细节
        '.hit_top_new': {//以下包含bbb的搜索结果。仍然搜索:aaa
            'width': '80%',
            'margin': '0 auto',
        },
        '.hit_top_new a': {
            'color': '#66ace0',
            'text-decoration': 'none',
        },
        '#rs_top_new': {//上方相关搜索
            'width': '80%',
            'margin': '0 auto',
        },
        '#rs_top_new a': {//上方相关搜索
            'color': '#66ace0',
            'text-decoration': 'none',
        },
    }
    needCompute = {}//需要计算的样式
    styleId = ''
    css = ''
    update = false

    constructor() {
        this.styleId = Helper.randomString(8)
    }

    apply() {
        let createCss = (style) => {
            let css = ''
            for (let selector of Object.keys(style)) {
                let str = ''
                for (let attribute of Object.keys(style[selector])) {
                    let value = style[selector][attribute].trim()
                    str += attribute + ':' + value
                    if (value.charAt(value.length - 1) !== ';')
                        str += ' !important;'
                }
                css += selector + '{' + str + '} '
            }
            return css
        }
        let styleElement = document.querySelector('#' + this.styleId)
        let style = () => Object.assign(this.style, this.detailStyle, this.needCompute)
        if (styleElement) {
            if (this.update) {
                this.css = createCss(style())
                styleElement.innerHTML = this.css
                this.update = false
            }
        } else {
            this.css = createCss(style())
            let container = document.createElement('style')
            container.id = this.styleId
            container.innerHTML = this.css
            document.querySelector('head').appendChild(container)
        }
    }

    /**
     * 需要计算的属性
     */
    compute() {
        //计算结果容器内文字宽度
        let c_container = document.querySelector('.c-container')
        let c_span6 = document.querySelector('.c-span6')
        if (c_container && c_span6) {
            //计算宽度,17为图片右边margin,最后减去2像素防止出现错误
            let width = c_container.clientWidth - c_span6.clientWidth - 17 - 30 - 2
            if (this.needCompute['.c-span18']) {
                if (this.needCompute['.c-span18']['width'] !== width + 'px') {
                    this.needCompute['.c-span18'] = {'width': width + 'px'}
                    this.update = true
                }
            } else this.needCompute['.c-span18'] = {'width': '950px'}
        }
        //计算左侧宽度
        let form = document.querySelector('#form')
        if (form) {
            //计算宽度,17为图片右边margin,最后减去2像素防止出现错误
            let width = form.clientWidth
            if (this.needCompute['#content_left']) {
                if (this.needCompute['#content_left']['width'] !== width + 'px') {
                    this.needCompute['#content_left'] = {'width': width + 'px'}
                    this.update = true
                }
            } else this.needCompute['#content_left'] = {'width': '672px'}
        }
    }

    beautify(time = 100) {
        this.compute()
        this.apply()
        setTimeout(() => {
            this.beautify(time)
        }, time)
    }
}

(function () {
    'use strict'

    if (window.location.host === 'zhidao.baidu.com') {
        if (document.getElementsByClassName('bannerdown').length > 0)
            document.getElementsByClassName('bannerdown')[0].remove()
        document.getElementsByTagName('aside')[0].remove()
    } else if (window.location.host === 'www.baidu.com') {
        let adController = new ADController()
        let beautifyController = new BeautifyController()
        try {
            adController.remove()
            beautifyController.beautify()
        } catch (e) {
            console.log(e)
        }
    }
})()