就拿google maps(http://maps.google.com)来实验吧.
发送一个请求,如:
http://maps.google.com/maps?f=q&hl=zh-CN&q=Shanghai&ie=UTF8&om=0&z=14&ll=36.451113,115.97\0821&spn=0.036453,0.086517&t=k
如何利用IHTML* 接口提取到地图里的图像地址?
每次请求可以得到20个地图图像的<IMG>标签。
偶现在很傻的办法是:嵌入一个browser控件,每次去取它的temp files,
要么就是从firefox里的Tools --> Page Info 里得到这些<IMG>嵌入一个browser 实在很傻,偶需要轻量级的代码来实现。
偶的思路是 利用spidermonky 这样的java 解析器来分析得到的内容,但并不止这些。1000分!! 得到解答后立即分5个贴给分。
发送一个请求,如:
http://maps.google.com/maps?f=q&hl=zh-CN&q=Shanghai&ie=UTF8&om=0&z=14&ll=36.451113,115.97\0821&spn=0.036453,0.086517&t=k
如何利用IHTML* 接口提取到地图里的图像地址?
每次请求可以得到20个地图图像的<IMG>标签。
偶现在很傻的办法是:嵌入一个browser控件,每次去取它的temp files,
要么就是从firefox里的Tools --> Page Info 里得到这些<IMG>嵌入一个browser 实在很傻,偶需要轻量级的代码来实现。
偶的思路是 利用spidermonky 这样的java 解析器来分析得到的内容,但并不止这些。1000分!! 得到解答后立即分5个贴给分。
如果用.net要简单一点
获得html源代码,用HtmlAgilityPack分析并取出页面所有img标签的src属性
temp.Format("http://maps.google.com/maps?f=q&hl=zh-CN&q=Shanghai&ie=UTF8&om=0&z=14&ll=36.451113,115.97\0821&spn=0.036453,0.086517&t=k
");
request.Open("GET",temp,false,"","");
request.Send(""); CXMLDOMDocument2 doc = CDOMDocument30Class::CreateXMLDOMDocument2();
doc.LoadXML(request.GetResponseText()); CXMLDOMNode node = doc.SelectSingleNode("//img[@src]");再遍历node就可以取到图片地址了mfc里使用msxml可以考虑以下文章
http://www.codeproject.com/soap/msxmlcpp.asp
偶表述的不太清楚,这个AJAX是表示google maps用的是AJAX,并不是说已经得到了xml文档了。
我用HttpOpenRequest()得到了"第一次请求"的DOM文档.但是这个AJAX的DOM文档是多次获得的。
后面的DOM文档(包含地图<IMG>标签的)是由 js脚本文件触发得到的。这个目前只能由browser获得,例如IE的 Save As 全部文档是无法得到<IMG>内容的,打开后只是个空架子,必须连网去下载才行。
Firefox做的比IE好,可以得到全部内容。大家先动手试一下,就明白怎么回事了。不要着急的贴代码,常规的代码是无效的,必须涉及到js解析,AJAX解析这些浏览器原理的代码才可以解决这个问题。好像IE的接口不涉及这么深层次的东西。
接收所有请求回来的数据 分析这些数据
找到你感兴趣的img 然后下载下来可以吗我一般不用ie browser去另存为等
很多网页好多东西 但是查看源文件就是一点
用抓包工具抓包看看 然后再构造自己的请求
推荐ieHTTPHeaders这个ie抓包插件不错
你的思路也跟我的相似:我是用WinINet HttpOpenRequest()来发送请求。
问题还是怎么解析js 文件 得到输出的GET命令,它每次都算出不同的GET参数,
总不能挂着IE来解析它吧,还是得研究spidermonky,怎么和firefox配合的问题
。
参考:http://blog.csdn.net/lion_wing/archive/2006/06/27/839134.aspx
对于能不能对JS、AJAX多次执行进行过滤,可以下载代码研究一下。
MIME类型:
image/gif
image/jpeg
image/pjpeg
image/tiff
image/x-png
image/x-xbitmap
image/bmp
image/x-jg
image/x-emf
image/x-wmf
http://kh2.google.com/kh?n=404&v=12&t=trstrtrrqtrrttq
http://kh1.google.com/kh?n=404&v=12&t=trstrtrrqtrqssr
http://kh3.google.com/kh?n=404&v=12&t=trstrtrrqtrrttt
http://kh1.google.com/kh?n=404&v=12&t=trstrtrrqtrrtqt
http://kh2.google.com/kh?n=404&v=12&t=trstrtrrqtrqsss
http://kh3.google.com/kh?n=404&v=12&t=trstrtrrqtrrttr
http://kh0.google.com/kh?n=404&v=12&t=trstrtrrqtrqsrs
http://kh0.google.com/kh?n=404&v=12&t=trstrtrrqtrrtts
http://kh2.google.com/kh?n=404&v=12&t=trstrtrrqtrrtqs
http://kh0.google.com/kh?n=404&v=12&t=trstrtrrqtrqssq
http://kh0.google.com/kh?n=404&v=12&t=trstrtrrqtrsqqq
http://kh1.google.com/kh?n=404&v=12&t=trstrtrrqtrqsst
http://kh3.google.com/kh?n=404&v=12&t=trstrtrrqtrqsrt
http://kh3.google.com/kh?n=404&v=12&t=trstrtrrqtrtrrr
http://kh0.google.com/kh?n=404&v=12&t=trstrtrrqtrrtsq
http://kh1.google.com/kh?n=404&v=12&t=trstrtrrqtrsqqr
http://kh1.google.com/kh?n=404&v=12&t=trstrtrrqtrrtst
http://kh3.google.com/kh?n=404&v=12&t=trstrtrrqtrrtrt
http://kh2.google.com/kh?n=404&v=12&t=trstrtrrqtrtrrq
http://kh2.google.com/kh?n=404&v=12&t=trstrtrrqtrsqrq
http://kh1.google.com/kh?n=404&v=12&t=trstrtrrqtrrtsr
http://kh2.google.com/kh?n=404&v=12&t=trstrtrrqtrrtss
http://kh0.google.com/kh?n=404&v=12&t=trstrtrrqtrrtrs
http://kh3.google.com/kh?n=404&v=12&t=trstrtrrqtrsqrr
提供的有力工具。但是我只能得到第一个img url ,怎么能得到全部的img list ?
我只需要 pOIBindInfo->GetBindString(BINDSTRING_URL, &Url, 1, &Fetched);
就可以得到url了,不需要接下来的ReportData ReportProgress了。
1、去掉CHTMLFilter实现的IInternetProtocolSink接口
2、CMimefilterDlg中:
BOOL CMimefilterDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
HRESULT hr=::CoGetClassObject(CLSID_HTMLFilter,CLSCTX_SERVER,NULL,IID_IClassFactory,(void**)&m_pFactory);
if(SUCCEEDED(hr))
{
hr=::CoInternetGetSession(0,&m_pSession,0);
if(SUCCEEDED(hr))
{
m_pSession->RegisterNameSpace(m_pFactory, CLSID_HTMLFilter, L"https", 0, NULL, 0);
m_pSession->RegisterNameSpace(m_pFactory, CLSID_HTMLFilter, L"http", 0, NULL, 0);
}
}
m_ie.Navigate("http://maps.google.com/maps?f=q&hl=zh-CN&q=Shanghai&ie=UTF8&om=0&z=14&ll=36.451113,115.97\\0821&spn=0.036453,0.086517&t=k", NULL, NULL, NULL, NULL);
return TRUE; // return TRUE unless you set the focus to a control
}
3、CHTMLFilter中:
STDMETHODIMP CHTMLFilter::Start(LPCWSTR szUrl,
IInternetProtocolSink *pOIProtSink,
IInternetBindInfo *pOIBindInfo,
DWORD grfPI, HANDLE_PTR dwReserved)
{
FILE *f = _wfopen(L"C:\\googlemap.log", L"a");
fputws(szUrl, f);
fputws(L"\n", f);
fclose(f);
return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
}STDMETHODIMP CHTMLFilter::Continue(PROTOCOLDATA *pProtocolData)
{
return S_OK;
}STDMETHODIMP CHTMLFilter::Abort(HRESULT hrReason, DWORD dwOptions)
{
UrlMonProtocol->Abort(hrReason, dwOptions);
return S_OK;
}STDMETHODIMP CHTMLFilter::Terminate(DWORD dwOptions)
{
return S_OK;
}STDMETHODIMP CHTMLFilter::Suspend()
{
return S_OK;
}STDMETHODIMP CHTMLFilter::Resume()
{
return S_OK;
}
// IInternetProtocol
STDMETHODIMP CHTMLFilter::Read(void *pv, ULONG cb, ULONG *pcbRead)
{
return S_OK;
}STDMETHODIMP CHTMLFilter::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
{
return E_FAIL;
}STDMETHODIMP CHTMLFilter::UnlockRequest()
{
return S_OK;
}STDMETHODIMP CHTMLFilter::LockRequest(DWORD dwOptions)
{
return S_OK;
}
4、打开C:\googlemap.log,就可以看到所有的图片要址了(如果需要GOOGLE地图的图片,可以对CHTMLFilter::Start进行修改实现)
1. 使用web browser控件只能得到可见的20个图像,而不是全部的24个图像,请问你怎么一次得到24个图像的? 能否再给出代码?一次得不到全部图像给我后续代码带来了很大麻烦。
2.如果把web browser控件属性设为invisable, 什么结果也得不到。因为我后续的程序很消耗内存和显存,而且高度频繁的更新url,实现不想让browser显示任何图像,我只想得到img url list, 由下载线程来处理。请问怎么让web browser控件不做任何显示的事情?
(1)我做了一个BHO(Browser Helper Objects),把我们的过滤功能加进去。
(2)用CoCreateInstance(CLSID_InternetExplorer,NULL,CLSCTX_SERVER,IID_IWebBrowserApp,(LPVOID*)&pWBApp)创建一个IE窗口,并用代码将其导航到GOOGLE地图页面,从而得到图片日志。第一种情况:将IE的Visible设为FALSE时,则LOG日志中的图片内容为空。
(以下几种情况,Visible为TRUE)
第二种情况:将IE的Width、Height都置为0,则LOG日志中的图片数为3。
第三种情况:在我拖拽IE的窗口,改变其大小时,LOG内的图片数,随之增加。
第四种情况:将IE的Width、Height分别置为1024、768,则得到的图片为20。
第五种情况:将IE的Width、Height、Top、Left分别置为1024、768、0、0,则得到的图片数中24。总结:
GOOGLE MAPS页面中的AJAX与服务器的交互和页面的布局、大小有很大的关系,它会根据浏览器控件当前显示的区域从服务器上下载不等数据的图片以供显示。
所以楼主不能将浏览器控件隐藏,且设置适当的显示区域,以取得一定的图片数。
能不能实现这个BHO仅做url解析和接受? 不做接下来的download和display ?
2、http://support.microsoft.com/kb/167658,像文中那样去建立IE实例,用:
HRESULT IWebBrowser2::put_Width(long Width);
HRESULT IWebBrowser2::put_Height(long Height);
HRESULT IWebBrowser2::put_Top(long Top);
HRESULT IWebBrowser2::put_Left(long Left);
3、我想这个BHO不太可能只做解析,不过你可以尝试一下。
我再等等看看如何阻塞IE的 download和display.
bmozjs ,引擎不錯.
html parser,如果只是提取, 用lex分析是很簡單的.
能不能说说“怎么使用”mozilla引擎的java script引擎,與html parser ?
我找遍mozilla网站也没发现什么文档。只有一些原理的文档。好像mozilla引擎没法独立使用,必须在它自己的环境里。
html parser 能解决AJAX的问题吗? google map的每张图都是通过复杂的js解析计算出来的,
影响因素有浏览器大小,位置,版本,提交参数,等n多因素。单单一个lex分析能解决吗?
我编译了一下,得到了js.exe 但是几乎没法用阿:用它来解析google map的js 文件,
说没定义window, document等基本变量,请问怎么定义呢? 像google map是先执行html的js脚本,得到一些变量定义,加上browser的window,document 才去执行真正的js文件,像这种情况怎么模拟?
java script腳本執行最終都需要通過post,或get方法向Web Service請求數據.
找找看,它的HTTP據包該類似下面.GET http://www.google.com/ HTTP/1.0
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*
Accept-Language: zh-tw
Cookie: PREF=ID=91fc2af9086acc7f:NW=1:TM=1157597063:LM=1157597063:S=Nixvn2epcAr7Bu49
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
Host: www.google.com....
能否再给点建议?
或者你直接由它來產生,得到http請求,然後透過socket發送到google,
再用lex分析google 返回.
请看:对于这么一个请求,从得到的结果看,怎么可能找到规律呢?
换句换说,答案就在返回的结果里,要是已经得到了,也不需要用lex分析了啊。
请求:
http://maps.google.com/maps?f=q&hl=zh-CN&q=Shanghai&ie=UTF8&om=0&z=14&ll=36.451113,115.970821&spn=0.036453,0.086517&t=k结果:GET http: //kh1.google.com/kh?n=404&v=13&t=trstrqtrqqrsrqr HTTP/1.1
Accept: */*
Referer: http://maps.google.com/maps?f=q&hl=zh-CN&q=Shanghai&ie=UTF8&om=0&z=14&ll=36.451113,115.970821&spn=0.036453,0.086517&t=k
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)
Host: kh1.google.com
Proxy-Connection: Keep-Alive
Cookie: khcookie=fzwq1KAV2G5pfwSBP4g1QNZWjOCXbjbO7S3zrQ; PREF=ID=67fd415ca3d04858:NW=1:TM=1167210906:LM=1167210906:S=zRjdbLWvwUZjZwYh; testcookie=
Proxy-Authorization: NTLM TlRMTVNTUAABAAAAB4IAogAAAAAAAAAAAAAAAAAAAAAFAJMIAAAAD1==
GET http: //kh2.google.com/kh?n=404&v=13&t=trstrqtrqqrsrrq HTTP/1.1
Accept: */*
Referer: http://maps.google.com/maps?f=q&hl=zh-CN&q=Shanghai&ie=UTF8&om=0&z=14&ll=36.451113,115.970821&spn=0.036453,0.086517&t=k
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)
Host: kh2.google.com
Proxy-Connection: Keep-Alive
Cookie: khcookie=fzwq1KAV2G5pfwSBP4g1QNZWjOCXbjbO7S3zrQ; PREF=ID=67fd415ca3d04858:NW=1:TM=1167210906:LM=1167210906:S=zRjdbLWvwUZjZwYh; testcookie=
Proxy-Authorization: NTLM TlRMTVNTUAABAAAAB4IAogAAAAAAAAAAAAAAAAAAAAAFAJMIAAAAD1==GET http: //kh0.google.com/kh?n=404&v=13&t=trstrqtrqqrrsts HTTP/1.1
Accept: */*
Referer: http://maps.google.com/maps?f=q&hl=zh-CN&q=Shanghai&ie=UTF8&om=0&z=14&ll=36.451113,115.970821&spn=0.036453,0.086517&t=k
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)
Host: kh0.google.com
Proxy-Connection: Keep-Alive
Cookie: khcookie=fzwq1KAV2G5pfwSBP4g1QNZWjOCXbjbO7S3zrQ; PREF=ID=67fd415ca3d04858:NW=1:TM=1167210906:LM=1167210906:S=zRjdbLWvwUZjZwYh; testcookie=
Proxy-Authorization: NTLM TlRMTVNTUAABAAAAB4IAogAAAAAAAAAAAAAAAAAAAAAFAJMIAAAAD1==
答案就是这些:
GET http: //kh0.google.com/kh?n=404&v=13&t=trstrqtrqqrrsts HTTP/1.1确实没法找到这些 “trstrqtrqqrrsts” 啊。
有个问题请教:现在我想得到browser object接受到的全部html,txt,javascript,js ,请问在你的代码里如何得到?能否说说如何在socket request里构造browser的位置、大小、版本 ? 谢谢!
browser,否则browser没法正确显示图像。但是browser是异步下载数据的,
这造成了在我们代码里得到的图像顺序是不对的,而且是随机的。
没办法正确显示图像。
圖片顯示位置有可能是由javascript決定的.
這是個比較細致的工作.樓主好好調試.有點奇怪的是,樓主為什麼不研究一下google提供的API .
2、mozilla引擎的方法:我的意思是,GOOGLE用JS先得到browser位置、大小、版本相关的信息(可能还有其它信息),然后再用JS将其进行运算(加密等操作,当然了,对于我们来说这并不保密,哈哈),再提交到服务器。你可以分析GOOGLE的JS代码,用程序来模拟运算(加密),再用socket提交到服务器。
m_pSession->RegisterNameSpace(m_pFactory, CLSID_HTMLFilter, L"text/html", 0, NULL, 0);
m_pSession->RegisterNameSpace(m_pFactory, CLSID_HTMLFilter, L"text/plain", 0, NULL, 0);
m_pSession->RegisterNameSpace(m_pFactory, CLSID_HTMLFilter, L"application/javascript", 0, NULL, 0);是不是在CHTMLFilter::Start()里或其它地方还要更改,我看这里捕捉的都是szUrl 阿,其他文字在哪里捕捉啊?google提供的API研究了,不能达到我的项目要求:不能取到image,只能print,而且全是script 不能在c++里用.
//m_pSession->RegisterNameSpace(m_pFactory, CLSID_HTMLFilter, L"http", 0, NULL, 0);
m_pSession->RegisterMimeFilter(m_pFactory,CLSID_HTMLFilterHTML,L"text/html");
m_pSession->RegisterMimeFilter(m_pFactory,CLSID_HTMLFilterJS,L"application/javascript");
m_pSession->RegisterMimeFilter(m_pFactory,CLSID_HTMLFilterJS,L"application/x-javascript");
请问修改一下你的CHTMLFilter 类型为"text/html"就可以得到下面列的xml数据吗?在CHTMLFilter::ReportData()需要进行什么修改吗?
每个image 其xml数据如下
<IMG
style="border: 0px none ; margin: 0px; padding: 0px; position: absolute; left: 917px; top: 724px; width: 256px; height: 256px; -moz-user-select: none;" src="http://kh2.google.com/kh?n=404&v=13&t=ttrrq"/>
我用firefox的DOM Inspector仔细察看了一下图像DOM node 发现其实每个image的left,top 就给出了位置,只要得到image DOM node的属性就行了。只不过位置需要再调一下,view里看不到的位置都是负值。
m_pSession->RegisterNameSpace(m_pFactory, CLSID_HTMLFilter, L"http", 0, NULL, 0);
仅仅得到了image url ,现在我想进一步得到image position 属性,就像
<IMG
style="border: 0px none ; margin: 0px; padding: 0px; position: absolute; left:917px; top: 724px; width: 256px; height: 256px; -moz-user-select: none;"src="http://kh2.google.com/kh?n=404&v=13&t=ttrrq"/>这些response如何得到?
修改一下你的CHTMLFilter 类型为"text/html"就可以得到上面的数据吗?在CHTMLFilter::ReportData()需要进行什么修改吗?
可能CHTMLFilter::ReportData不会做太大的改变,因为我也没动写过过滤XML的代码所以可以试一下。
http://kh2.google.com/kh?n=404&v=13&t=tqtrq
的信息,跟最早用HttpOpenRequest()得到的内容一样。
为啥用
m_pSession->RegisterNameSpace(m_pFactory, CLSID_HTMLFilter, L"http", 0, NULL, 0);
至少可以得到url 呢?能解释一下吗?2.使用
CComPtr<IStream> DataStream;
总是报错。在
DataStream->Read(pv, cb, pcbRead);
和
CreateStreamOnHGlobal(0, true, &DataStream);
时,请问这个DataStream做什么用的?可否完全去掉呢?
m_pSession->RegisterNameSpace(m_pFactory, CLSID_HTMLFilter, L"http", 0, NULL, 0);
是对URL的http命名空间的截获。
2、DataStream是为浏览器准备的数据。报错?出什么错误?
DataStream 报错在Atlbase.h 的指针非NULL 断言错误,如下: _NoAddRefReleaseOnCComPtr<T>* operator->() const
{
ATLASSERT(p!=NULL);
return (_NoAddRefReleaseOnCComPtr<T>*)p;
}如何修改?
http://support.microsoft.com/kb/260840
我试了"text/xml" 结果什么都得不到,连CHTMLFilter::ReportData()都没调用!
说明得到的还是HTML ,firefox的DOM Inspector把HTML转成xml而已。
您提供的例子也肯定没帮助了:它是把xml转成HTML.能否空闲时动手帮我试一下? 我等您的消息。这东西实践性太强,肯定有很大的处理技巧,单单指导效果不大。像您动手帮我把URL得到用到的MIME filter 对我就属于新东西。
谢谢!
style="border: 0px none ; margin: 0px; padding: 0px; position: absolute; left:917px; top: 724px; width: 256px; height: 256px; -moz-user-select: none;"src="http://kh2.google.com/kh?n=404&v=13&t=ttrrq"/>请问,这段代码你是怎样得到的?
firefox的工具确实强大:除了DOM Inspector,Page Info,Save As 都可以得到image url,
image的属性在DOM Inspector 和Save As里也可以得到。
我感觉google maps 就是分2步走:第一步得到常见的html,第二步再根据解析maps.70.js 文件,进一步连接server,得到HTML, 本质上第二次方法跟第一次都一样,只不过它分2次走,造成获取HTML的困难。
我觉得:图像位置的HTML也是server发到本地来的,而且在DOM Inspector里也仅找到一处image url
出现的地方(共30个),说明browser是把接受到的HTML “剥离”了,把图像地址发出,被我们截获,
而image的属性被browser保留用作显示。
我准备趁元旦这几天好好研究firefox 2.0源码,目标是提取个超精简的js/xml解析器
http://support.microsoft.com/kb/185127
如何从 WebBrowser VC 应用程序调用脚本函数
我觉得可以在程序中嵌入webbrowser控件,执行js脚本,同时禁止加载图像(通过实现IDocHostUIHandler接口,输入 DOCHOSTUIFLAG_NOPICS flag.)这样可以获得纯html文本而不下载图片文件。
http://www.codeproject.com/com/dispexsinkconnector.asp
我觉得你需要转换一下思路。
人家用Flash实现的。我已经反编译出Action Script,正在分析中。http://www.flashearth.com/flash_earth.swf
我现在分析了部分firefox的源码,思路清晰多了,估计春节就可以提炼出一个强大的Javascript分析器:给定一个url, 提交后就可以下载到指定特征的img 或 其他媒体文件的返回字符串。
其实firefox关于javascript的解析不复杂,主要是它的实现框架。
看来还是我的思路保险:用hack的办法只能管一会,不能管时间长。google会不停的变换加密算法的。但不管怎么变换,还是得让browser观看啊。
可以达到80000*60000大小 Jpeg格式,并没有上限。下一步,准备实现智能自动探索城市范围,以及
配套的看图软件,这么大的图片可是一打开就死机的。
自动探索城市范围可以自动发现一些军事基地啥的,google会在很多偏僻的地方提供大图,而这些很难用人工发现的。软件效率也经过优化,运行时内存不超过20M,即使合成超大图片的时候,还可以进一步利用显卡加速。
这么个小软件,用到的技术和技巧,足以写一本非常综合的编程书籍。最后,感谢各位提供的思路,回过头来才发现你们的建议是多么有效。