获取重定向后的URL

小小虫啊 2014-05-15 03:50:44



如题:

MFC 实现 获取网页重定向后的URL

不能使用Webbrowser控件

VC 6.0中 使用 CHttpFile::QueryOption ()是可以获取到的。

但是 VS 2010中 不能使用这个函数。

所以是使用 CHttpFile::QueryOption(DWORD, CString)这个函数获取的请绕过。

除非你能让他在VS2010中运行起来并且正确获取。

谢谢O(∩_∩)O谢谢
...全文
587 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
encoderlee 2015-11-18
  • 打赏
  • 举报
回复
引用 15 楼 kemond 的回复:
我测试的是这个网址
https://store.taobao.com/shop/view_shop.htm?spm=608.7065813.nf.1.dE0g07&user_number_id=706512823
这个应该是跳转后的网址,可是始终返回的是空白。
https://shop66796293.taobao.com/shop/view_shop.htm?spm=608.7065813.nf.1.dE0g07&user_number_id=706512823



你的这段代码我这里测试是正常的,能取到,我这里环境是WIN8.1 64位+VS2013
kemond 2015-11-17
  • 打赏
  • 举报
回复
我测试的是这个网址 https://store.taobao.com/shop/view_shop.htm?spm=608.7065813.nf.1.dE0g07&user_number_id=706512823 这个应该是跳转后的网址,可是始终返回的是空白。 https://shop66796293.taobao.com/shop/view_shop.htm?spm=608.7065813.nf.1.dE0g07&user_number_id=706512823
kemond 2015-11-17
  • 打赏
  • 举报
回复
引用 11 楼 CharlesSimonyi 的回复:
我这里VS2010下测试,BOOL CHttpFile::QueryInfo( DWORD dwInfoLevel, CString& str, LPDWORD dwIndex = NULL)也能获得结果。



您好,我参考您这个写了这段程序,可始终读取不出来,是空的。
小小虫啊 2014-05-19
  • 打赏
  • 举报
回复
引用 10 楼 CharlesSimonyi 的回复:
你用CInternetSession::OpenURL或CHttpConnection::OpenRequest打开连接的时候,有没有用 INTERNET_FLAG_NO_AUTO_REDIRECT标志。得用了这个标志,它才不会自动处理重定向,从而请求后才能提取到重定向的地址,否则的话它在内部处理掉了重定向,等你调用QueryInfo时,已经 200 OK 了,自然就为空值了。
嗯啊,原来真的是少了这个标志呢! 难怪一直获取不到。THANKYOU ...
encoderlee 2014-05-16
  • 打赏
  • 举报
回复
TCHAR tszLocation[500] = {0}; DWORD dwBufSize = 500 * sizeof(TCHAR); pHttpFile->QueryInfo(HTTP_QUERY_LOCATION, tszLocation, &dwBufSize); http://msdn.microsoft.com/en-us/library/windows/desktop/aa384238(v=vs.85).aspx
小小虫啊 2014-05-16
  • 打赏
  • 举报
回复
引用 6 楼 CharlesSimonyi 的回复:
VS2010下的CHttpFile::QueryOption也是可以的,我以前用过,第一个参数使用HTTP_QUERY_LOCATION来获取重定向的地址。 不知道你遇到的是什么问题,如果问题是出现断言错误,可以用 BOOL CHttpFile::QueryInfo( DWORD dwInfoLevel, LPVOID lpvBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex = NULL ) const; 而不要用 BOOL CHttpFile::QueryInfo( DWORD dwInfoLevel, CString& str, LPDWORD dwIndex = NULL) const;
BOOL CHttpFile::QueryInfo( DWORD dwInfoLevel, LPVOID lpvBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex = NULL ) const;这个怎么用啊,参数二强制转不出来啊。
encoderlee 2014-05-16
  • 打赏
  • 举报
回复
我这里VS2010下测试,BOOL CHttpFile::QueryInfo( DWORD dwInfoLevel, CString& str, LPDWORD dwIndex = NULL)也能获得结果。

encoderlee 2014-05-16
  • 打赏
  • 举报
回复
你用CInternetSession::OpenURL或CHttpConnection::OpenRequest打开连接的时候,有没有用 INTERNET_FLAG_NO_AUTO_REDIRECT标志。得用了这个标志,它才不会自动处理重定向,从而请求后才能提取到重定向的地址,否则的话它在内部处理掉了重定向,等你调用QueryInfo时,已经 200 OK 了,自然就为空值了。
小小虫啊 2014-05-16
  • 打赏
  • 举报
回复
引用 8 楼 CharlesSimonyi 的回复:
TCHAR tszLocation[500] = {0}; DWORD dwBufSize = 500 * sizeof(TCHAR); pHttpFile->QueryInfo(HTTP_QUERY_LOCATION, tszLocation, &dwBufSize); http://msdn.microsoft.com/en-us/library/windows/desktop/aa384238(v=vs.85).aspx
早试过了,空 值。
encoderlee 2014-05-15
  • 打赏
  • 举报
回复
VS2010下的CHttpFile::QueryOption也是可以的,我以前用过,第一个参数使用HTTP_QUERY_LOCATION来获取重定向的地址。 不知道你遇到的是什么问题,如果问题是出现断言错误,可以用 BOOL CHttpFile::QueryInfo( DWORD dwInfoLevel, LPVOID lpvBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex = NULL ) const; 而不要用 BOOL CHttpFile::QueryInfo( DWORD dwInfoLevel, CString& str, LPDWORD dwIndex = NULL) const;
版主大哥 2014-05-15
  • 打赏
  • 举报
回复
BOOL CAsyncHttp::AsyncHttpSetHeader(char* strHeader)
{
	if( !HttpAddRequestHeaders(m_hRequest,strHeader,-1,HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE))
	{
		TRACE("ERROR: HttpAddRequestHeaders failed \n");

		return FALSE;
	}
	return TRUE;
}

BOOL CAsyncHttp::AsyncHttpSendRequest(char* strBody,int aiLen)
{
	ResetEvent(m_hEventReqOK);

resend:

	BOOL bRequest = HttpSendRequest(m_hRequest,"\r\n\r\n",4,strBody,aiLen);

	if(!bRequest)
	{
		if(ERROR_IO_PENDING == GetLastError())
		{
			if(WaitAsyncEvent(ASYNC_HTTP_RECV_TIMEOUT,(LPARAM)this))
			{
				TRACE( "WARMING: HttpSendRequest failed, maybe timeout  \n");

				return FALSE;
			}
		}
		else
		{
			TRACE("ERROR: HttpSendRequest failed \n");

			return FALSE;
		}
	}
	if (m_bSetProxy)
	{
		DWORD dwStatus;

		DWORD dwStatusSize = sizeof(dwStatus);

		HttpQueryInfo(m_hRequest,HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE,&dwStatus,&dwStatusSize,NULL);

		switch (dwStatus)
		{
		case HTTP_STATUS_PROXY_AUTH_REQ : 
			{
				InternetSetOption(m_hRequest,INTERNET_OPTION_PROXY_USERNAME,(LPVOID)m_strProxyUser.c_str(),m_strProxyUser.length());

				InternetSetOption(m_hRequest,INTERNET_OPTION_PROXY_PASSWORD,(LPVOID)m_strProxyUserPass.c_str(),m_strProxyUserPass.length());
				
				goto resend;

				break;
			}
		case HTTP_STATUS_DENIED : 
			{
				InternetSetOption(m_hRequest,INTERNET_OPTION_PROXY_USERNAME,(LPVOID)m_strProxyUser.c_str(),m_strProxyUser.length());

				InternetSetOption(m_hRequest,INTERNET_OPTION_PROXY_PASSWORD,(LPVOID)m_strProxyUserPass.c_str(),m_strProxyUserPass.length());

				goto resend;

				break;
			}
		}
	}
	return TRUE;
}

string& CAsyncHttp::AsyncHttpRecieveResponse()
{
	char szBuff [ASYNC_HTTP_BUFFER_SIZE + 1] = {0}; 

	while(true)
	{
		INTERNET_BUFFERS stIB = {0};

		stIB.dwStructSize = sizeof(INTERNET_BUFFERS);

		stIB.lpvBuffer = szBuff;

		stIB.dwBufferLength = ASYNC_HTTP_BUFFER_SIZE;

		ResetEvent( m_hEventReqOK );

		if( !::InternetReadFileExA(m_hRequest,&stIB,IRF_ASYNC,(LPARAM)this))
		{
			if(ERROR_IO_PENDING == GetLastError())
			{
				if(WaitAsyncEvent(ASYNC_HTTP_RECV_TIMEOUT,(LPARAM)this))
				{
					TRACE("WARMING: InternetReadFileExA failed, maybe timeout  \n");

					break;
				}
			}
			else
			{
				TRACE("ERROR: InternetReadFileExA failed \n");

				break;
			}
		}
		szBuff[stIB.dwBufferLength] = 0;

		if (stIB.dwBufferLength == 0) 
		{ 
			break; 
		}
		m_strResponse.append(szBuff,stIB.dwBufferLength);
	}
	return m_strResponse;
}

void CALLBACK CAsyncHttp::AsyncInternetCallback(HINTERNET hInternet,DWORD dwContext,DWORD dwInternetStatus,LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
{
	CAsyncHttp* pObj = (CAsyncHttp*)dwContext;

	switch(dwInternetStatus)
	{
	case INTERNET_STATUS_HANDLE_CREATED :
		{
			pObj->m_hRequest = (HINTERNET)(((LPINTERNET_ASYNC_RESULT)(lpvStatusInformation))->dwResult);

			break;
		}
	case INTERNET_STATUS_HANDLE_CLOSING :
		{
			SetEvent(pObj->m_hEventAbort);

			break;
		}
	case INTERNET_STATUS_REQUEST_COMPLETE :
		{
			if (ERROR_SUCCESS == ((LPINTERNET_ASYNC_RESULT)(lpvStatusInformation))->dwError)
			{ 
				SetEvent(pObj-> m_hEventReqOK);
			}
			else
			{ 
				//如果发生错误,则处理错误事件
				//这里也是一个陷阱,经常会忽视处理这个错误,
				pObj->m_dwErrorCode = ASYNC_HTTP_ERR_OTHER;

				SetEvent(pObj->m_hEventReqFail);
			}
			break;
		}
	default:
		{
			break;
		}
	}
	return;
}

BOOL CAsyncHttp::WaitAsyncEvent(DWORD dwTimeOut,DWORD dwContext)
{
	CAsyncHttp* pObj = (CAsyncHttp*)dwContext;

	HANDLE hEvents[] = {pObj->m_hEventAbort,pObj->m_hEventReqFail,pObj->m_hEventReqOK};

	DWORD dwRet = WaitForMultipleObjects(3,hEvents,FALSE,INFINITE);

	switch(dwRet)
	{
	case WAIT_TIMEOUT:
		{
			//pObj->m_dwErrorCode = ASYNC_HTTP_ERROR_TIMEOUT;	// 超时错误
			return TRUE;
		}
	case WAIT_OBJECT_0:
		{
			//pObj->m_dwErrorCode = ASYNC_HTTP_ERROR_CANCEL;	// 终止当前操作
			return TRUE;	
		}
	case WAIT_OBJECT_0+1:
		{
			//pObj->m_dwErrorCode = ASYNC_HTTP_ERROR_NET;		// 完成网络操作失败
			return TRUE;
		}
	case WAIT_OBJECT_0+2:						// 完成网络操作成功
		{
			break;			
		}
	}
	return FALSE;
}

void CAsyncHttp::AsyncHttpCloseConn()
{
	if(NULL != m_hRequest)
	{
		InternetCloseHandle(m_hRequest);

		m_hRequest = NULL;
	}
	if(NULL != m_hSession)
	{
		InternetSetStatusCallback(m_hSession,NULL);

		m_hSession = NULL;
	}
	if(m_hEventAbort)
	{
		CloseHandle(m_hEventAbort);

		m_hEventAbort = NULL;
	}
	if(m_hEventReqFail)
	{
		CloseHandle(m_hEventReqFail);

		m_hEventAbort = NULL;
	}
	if(m_hEventReqOK)
	{
		CloseHandle(m_hEventReqOK);

		m_hEventAbort = NULL;
	}
}

BOOL CAsyncHttp::AsyncHttpSetProxy(string& strProxyServer,long lProxyPort,string& strProxyUser,string& strProxyUserPass)
{
	//参数正确性检查
	if (strProxyServer.empty())
	{
		return FALSE;
	}
	//赋值
	m_bSetProxy = TRUE;

	m_strProxyServer = strProxyServer;

	m_lProxyPort = lProxyPort;

	m_strProxyUser = strProxyUser;

	m_strProxyUserPass = strProxyUserPass;

	return TRUE;
}

BOOL CAsyncHttp::AsyncHttpSetProxyOff()
{
	//赋值
	m_bSetProxy = FALSE;

	return TRUE;
}

版主大哥 2014-05-15
  • 打赏
  • 举报
回复

using namespace std;

CAsyncHttp::CAsyncHttp() : m_bSetProxy(FALSE)		//确认是否设置了代理
						 , m_strProxyServer("")		//代理服务器的地址
						 , m_lProxyPort(8080)		//代理服务器的端口
						 , m_strProxyUser("")		//登录代理服务器的用户名
						 , m_strProxyUserPass("")	//登录代理服务器的用户密码
{
	m_hSession = NULL;
	m_hConnect = NULL;
	m_hRequest = NULL;

	m_hEventAbort = ::CreateEvent(NULL,TRUE,FALSE,NULL);
	m_hEventReqFail = ::CreateEvent(NULL,TRUE,FALSE,NULL);
	m_hEventReqOK = ::CreateEvent(NULL,TRUE,FALSE,NULL);
	
	m_dwErrorCode = ASYNC_HTTP_OK;
}

CAsyncHttp::~CAsyncHttp()
{
	AsyncHttpCloseConn();
}

BOOL CAsyncHttp::AsyncHttpOpen()
{
	string strProxyInfo;

	if (m_bSetProxy)
	{
		strProxyInfo.clear();

		strProxyInfo = m_strProxyServer;

		strProxyInfo.append(":");

		CString strPort;

		strPort.Format("%ld",m_lProxyPort);

		strProxyInfo.append((LPCSTR)strPort);

		m_hSession = InternetOpen("xihu",INTERNET_OPEN_TYPE_PROXY,strProxyInfo.c_str() ,NULL,INTERNET_FLAG_ASYNC);
	}
	else
	{
		m_hSession = InternetOpen("xihu",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,INTERNET_FLAG_ASYNC);
	}
	
	if( NULL == m_hSession )
	{
		TRACE( "ERROR: InternetOpen failed \n");

		return FALSE;
	}
	InternetSetStatusCallback(m_hSession,(INTERNET_STATUS_CALLBACK)AsyncInternetCallback);
	
	return TRUE;
}

BOOL CAsyncHttp::AsyncHttpConnect(char* strServerAddr,int nPort)
{
	m_hConnect = InternetConnect(m_hSession,strServerAddr,(INTERNET_PORT)nPort,NULL,NULL,INTERNET_SERVICE_HTTP,0,0);

	if( NULL == m_hConnect )
	{
		TRACE( "ERROR: InternetConnect failed \n" );

		return FALSE;
	}
	if (m_bSetProxy)
	{
		InternetSetOption(m_hConnect,INTERNET_OPTION_PROXY_USERNAME,(LPVOID)m_strProxyUser.c_str(),m_strProxyUser.length());

		InternetSetOption(m_hConnect, INTERNET_OPTION_PROXY_PASSWORD,(LPVOID) m_strProxyUserPass.c_str(),m_strProxyUserPass.length());
	}
	return TRUE;
}

BOOL CAsyncHttp::AsyncHttpOpenRequest(char* strObjectName,char* strMethod)
{
	char* szAccept[] = {"*/*",NULL};

	ResetEvent(m_hEventReqOK);

	m_hRequest = HttpOpenRequestA(m_hConnect,strMethod,strObjectName,_T("HTTP/1.0"), NULL,(LPCSTR*)szAccept,INTERNET_FLAG_RELOAD,(LPARAM)this);

	if( NULL == m_hRequest )
	{
		if( ERROR_IO_PENDING == GetLastError())
		{
			if( WaitAsyncEvent(ASYNC_HTTP_RECV_TIMEOUT,(LPARAM)this))
			{
				TRACE( "WARMING: HttpOpenRequest failed, maybe timeout  \n");

				return FALSE;
			}
		}
		else
		{
			TRACE("ERROR: HttpOpenRequest failed \n");

			return FALSE;
		}
	}

	return TRUE;
}
版主大哥 2014-05-15
  • 打赏
  • 举报
回复

#include <wininet.h>

#pragma comment(lib,"Wininet.lib")

#include <string>
using namespace std;

#define ASYNC_HTTP_OK					0
#define ASYNC_HTTP_ERROR_TIMEOUT		-1
#define ASYNC_HTTP_ERROR_CANCEL			-2
#define ASYNC_HTTP_ERROR_NET			-3
#define ASYNC_HTTP_ERROR_URL			-100
#define ASYNC_HTTP_ERROR_CREATE_THREAD	-101
#define ASYNC_HTTP_ERR_OTHER			-999
#define ASYNC_HTTP_BUFFER_SIZE			4*1024
#define ASYNC_HTTP_RECV_TIMEOUT			1000  

class CAsyncHttp
{
public:
	CAsyncHttp();

	virtual ~CAsyncHttp();

	BOOL AsyncHttpOpen();

	BOOL AsyncHttpConnect(char* strServerAddr,int nPort);

	BOOL AsyncHttpOpenRequest(char* strObjectName,char* strMethod);

	BOOL AsyncHttpSetHeader(char* strHeader);

	BOOL AsyncHttpSendRequest(char* strBody,int aiLen);

	string& AsyncHttpRecieveResponse();

	void AsyncHttpCloseConn();

	//设置代理
	BOOL AsyncHttpSetProxy(string& strProxyServer,long lProxyPort,string& strProxyUser,string& strProxyUserPass);
	//取消代理
	BOOL AsyncHttpSetProxyOff();

	DWORD m_dwErrorCode;
private:
	//回调函数,系统api通过该回调函数通知CAsyncHttp http通信过程中的各种状态
	static void CALLBACK AsyncInternetCallback(HINTERNET hInternet,DWORD dwContext,DWORD dwInternetStatus,LPVOID lpvStatusInformation,DWORD dwStatusInformationLength);

	static BOOL WaitAsyncEvent(DWORD dwTimeOut, DWORD dwContext);

	void OnDisConnect();

	string m_strResponse;		//保存返回流
	BOOL   m_bSetProxy;			//确认是否设置了代理
	string m_strProxyServer;	//代理服务器的地址
	long   m_lProxyPort;		//代理服务器的端口
	string m_strProxyUser;		//登录代理服务器的用户名
	string m_strProxyUserPass;	//登录代理服务器的用户密码
	HINTERNET m_hSession;		//http InternetOpen句柄
	HINTERNET m_hConnect;		//http InternetConnect句柄
	HINTERNET m_hRequest;		//http HttpOpenRequestA句柄
	HANDLE m_hEventAbort;		//用户取消事件句柄
	HANDLE m_hEventReqFail;		//失败或异常事件句柄
	HANDLE m_hEventReqOK;		//成功事件句柄
};
小小虫啊 2014-05-15
  • 打赏
  • 举报
回复
引用 1 楼 oyljerry 的回复:
winhttp API
怎么用? 没用过这个。
oyljerry 2014-05-15
  • 打赏
  • 举报
回复
winhttp API

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧