在前面两篇《聚BT浏览器扩展自定义网站从入门到精通1-HTTP请求类型GET、GET_CUSTOM》、《聚BT浏览器扩展自定义网站从入门到精通2-HTTP请求类型NEWTAB、NEWTAB_IFRAME》讲解了聚BT浏览器扩展 HTTP请求类的GET、GET_CUSTOM以及NEWTAB、NEWTAB_IFRAME。这篇继续讲解POST。
POST类型分为两大类:普通POST请求、NEWTAB/NEWTAB_IFRAME的请求。
GET/GET_CUSTOM和NEWTAB/NEWTAB_IFRAME (实际上前面讲的NEWTAB是GET类型的新开标签页),系统都有缺省的searcher或parser,但对于POST类型,searcher和parser都需要自定义。
普通POST请求
普通POST请求,不需要新开标签页,也是最常用的POST类型。
普通POST的典型例子:好恐怖 https://www.hkb123.com 。值得推荐一下,好恐怖电影站质量不错,尤其是很多冷门篇此站都有收集。
POST类型的请求,在查询时候,浏览器地址栏不会带查询关键词信息,因此在自定义站点页面,网站搜索地址可以只填写官网首页:https://www.hkb123.com ,不需要带searchkeyword关键词。
在好恐怖首页:https://www.hkb123.com,输入“爱与怪物”查询,大致的请求交互流程为:
1、实际请求URL(Request URL)为:https://s.haokongbu.net/e/search,请求类型(Request Method)为:POST
POST的Form表单参数为:show=title%2Cftitle%2Cactor&keyboard=%E7%88%B1%E4%B8%8E%E6%80%AA%E7%89%A9
2、服务器返回302重定向请求,重定向地址为 https://s.haokongbu.net/e/search/result/?searchid=582944 ,请求类型为GET
地址栏变为为:https://s.haokongbu.net/e/search/result/?searchid=582944 ,搜索结果返回并展示。
对于POST类型的请求,每一个网站的searcher都不相同,只能一个一个网站自定义,例如好恐怖的searcher为:
async
再次强调:这是系统内置函数,在自定义界面的”网站搜索代码“字段,不需要输入函数名,只需要输入函数体部分。
对应的系统内置parser 为hkb123Parser
function hkb123Parser(content, url, source, keyword) {
let myDocument = documentFactory(content);
const elements = myDocument.querySelectorAll("div.channel-content ul li p a");
let hrefs = [];
for (let element of elements) {
let href = element.getAttribute("href");
if (href) {
href = relativeUrlToAbsolute(href, url);
let text = element.innerText;
let desc = keyword;
//console.debug("parser.js hkb123Parser href is: " + href + ", text is:" + text);
if (href && text) {
hrefs.push({ link: href, linkText: text, desc: desc, source: source, keyword: keyword, url: url, type: "movie" });
}
}
}
return hrefs;
}
再次强调:这是系统内置函数,在自定义界面的”网站解析代码“字段,不需要输入函数名,只需要输入函数体部分。
NEWTAB/NEWTAB_IFRAME 的POST
以上举的好恐怖是普通的POST,但假如页面请求涉及复杂的交互逻辑,例如有ajax请求或请求报文有加密请求,此时,为降低抓包分析难度,可以直接使用NEWTAB/NEWTAB_IFRAME 配合自定义searcher的方案。
典型例子:知网 https://www.cnki.net
function cnkiSearcher(url, keyword) {
//console.debug("parserNewTab.js cnkiSearcher keyword is: " + keyword);
if (document.getElementById("txt_search")) {
let element = document.getElementById("txt_search");
element.value = keyword;
var handler = setInterval(function () {
element = document.getElementById("txt_search");
//console.debug("parserNewTab.js cnkiSearcher value1 is: " + element.value);
if (element.value == keyword) {
//console.debug("parserNewTab.js cnkiSearcher value2 is: " + keyword);
clearInterval(handler);
document.querySelector("input.search-btn").click();
setTimeout(function () {}, 1000);
} else {
cnkiSearcher(keyword);
}
}, 1000);
} else {
total++;
if (total < 7) {
cnkiSearcher(url, keyword);
}
}
}
代码看起来貌似有点复杂,核心思路如下:
1、在采用 NEWTAB_IFRAME 模式打开标签页
2、等待页面装载完成
通过document.getElementById(“txt_search”) 轮询页面txt_search元素
如果未获取到,则递归调用cnkiSearcher自己。
重复7次未获取到,则退出
3、将搜索框txt_search的值设置为搜索关键词
4、模拟点击 input.search-btn完成搜索。
NEWTAB类型的POST极少使用,如果不喜欢新开标签页,也可以通过分析请求报文和相关的JavaScript函数,用自定义普通POST实现。
系统缺省内置的parser为:
function cnkiParser(url, source, keyword) {
const elements = document.querySelectorAll("td.name a");
let hrefs = [];
for (let element of elements) {
let href = element.getAttribute("href");
let match = href.match(/FileName=(.*)&DbName=(.*)&DbCode=(.*)&/);
if (match) {
let filename = match[1];
let dbname = match[2];
let dbcode = match[3];
href = "https://kns.cnki.net/kcms/detail/detail.aspx?filename=" + filename + "&dbname=" + dbname + "&dbcode=" + dbcode;
let text = element.innerText;
let desc = keyword;
console.debug("parser.js mikuclubParser href is: " + href + ", text is:" + text);
if (href && text) {
hrefs.push({ link: href, linkText: text, desc: desc, source: source, keyword: keyword, url: url, type: "scholar" });
}
}
}
return hrefs;
}
以上为系统缺省内置的parser,如果在自定义界面,输入如下:
let myDocument = documentFactory(content);
const elements = myDocument.querySelectorAll("td.name a");
let hrefs = [];
for (let element of elements) {
let href = element.getAttribute("href");
let match = href.match(/FileName=(.*)&DbName=(.*)&DbCode=(.*)&/);
if (match) {
let filename = match[1];
let dbname = match[2];
let dbcode = match[3];
href = "https://kns.cnki.net/kcms/detail/detail.aspx?filename=" + filename + "&dbname=" + dbname + "&dbcode=" + dbcode;
let text = element.innerText;
let desc = keyword;
console.debug("parser.js mikuclubParser href is: " + href + ", text is:" + text);
if (href && text) {
hrefs.push({ link: href, linkText: text, desc: desc, source: source, keyword: keyword, url: url, type: "scholar" });
}
}
}
return hrefs;
主要差异:
1、在自定义界面需要对搜索结果使用documentFactory构建document
let myDocument = documentFactory(content);
const elements = myDocument.querySelectorAll("td.name a");
2、正如反复强调的:不需要输入函数名,只需要输入函数体部分
由此总算介绍完了聚BT浏览器扩展的几种请求类型,下一篇针对系统内置的几个函数重点介绍,包括documentFactory, httpGet,httpPost等,以更好理解自定义searcher和parser的逻辑。