'use strict'
// 监控img攻防
var imgObserver = new MutationObserver(function (mutations) {
mutations.forEach(function (m) {
if (m.type === 'attributes' && m.oldValue) {
m.target.setAttribute('data-osrc', m.oldValue)
// console.log(m.target, m.oldValue, m.target.src)
}
})
})
imgObserver.observe(document, {childList: true, subtree: true, attributes: true, attributeOldValue: true, attributeFilter: ['src']})
// 统一在写一起, 尽量基于es5语法
var cleanObj = {
// 变量
wrapperID: 'qrm1493625539248',
cssPath: 'https://pcbrowser.dd.qq.com/pcbrowserbig/qb9/mbrm/clean.css',
iframePath: 'https://pcbrowser.dd.qq.com/pcbrowserbig/qb9/mbrm/index.html',
iframeElt: null,
againNum: 0,
// 各site的类别未必相同
typeRule: null,
// 先遮罩防止闪
mask: function () {
cleanObj.iframeElt = document.createElement('iframe')
cleanObj.iframeElt.style.cssText = `position:fixed;top:0;bottom:0;left:0;right:0;
z-index:999999;width:100%;height:100%;background:white;`
cleanObj.iframeElt.src = cleanObj.iframePath + '?t=' + Date.now()
document.documentElement.appendChild(cleanObj.iframeElt)
},
// 监控元素
observer: function (elt, config, cb) {
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (m) {
cb(m)
})
})
observer.observe(elt, config)
return observer
},
// 引入样式
injectCss: function (pElt) {
var elt
// 引入样式
elt = document.createElement('link')
elt.id = 'q1493538638421'
elt.type = 'text/css'
elt.rel = 'stylesheet'
elt.href = cleanObj.cssPath + '?t=' + Date.now()
pElt.appendChild(elt)
},
// 隐藏页面内的原有元素
hide: function () {
var eltArr
// 隐藏所有
eltArr = document.querySelectorAll('body > *')
eltArr = Array.prototype.slice.call(eltArr)
eltArr.forEach(function (n) {
if (n.nodeType === 1 && n.nodeName !== 'SCRIPT' && n !== cleanObj.iframeElt &&
n.id !== cleanObj.wrapperID) {
n.style.cssText += ';display:none !important;'
}
})
// 监听, 防止动态生成的
cleanObj.observer(document.body, {childList: true, attributes: true, subtree: true, attributeFilter: ['style', 'class']}, function (m) {
var arr
// 一种是新增
if (m.type === 'childList' && m.target === document.body && m.addedNodes.length) {
Array.prototype.slice.call(m.addedNodes).forEach(function (n) {
if (n.id !== cleanObj.wrapperID) {
n.style.cssText += ';display:none !important;'
}
})
}
// 一种是改变style显示
else if (m.type === 'attributes' && m.target.parentNode === document.body) {
if (m.target.id !== cleanObj.wrapperID) {
m.target.remove()
}
}
})
},
// 防止多次init
isInit: false,
// 验证函数, 如果正常统一处理
valid: function (isValid, docF) {
if (!cleanObj.isInit && isValid) {
document.body.appendChild(docF)
cleanObj.hide()
cleanObj.isInit = true
setTimeout(function () {
cleanObj.iframeElt.remove()
}, 200)
}
},
// 判断类别
pickTypeRule: function () {
// 投票
if (/\.toutiao\.com$/i.test(location.host) && document.querySelector('#pagelet-vote')) {
cleanObj.typeRule = 'toutiao_vote'
}
// 文章
else if (/\.toutiao\.com$/i.test(location.host) && document.querySelector('.article-container, #article-main, .article')) {
cleanObj.typeRule = 'toutiao_article'
}
// 头条视频
else if (location.host === 'm.365yg.com' && document.querySelector('[class*=video-container]')) {
cleanObj.typeRule = 'toutiao_video'
}
// 问答
else if (location.host === 'wenda.toutiao.com' && document.querySelectorAll('.question, .answer').length === 2 ) {
cleanObj.typeRule = 'toutiao_question'
}
// 网易新闻
else if (location.host === 'c.m.163.com') {
if (/^\/news\/(a|p)\//i.test(location.pathname)) {
cleanObj.typeRule = '163_article'
}
// else if (/^\/news\/v\//i.test(location.pathname)) {
// cleanObj.typeRule = '163_video'
// }
}
},
// 清洗规则
ruleMap: {
'toutiao_vote': function () {
cleanObj.iframeElt.remove()
},
'toutiao_video': function () {
// 元素
var docF, wElt, tElt, cElt, rlElt, rltElt, rllElt
// 监控句柄
var tOb, cOb
// style
cleanObj.injectCss(document.head)
// 封装root
docF = document.createDocumentFragment()
wElt = document.createElement('div')
wElt.id = cleanObj.wrapperID
docF.appendChild(wElt)
// 标题
tElt = document.createElement('h1')
tElt.className = 'rm-title'
wElt.appendChild(tElt)
tOb = cleanObj.observer(document.querySelector('.video-info'), {childList: true, subtree: true}, function (m) {
tElt.textContent = document.querySelector('.video-info h1').textContent
tOb.disconnect()
cleanObj.valid(tElt.textContent && cElt.innerHTML, docF)
})
// 视频
cElt = document.createElement('div')
wElt.appendChild(cElt)
cOb = cleanObj.observer(document.querySelector('.tt-video-box'), {childList: true}, function () {
cElt.innerHTML = document.querySelector('.tt-video-box video').outerHTML
cOb.disconnect()
cleanObj.valid(tElt.textContent && cElt.innerHTML, docF)
})
// 推荐列表
rlElt = document.createElement('div')
rlElt.className = 'rm-video-recommend'
rltElt = document.createElement('h2')
rlElt.appendChild(rltElt)
rllElt = document.createElement('div')
rlElt.appendChild(rllElt)
wElt.appendChild(rlElt)
cleanObj.observer(document.querySelector('[class*=video-container]'), {childList: true, subtree: true, attributes: true, attributeFilter: ['src']}, function (m) {
// 每次都遍历一遍
var tmp = Array.prototype.slice.call(m.target.querySelectorAll('[data-group-id]'))
tmp.forEach(function (n) {
var tmp = rllElt.querySelector('[data-group-id="'+n.getAttribute('data-group-id')+'"]')
// 更新
if (tmp) {
tmp.querySelector('img').src = n.querySelector('img').src
}
// 新增
else {
rllElt.innerHTML += `
${n.querySelector('a').title}
${n.querySelector('.time').title}
` } // 存在video else if (n.classList.contains('tt-video-box') && n.children.length === 1) { htmlStr += `
${n.innerHTML}
` } // 下面只有文本 else if (n.nodeType === 1 && !n.children.length && !/script|style/i.test(n.nodeName)) { htmlStr += `${n.textContent}
` } // 单独p的处理, 没有className else if (/p/i.test(n.nodeName) && n.children.length && !n.className) { // 下面包含文本和img if (n.querySelector('img')) { // 图文混合, 所以要子节点, 知识点啊 tmp = Array.prototype.slice.call(n.childNodes) tmp.forEach(function (m) { if (m.nodeType === 3 && m) { htmlStr += `${m.textContent}
` } else if (m.nodeType === 1 && m.nodeName === 'IMG') { htmlStr += `` } }) } // 下面包含strong等修饰元素 else { htmlStr += `
${n.textContent}
` } } // 还有嵌套 else if (n.children.length) { nestFunc(n) } }) } nestFunc(atElt) return htmlStr } // style cleanObj.injectCss(document.head) // 定位 rootElt = document.querySelector('.article-container, #article-main, .article') // 封装 docF = document.createDocumentFragment() wElt = document.createElement('div') wElt.id = cleanObj.wrapperID docF.appendChild(wElt) // 标题 tElt = document.createElement('h1') tElt.className = 'rm-title' wElt.appendChild(tElt) // 来源 sElt = document.createElement('div') sElt.className = 'rm-source' wElt.appendChild(sElt) // 内容 cElt = document.createElement('div') cElt.className = 'rm-content' wElt.appendChild(cElt) // 监控 cleanObj.observer(rootElt, {childList: true, subtree: true}, function (m) { if (m.type === 'childList') { if (m.target.classList.contains('title') || m.target.classList.contains('article__title')) { tElt.textContent = m.target.textContent } // 文章 else if ((m.target.classList.contains('article-content') || m.target.classList.contains('article__content')) && m.addedNodes.length) { cElt.innerHTML = buildContentHtmlFunc(m.target) } // 更新video else if (m.target.classList.contains('tt-video-box')) { cElt.querySelector('.rm-video').innerHTML = m.target.innerHTML } // 来源 if (!sElt.textContent) { if (document.querySelector('.subtitle')) { sElt.textContent = document.querySelector('#mediaName').textContent + ' ' + document.querySelector('.subtitle .time span:last-child').textContent } else if (document.querySelector('.article__author')) { sElt.textContent = document.querySelector('.media-name').textContent + ' ' + document.querySelector('.publish-time').textContent } } } cleanObj.valid(tElt.textContent && cElt.innerHTML, docF) }) // 小说类有时会直出 tElt.textContent = rootElt.querySelector('.title, .article__title').textContent cElt.innerHTML = buildContentHtmlFunc(rootElt.querySelector('.article-content, .article__content')) // 来源 if (!sElt.textContent) { if (document.querySelector('.subtitle')) { sElt.textContent = document.querySelector('#mediaName').textContent + ' ' + document.querySelector('.subtitle .time span:last-child').textContent } else if (document.querySelector('.article__author')) { sElt.textContent = document.querySelector('.media-name').textContent + ' ' + document.querySelector('.publish-time').textContent } } cleanObj.valid(tElt.textContent && cElt.innerHTML, docF) }, 'toutiao_question': function () { // 元素 var docF, wElt, tElt, cElt, sElt, eltArr // style cleanObj.injectCss(document.head) // 封装root docF = document.createDocumentFragment() wElt = document.createElement('div') wElt.id = cleanObj.wrapperID docF.appendChild(wElt) // 标题 tElt = document.createElement('div') tElt.className = 'rm-wenda-title' tElt.innerHTML = `${document.querySelector('.question .full-des').textContent}
` wElt.appendChild(tElt) // 来源 sElt = document.createElement('div') sElt.className = 'rm-source' wElt.appendChild(sElt) // 内容 cElt = document.createElement('div') cElt.className = 'rm-content' wElt.appendChild(cElt) eltArr = document.querySelectorAll('.answer li') eltArr = Array.prototype.slice.call(eltArr) eltArr.forEach(function (n) { cElt.innerHTML += `` } else if (/p/i.test(n.nodeName) && (!n.className || n.classList.contains('text'))) { htmlStr += `
${n.textContent}
` } }) break case 'array': obj.forEach(function (n) { if (n.img) { htmlStr += `` } if (n.note) { htmlStr += `
${n.note}
` } }) break } return htmlStr } // style cleanObj.injectCss(document.head) // 定位 rootElt = document.querySelector('article') // 封装 docF = document.createDocumentFragment() wElt = document.createElement('div') wElt.id = cleanObj.wrapperID docF.appendChild(wElt) // 标题 tElt = document.createElement('h1') tElt.className = 'rm-title' wElt.appendChild(tElt) // 来源 sElt = document.createElement('div') sElt.className = 'rm-source' wElt.appendChild(sElt) // 内容 cElt = document.createElement('div') cElt.className = 'rm-content' wElt.appendChild(cElt) // 直出 tElt.textContent = rootElt.querySelector('.article-title, .title').textContent sElt.textContent = (rootElt.querySelector('.tname, .subtitle > span') ? rootElt.querySelector('.tname, .subtitle > span').textContent : rootElt.querySelector('.source').textContent) + ' ' + rootElt.querySelector('.time').textContent // 两种情况 if (window.PHOTOS_INFO && Array.isArray(window.PHOTOS_INFO)) { cElt.innerHTML = buildContentHtmlFunc(PHOTOS_INFO, 'array') } else { cElt.innerHTML = buildContentHtmlFunc(rootElt.querySelector('.text, .js-photo-content')) } cleanObj.valid(tElt.textContent && cElt.innerHTML, docF) }, }, // 清洗 clean: function () { if (cleanObj.isInit) { return } cleanObj.pickTypeRule() if (cleanObj.typeRule) { try { cleanObj.ruleMap[cleanObj.typeRule]() } catch (e) { console.log(e) } } else { // 失败后延时2s再试一次 if (cleanObj.againNum < 10) { setTimeout(function () { cleanObj.clean() }, 200) cleanObj.againNum++ } else { cleanObj.iframeElt.remove() } } }, // 入口 init: function () { cleanObj.mask() document.addEventListener('DOMContentLoaded', cleanObj.clean, false) // 容错 setTimeout(function () { if (!cleanObj.isInit) { cleanObj.iframeElt.remove() } }, 1000 * 5) } } cleanObj.init()