谷歌抓取网页视频插件(一眼百度搜索结果的链接设置和设置参数的设置)
优采云 发布时间: 2022-02-28 06:22谷歌抓取网页视频插件(一眼百度搜索结果的链接设置和设置参数的设置)
Chrome插件开发系列三:百度google搜索链接直链院长系列文章二维码阅读
2018-10-21 23:01
几乎每天我们都使用百度或谷歌上网获取各种知识或资源。你有没有注意到,有时候从百度或者谷歌跳转到我们真正想看的网页,速度非常慢?为什么会这样?我们打开开发者工具,看看百度搜索结果的链接设置:
从上面的截图可以看出,搜索结果页面的链接并不是直接指向要访问的网站,而是一个百度自己的URL,我们称之为百度中转页面,然后通过location或者跳转其他方法。我去了要访问的网站的网站,所以排除了结果站加载速度的问题。百度转移页面的速度也会影响从百度结果页面跳转到要访问的网站的速度。网站,我们无法优化它的访问速度,但是我们可以想办法去掉百度中转步骤,直接跳转到要访问的网站,加快我们对资源的访问。
现在的问题是如何获取要访问的 URL。在上面的截图中,我们发现要访问的网站在百度中转时是用url参数标记的,url参数是一个加密的结果。这部分加密算法没有研究。通过进一步抓拍百度转账页面的跳转,我们可以发现,百度转账页面是通过location跳转到要访问的网站,而location就是要访问的明文。访问url,但是我们无法通过js直接获取response中的location参数。现在我们有两种方法来解决它:
1、通过后端语言解析响应头信息中的location参数,然后前端将百度转移页面地址传递给后端进行解析,得到解析结果。解析代码比较简单,这里就不演示了。
2、在前面的基础知识中,我们了解到插件可以拦截和修改一些请求参数,那么我们可以充分利用这个来解析位置参数。前面我们说了js不能直接解析location参数,为什么?? xhr 对象有一个 getResponseHeader 方法。原因是该位置会导致页面重定向。js 无法阻止这种重定向,所以请求是最终要访问的地址,getResponseHeader 获取要访问的地址的响应头。,这不是我们想要的,而且由于要访问的地址可能是http或者https,而百度搜索页面是https,所以也可能存在mixcontent的问题,不能通过允许跨域来解决。但是使用插件,我们可以去掉响应头中的location参数,
var modifyFieldName = 'location';
var searchUrlReg = /https:\/\/www\.baidu\.com\/link\?url=/;
chrome.webRequest.onBeforeSendHeaders.addListener(function(details){
var url = details.url;
if (searchUrlReg.test(url)) {
details.requestHeaders.push({
name: 'Access-Control-Expose-Headers',
value: 'Redirect'
});
}
return {requestHeaders: details.requestHeaders};
},
{
urls : [""]
},
["blocking", "requestHeaders"]);
chrome.webRequest.onHeadersReceived.addListener(function(details) {
var url = details.url;
var responseHeaders = details.responseHeaders;
var allowOriginHeader = responseHeaders.find(function(rh, index){
if (rh.name === modifyFieldName) {
responseHeaders[index]['value'] = 'https://www.baidu.com/';
return true;
}
if (rh.name.toLowerCase() === modifyFieldName.toLowerCase() && searchUrlReg.test(url)) {
responseHeaders.push({
name: 'redirect',
value: rh.value
});
responseHeaders.splice(index, 1);
}
});
return {
responseHeaders: responseHeaders
};
},
{
urls : [""]
},
["responseHeaders","blocking"]);
上面代码中,我们截取了响应头,删除了location字段,将location字段的值赋给redirect字段,作为自定义字段返回,但是这里需要注意的一点是自定义redirect并没有不能直接通过xhr的getResponseHeader方法获取。您需要将重定向字段添加到 Access-Control-Expose-Headers 字段以将其公开,因为重定向不是标准的标头信息字段。
屏蔽跳转并添加自定义字段后,我们可以通过js获取。下面是js获取redirect字段的代码:
function getRealLink(url, callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', url, true);
xmlhttp.onload = function() {
var redirect = this.getResponseHeader('redirect');
if (redirect) {
callback(redirect);
}
}
xmlhttp.send();
}
核心部分明白了,剩下的工作就是我们需要将百度搜索结果页面的中转地址替换为最终要访问的地址。以下是代码:
(function() {
let timer = null;
const container = document.querySelector('#wrapper_wrapper');
replaceUrl();
watchUpdate();
function replaceUrl() {
unWatchUpdate();
const resultLink = [].slice.call(document.querySelectorAll('.result h3 a, .result-op h3 a'), 0);
resultLink.forEach(function(item) {
var url = item.getAttribute('href').replace(/&wd.*$/, '');
if (/https?\:\/\/www\.baidu\.com\/link\?url/.test(url)) {
getRealLink(url.replace('http', 'https'), function(sc) {
item.href = sc;
});
}
});
watchUpdate();
}
function getRealLink(url, callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', url, true);
xmlhttp.onload = function() {
var redirect = this.getResponseHeader('redirect');
if (redirect) {
callback(redirect);
}
}
xmlhttp.send();
}
function watchUpdate() {
container.addEventListener('DOMSubtreeModified', function() {
handleUpdate();
}, false);
}
function unWatchUpdate() {
container.removeEventListener('DOMSubtreeModified', handleUpdate);
}
function handleUpdate() {
timer && clearTimeout(timer);
timer = setTimeout(function() {
replaceUrl();
});
}
}());
因为百度搜索也可能是异步的,所以我们这里也使用 DOMSubtreeModified 来监控异步更新。
其余的google搜索结果页面链接这里就不分析了。和百度比起来,就简单多了。中转页面的url参数是要访问的明文地址。我们只需要提取出要访问的地址,然后替换成现在,异步搜索的处理和百度一样。
系列文章导航:
第一节:Chrome插件开发系列一:弹窗终结者
第二节:Chrome插件开发系列之二:跨域调试助手
第四节:Chrome插件开发系列四:URL二维码生成
第五节:Chrome插件开发系列之五:插件管理器
报酬