模拟网页行为之实践篇
无论是模拟网页点击还是直接协议发包,都有其适用的环境。不同的需求选择不同的方案。如果只是简单的获取类似网页IP地址的需求,实际上协议发包是最简单的。但如果是用户名网页登陆等稍微复杂的登陆要求,则直接填写表单,并获取按钮元素来模拟点击这个方案来讲相对简单。但需求若稍微再变化一点,要求效率多线程,这个时候又是协议发包会作为首选,哪怕需要用户名网页登陆。没有最好的方案只有更合适的方案。这点很重要。
先说模拟网页点击方式,一般我采用的是继承MFC里面的CDHtmlDialog类自己命名为CWebLoginDlg,选择MFC并不是说有多好用,而是本人对于MFC使用更熟悉,学习成本更低,仅此而已。
模拟网页逻辑就是个状态机的处理,而状态的获取,一个可以通过获取网页源码判断特征字符串的方式,还有个可以通过XMLHttpRequest的回包判断数据的方式,再有也可以通过获取网页元素com组件对象是否存在的方式。
先说获取网页源码,基本原理是先获取网页DOC对象, 然后遍历DOC里面的元素,找到TAG为html的元素 get_outerHTML,c++代码如下:
std::wstring CWebLoginDlg::GetHtmlSource()
{CComPtr<IHTMLDocument2> sphtmlDoc;CComPtr<IHTMLElementCollection> pIHTMLElementCollect;GetDHtmlDocument(&sphtmlDoc);if (!sphtmlDoc){return L"";}sphtmlDoc->get_all(&pIHTMLElementCollect);long iCount;pIHTMLElementCollect->get_length(&iCount);CComBSTR data;for (int i = 0; i < iCount; i++){CComVariant v3,v4;v3=(long)i;v4.vt=VT_I4;v4=(long)0;CComPtr<IDispatch> pDisp;HRESULT hr = pIHTMLElementCollect->item(v3,v4,&pDisp);if (!SUCCEEDED(hr)){continue;}CComQIPtr<IHTMLElement, &IID_IHTMLElement> pHTMLElement(pDisp);if(pHTMLElement == NULL){continue;}CComBSTR strTagName;hr = pHTMLElement->get_tagName(&strTagName);if(!SUCCEEDED(hr)){continue;}CString strTag=strTagName;strTag.MakeLower();if(strTag!="html"){continue;}hr = pHTMLElement->get_outerHTML(&data);if(!SUCCEEDED(hr)){return L"";}break;}std::wstring source = data.m_str;return source;
}
再说XMLHttpRequest, XMLHttpRequest是对ajax技术的实现,重点体现在包头的Content-Type字段,这个字段值为application/x-www-form-urlencoded,例如网页代码:
function syncGameInfoAgent () {$.ajax({url : "/api/web/syncGameInfoAgent",type : "GET",cache : false,async : false,success : function(data, textStatus, jqXHR) {}});}
这种方式的ajax还会多个X-Requested-With字段,值为XMLHttpRequest,回包数据都为json格式,还有一种网页代码:
var loadLoginInfo = function() {$.ajax({url : getDomain() + "rest/user",type : "GET",data : {"fields" : "isNameCheck,charCount,isBlocked,isGameBlocked,extAccountInfo"},cache : false,async : true,dataType : "jsonp",success : function(response) { ...
这种方式ajax没有X-Requested_With字段,回包数据为网页数据。c++实现方式如下:
MSXML2::IXMLHTTPRequestPtr m_pIXMLHTTPRequest;m_pIXMLHTTPRequest.CreateInstance("Msxml2.XMLHTTP.6.0");std::wstring CWebLoginDlg::XMLHttpRequest( std::wstring url , std::string requestType/* = "GET"*/)
{BSTR bstrString = NULL;HRESULT hr=m_pIXMLHTTPRequest->open(requestType.c_str(), url.c_str(), false);SUCCEEDED(hr) ? 0 : throw hr;m_pIXMLHTTPRequest->setRequestHeader("X-Requested-With", "XMLHttpRequest"); //这里第二种情况则不能带有此字段m_pIXMLHTTPRequest->setRequestHeader("Content-Type", "application/x-www-form-urlencoded");hr=m_pIXMLHTTPRequest->send();SUCCEEDED(hr) ? 0 : throw hr;bstrString=m_pIXMLHTTPRequest->responseText; //第二种情况则m_pIXMLHTTPRequest->responseBodystd::wstring freePayString = bstrString;if (bstrString){SysFreeString(bstrString);bstrString = NULL;}return freePayString;
}
这里提供一个技巧,找到ajax代码的实现,可以先抓包得到http header里面的request url的url字符串,然后在脚本里面去查找字符串,一般字符串就在ajax代码
url : getDomain() + "rest/user"里面搜索到,搜索到后可以看代码对于返回值的处理,这样才好方便写逻辑。
最后说下获取网页元素,一般来说网页元素都会带有ID或者带有ClassName,例如网页代码:
<input type="password" id="pwd" name="password" class="user_pw" maxlength="16" size="12" autocomplete="off" title="???? ??">
如果想通过ID获取网页对象,简单的可以直接通过GetElement函数来实现,C++代码如下:
IHTMLElement *id = NULL;
this->GetElement(TEXT("id"), &id);
如果想通过ClassName类名来获取网页对象,C++代码如下:
CComQIPtr< IHTMLElement > CWebLoginDlg::GetElementByClassName( std::wstring className )
{CComPtr<IHTMLDocument2> pIHTMLDocument2;GetDHtmlDocument(&pIHTMLDocument2);HRESULT hr; CComQIPtr< IHTMLElementCollection > spElementCollection; hr = pIHTMLDocument2->get_all( &spElementCollection ); //取得表单集合 if ( FAILED( hr ) ) {ATLTRACE("获取集合 IHTMLElementCollection 错误");} long nFormCount=0;hr = spElementCollection->get_length( &nFormCount ); if ( FAILED( hr ) ) {ATLTRACE("获取数目错误");} IDispatch *pDisp = NULL;CComQIPtr< IHTMLElement > ret = pDisp;for(long i=0; i<nFormCount; i++) { pDisp = NULL;hr = spElementCollection->item( CComVariant( i ), CComVariant(), &pDisp ); if ( FAILED( hr ) ) {continue;}CComQIPtr< IHTMLElement > pElement = pDisp;pDisp->Release();CComBSTR varRet;hr = pElement->get_className(&varRet);if (FAILED(hr)){continue;}if (varRet == NULL){continue;}LPCTSTR lpName = OLE2CT( varRet );if (std::wstring(lpName) == className){ret = pElement;break;}}return ret;
}
以上就是模拟网页中获取网页状态的基本函数,有了这几个函数网页模拟方式的基本框架基本都可以搭建起来了。
模拟网页行为之实践篇相关推荐
- 模拟网页行为之实践篇三
现在来谈下验证码图片的获取方式,带有验证码的地方都会附带有个刷新按钮,而刷新按钮的地方就是获取验证码网址代码.如果看过前面写的<模拟网页行为之工具篇>就会很容易定位到代码位置.定位到代码位 ...
- 模拟网页行为之实践篇二
在模拟网页行为中,最常用的就是提交表单了,其次就是获取验证图片数据,再次hook网页中的js代码的实现. 先说具体的应用场景,简单的场景,如填写用户名密码登陆,这里就涉及到获取表单,填写表单数据,提交 ...
- 模拟网页行为之工具篇二
先说360浏览器,打开开发者选项,可以看到界面提供了几个功能选项,如图: 这个图片的第一个搜索图标点中过后,再去选中网页你感兴趣的部分就可以在Element选项中跳转到你感兴趣的代码.也可以直接ctr ...
- 模拟网页行为之工具篇
模拟网页行为最常见的包含模拟网页登陆,模拟提交表单,甚至可以拒绝网页第三方安全软件的加载等一些更酷的行为,这种行为不仅仅是减少了一些非常枯燥重复的过程,更重要的是提升了商业行为中的效率,甚至会给你直接 ...
- python判断网页密码加密方式_Python模拟网页中javascript加密与验证的相关处理
在做网络爬虫的过程中你是否一些在这方面做的很好的网站,你向知道他是通过哪些相关的操作做出这么好的网站,以下就是文章的相关内容的具体介绍,希望你浏览完下面的内容会有所收获.Python模拟网页的java ...
- node.js如何模拟网页点击?
可以使用 Node.js 和一个第三方库,如 Puppeteer,来模拟网页点击.Puppeteer 是一个 Node.js 库,它提供了一个高级 API,用于控制 Chrome 或 Chromium ...
- 模拟网页点击爬虫交管12123违章数据!违章信息及时处理!
本次介绍怎么以模拟点击方式进入交管12123爬取车辆违章数据,本文直接讲解过程,使用的命令解释见上一篇文章.本文同<Python教程-模拟网页点击爬虫定位系统>同样为企业中实际的爬虫案例, ...
- c语言写自动填写表单提交,利用C语言实现POST数据包如此简单【模拟网页提交表单】...
http://www.maben.com.cn/archives/212.html 利用C语言实现POST数据包如此简单[模拟网页提交表单] //*************************** ...
- 【学浪下载教程】06学浪模拟网页版登录,无需客户端和全局代理软件
学浪最新版插件添加了模拟网页端的功能,让大家不再需要打开客户端和全局代理软件(Proxifier) 这个功能只限于谷歌无痕模式下面 使用步骤 1.点击谷歌安装包进行安装(自己有谷歌浏览器就不需要安装) ...
最新文章
- 超详细的CMD文件讲解
- BeetleX之XRPC远程委托调用
- 谈谈C#中的三个关键词new , virtual , override
- 机器学习中生成模型和判别模型
- coreboot学习10:coreboot第一阶段学习小结
- 可重入函数 与线程安全的区别与联系
- math.floor实现四舍五入
- structs 1.x 学习
- 需要压缩NTFS盘的情况有哪些?
- 汽车品牌如何运营用户?
- 用java写图形验证码,超级简单
- 解决lefse配置过程中遇到的问题
- Discuz X3.4模板创建与配置原理简介
- 【STM32】HAL库——ADC
- 十张图,看数据分析如何赋能销售
- 【计算机网络】Web应用的安全问题——概述
- COS操作 java实现
- Matlab信号添加噪声及信噪比SNR的计算
- 视频教程-ElasticSearch7.x集群搭建(es7)主从读写分离搭建教程-ELK
- 云顶之弈下累了 就来看看C/C++内存管理吧
热门文章
- Java面试知识点:多线程
- web.xml配置解释
- svg笔记----------path篇
- 『重构--改善既有代码的设计』读书笔记----Split Temporary Variable
- 单例模式小记【原创】
- SpringBoot笔记整理(二)
- HTML--注册页面案例
- html5+实现图片自动切换,js图片自动切换效果处理代码
- c语言实现图像拼接程序,opencv2实现10张图像上下左右拼接融合分享!
- c++函数为什么带imp_二次函数含参最值问题,老师怎么讲学生都不明白,试试这九张动图...