使用 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 事件监控加载进度
于是,决定适用 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 事件监控加载进度
相关文章推荐
- 回发或回调参数无效。在配置中使用 或在页面中使用 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。
- 回发或回调参数无效。在配置中使用 或在页面中使用 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。
- 数据采集-关于密码使用js脚本进行rsa方式加密的解决方法
- java使用多线程进行分页数据采集
- 使用ob,memcache(小数据)进行页面静态化,和储存数据
- 使用Ext Viewport进行页面布局时Panel中的sumit按钮无法提交表单数据
- 使用 ArcGIS Online和APP进行监控操作和数据采集
- file_get_contents进行页面采集数据
- Python使用scrapy采集数据过程中放回下载过大页面的方法
- PHP中使用snoopy采集类进行数据抓取
- 如何使用正则表达式进行QQ校友的数据采集
- 基于curl数据采集之单页面并行采集函数get_htmls的使用
- http和https进行数据 采集使用.net类 httpwebrequest和httpwebresponse
- 基于curl数据采集之单页面采集函数get_html的使用
- 使用两个不同类型的数据进行加法计算时,使用异常处理语句捕获由于数据类型错误而出现的异常,发生生成错误。是否继续并运行上次的成功生成?
- .Net Windows 程序中 使用WebBrowser实现需要登陆的页面截取(采集)
- 在使用SSH过程中,在JSP页面中对数据进行处理,出异常!
- 基于curl数据采集之单页面并行采集函数get_htmls的使用
- Kinect2.0之使用KinectSDK自带的KinectStudio进行数据采集
- Swift - 使用导航条和导航条控制器来进行页面切换并传递数据