您的位置:首页 > 编程语言 > Java开发

使用 webBrowser 进行页面采集时捕获所有xhr数据

2017-03-09 18:28 1256 查看
最近又开始玩采集了,这次的采集目标很别扭,基本上所有的数据都是通过异步加载到页面的,也就是说通过 HttpWebRequest 这个类进行采集的话,基本上获取不到真实数据了,或者非要使用 HttpWebRequest 也不是不可以,但是就需要对每一个返回的 JSon 数据进行单独抓取,感觉好麻烦啊

于是,决定适用 WebBrowser 进行对返回 JSon进行监控

首先在网上找了几个文章,讲解了如何捕获 xhr 数据,(http://www.jb51.net/article/91419.htm)

;(function () {
if (typeof window.CustomEvent === 'function') return false;
function CustomEvent ( event, params ) {
params = params || { bubbles: false, cancelable: false, detail: undefined };
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
return evt;
}
CustomEvent.prototype = window.Event.prototype;
window.CustomEvent = CustomEvent;
window._xhrs = window._xhrs||{count:0,result:[],send:0};
})();
;(function()
{
function ajaxEventTrigger(event) {
var ajaxEvent = new CustomEvent(event, { detail: this });
window.dispatchEvent(ajaxEvent);
if (event=='ajaxLoadStart'){
window._xhrs['count']++;
}
if (event=='ajaxLoadEnd'){
if (/^<[\s\S]*>$/gi.test(this['responseText'])){
alert(this['responseText'])
}else{
window._xhrs['result'].push(this['responseText']);
}
returnCSharp();
}
}
var oldXHR = window.XMLHttpRequest;
function newXHR()
{
var realXHR = new oldXHR();
realXHR.addEventListener('abort', function() { ajaxEventTrigger.call(this, 'ajaxAbort'); }, false);
realXHR.addEventListener('error', function() { ajaxEventTrigger.call(this, 'ajaxError'); }, false);
realXHR.addEventListener('load', function() { ajaxEventTrigger.call(this, 'ajaxLoad'); }, false);
realXHR.addEventListener('loadstart', function() { ajaxEventTrigger.call(this, 'ajaxLoadStart'); }, false);
realXHR.addEventListener('progress', function() { ajaxEventTrigger.call(this, 'ajaxProgress'); }, false);
realXHR.addEventListener('timeout', function() { ajaxEventTrigger.call(this, 'ajaxTimeout'); }, false);
realXHR.addEventListener('loadend', function() { ajaxEventTrigger.call(this, 'ajaxLoadEnd'); }, false);
realXHR.addEventListener('readystatechange', function() { ajaxEventTrigger.call(this, 'ajaxReadyStateChange'); }, false);
return realXHR;
}
window.XMLHttpRequest = newXHR;
})();

这段代码很有意思,它实现的目的是重写一个浏览器内的 XMLHttpRequest 对象,并将该对象追加几个事件监控,我在这个 js 代码中定义了一个方法 returnCSharp,用以在符合条件或者数据加载完毕时将数据返回到 WinForm 中,具体实现可以在网上去搜索一下怎么实现 js 和 c# 通讯,这里就不再讲述了

经过测试这个代码是可以使用的,但是产生了一个很让人郁闷的问题,即:使用 WebBrowser.Navigate 之后,js 即可执行了,我再追加这段 js 时就已经遗漏了部分异步请求的信息,这太恶心了,于是又进行一番查找,发现 http://www.cnblogs.com/eaglet/archive/2008/11/19/1336347.html 这里对 WebBrowser 做了一个超出我知识范畴的重点“WebBrowser 其实是对 ActiveX 控件 SHDocVw 的封装,而这个SHDocVw的很多底层调用WebBrowser控件并没有提供实现,我们需要直接操作
SHDoceVw 控件来实现这些高级调用。


好吧,看看这个高级调用里都有些什么?非常棒!我们发现了这个!BeforeScriptExecute!

很好,我们在构造函数中写上这些 InitializeComponent();
webBrowser1.ObjectForScripting = this;
wb = (SHDocVw.WebBrowser)webBrowser1.ActiveXInstance;
wb.BeforeScriptExecute += Wb_BeforeScriptExecute;


在 WebBrowser 加载完成之后,js 运行之前将我们想优先运行的东西运行起来,然后实现完整监控 xhr 数据!

于是,加上js执行的调用

private void Wb_BeforeScriptExecute(object pDispWindow)
{
string text = webBrowser1.DocumentText;
IHTMLDocument2 vDocument = (IHTMLDocument2)webBrowser1.Document.DomDocument;
try
{
vDocument.parentWindow.execScript(script, "javascript");
}
catch (Exception ex)
{
this.Close();
}
}

很好,这很方便,这样就可以直接通过 WebBrowser 一次调用来获取完整 json 数据,而不用再使用正则啦、Dom啦进行数据分析,以实现降低我们数据分析的成本

补充:引用中追加了以下两个

Microsoft.mshtml 程序集--扩展,使用 IHTMLDocument2 直接运行 JS 代码

windows/system32/shdocvw.dll 使用 BeforeScriptExecute 事件监控加载进度
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐