VC使用libcurl模擬登錄CSDN并自動評論資源以獲取積分
環境:Win7 64位+VC2008
軟件及源碼下載:(http://pan.baidu.com/s/1jGE52pK)
涉及到的知識點:
libcurl的使用(包括發送http請求、發送cookie給服務器、保存cookie)
關于libcurl的資料,推薦大家參考下官方文檔:http://curl.haxx.se/libcurl/c/example.html
軟件運行結果
libcurl中的所有函數
curl_easy_cleanupcurl_easy_duphandle
curl_easy_escape
curl_easy_getinfo
curl_easy_init
curl_easy_pause
curl_easy_perform
curl_easy_recv
curl_easy_reset
curl_easy_send
curl_easy_setopt
curl_easy_strerror
curl_easy_unescape
curl_escape (deprecated, do not use)
curl_formadd
curl_formfree
curl_formget
curl_free
curl_getdate
curl_getenv (deprecated, do not use)
curl_global_cleanup
curl_global_init
curl_global_init_mem
curl_mprintf (deprecated, do not use)
curl_multi_add_handle
curl_multi_assign
curl_multi_cleanup
curl_multi_fdset
curl_multi_info_read
curl_multi_init
curl_multi_perform
curl_multi_remove_handle
curl_multi_setopt
curl_multi_socket
curl_multi_socket_action
curl_multi_strerror
curl_multi_timeout
curl_share_cleanup
curl_share_init
curl_share_setopt
curl_share_strerror
curl_slist_append
curl_slist_free_all
curl_strequal (deprecated, do not use)
curl_strnequal (deprecated, do not use)
curl_unescape (deprecated, do not use)
curl_version
curl_version_info
CURLcode curl_global_init(long flags)
描述:這個函數只能用一次。(其實在調用curl_global_cleanup 函數后仍然可再用)
如果這個函數在curl_easy_init函數調用時還沒調用,它將由libcurl庫自動完成。
參數:flags
CURL_GLOBAL_ALL //初始化所有的可能的調用。
CURL_GLOBAL_SSL //初始化支持 安全套接字層。
CURL_GLOBAL_WIN32 //初始化win32套接字庫。
CURL_GLOBAL_NOTHING //沒有額外的初始化。 void curl_global_cleanup(void);
描述:在結束libcurl使用的時候,用來對curl_global_init做的工作清理。類似于close的函數。
char *curl_version( );
描述: 打印當前libcurl庫的版本 CURL *curl_easy_init( ); 描述:curl_easy_init用來初始化一個CURL的指針(有些像返回FILE類型的指針一樣). 相應的在調用結束時要用curl_easy_cleanup函數清理.一般curl_easy_init意味著一個會話的開始. 它的返回值一般都用在easy系列的函數中 void curl_easy_cleanup(CURL *handle); 描述:這個調用用來結束一個會話.與curl_easy_init配合著用.
參數:CURL類型的指針. CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
描述: 這個函數最重要了.幾乎所有的curl 程序都要頻繁的使用它.
它告訴curl庫.程序將有如何的行為. 比如要查看一個網頁的html代碼等.
(這個函數有些像ioctl函數)
參數:
1 CURL類型的指針
2 各種CURLoption類型的選項.(都在curl.h庫里有定義,man 也可以查看到)
3 parameter 這個參數 既可以是個函數的指針,也可以是某個對象的指針,也可以是個long型的變量.它用什么這取決于第二個參數.
CURLoption 這個參數的取值很多.具體的可以查看man手冊. CURLcode curl_easy_perform(CURL *handle); 描述:這個函數在初始化CURL類型的指針 以及curl_easy_setopt完成后調用. 就像字面的意思所說perform就像是個舞臺.讓我們設置的
option 運作起來.
參數:
CURL類型的指針
如何操作cookie
通過curl_easy_setopt函數的第二個參數,就可以很容易的操作cookie 保存cookie信息到本地的cookie.txt文件curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookie.txt");
讀取本地的cookie.txt文件中的cookie信息
curl_easy_setopt(easy_handle, CURLOPT_COOKIEFILE,
"cookie.txt"
);
模擬登錄csdn

ReturnInfo CCSDNDlg::LoginServer(CString strUser,CString strPass) { ReturnInfo returnInfo; returnInfo.bReturn = FALSE; CURL *curl; CURLcode res; struct curl_slist *headers = NULL; curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); if(curl){ //初始化cookie引擎 curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION, 1L); //http請求頭 headers = curl_slist_append(headers,"User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0"); //模擬瀏覽器 headers = curl_slist_append(headers,"Host:passport.csdn.net"); headers = curl_slist_append(headers,"Accept:*/*"); headers = curl_slist_append(headers,"Accept-Language:zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3"); headers = curl_slist_append(headers,"Accept-Encoding:gzip, deflate"); headers = curl_slist_append(headers,"X-Requested-With:XMLHttpRequest"); headers = curl_slist_append(headers,"Referer:https://passport.csdn.net/account/loginbox?callback=logined&hidethird=1&from=http%3a%2f%2fwww.csdn.net%2f"); headers = curl_slist_append(headers,"Connection:keep-alive"); curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookie.txt"); //把服務器發過來的cookie保存到cookie.txt //發送http請求頭 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); char url[256]; sprintf(url,"http://passport.csdn.net/ajax/accounthandler.ashx?t=log&u=%s&p=%s&remember=0&f=http%3A%2F%2Fwww.csdn.net%2F&rand=0.47590136872096434",strUser,strPass); curl_easy_setopt(curl, CURLOPT_URL,url); string content; //設置回調函數 res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer); res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content); //執行http請求 res = curl_easy_perform(curl); string returnVal; Utf8ToMb((char*)content.c_str(),content.length(),returnVal); int pos = returnVal.find("\"status\":true"); if ( pos >= 0){ returnInfo.bReturn = TRUE; int nStartPos = content.find("data\":"); int nEndPos = content.rfind("\"}}"); returnInfo.data = content.substr(nStartPos+6,nEndPos - nStartPos-4); }else{ int nStartPos = returnVal.find("error\":"); int nEndPos = returnVal.find("data\":",nStartPos); returnInfo.strErrorInfo = returnVal.substr(nStartPos+8,nEndPos-nStartPos-11); } //釋放資源 curl_easy_cleanup(curl); curl_slist_free_all(headers); headers = NULL; } curl_global_cleanup(); return returnInfo; }

根據給定的網址獲取網頁源碼

static string GetHtmlPage(string url) { CURL *easy_handle; CURLcode res; string content; curl_global_init(CURL_GLOBAL_ALL); easy_handle = curl_easy_init(); if( easy_handle ) { //初始化cookie引擎 curl_easy_setopt(easy_handle, CURLOPT_COOKIEFILE,""); curl_easy_setopt(easy_handle,CURLOPT_TIMEOUT,5); //設置請求超時時間 //curl_easy_setopt(easy_handle,CURLOPT_VERBOSE,1); //輸出請求頭和響應頭 //curl_easy_setopt(easy_handle,CURLOPT_HEADER,1); curl_easy_setopt(easy_handle,CURLOPT_FOLLOWLOCATION, 1L); //http請求頭 struct curl_slist *headers = NULL; headers = curl_slist_append(headers,"Host: download.csdn.net"); headers = curl_slist_append(headers,"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0"); headers = curl_slist_append(headers,"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); headers = curl_slist_append(headers,"Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3"); headers = curl_slist_append(headers,"Referer: http://www.csdn.net/"); headers = curl_slist_append(headers,"Connection: keep-alive"); curl_easy_setopt(easy_handle, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(easy_handle, CURLOPT_COOKIEFILE, "cookie.txt"); //讀取本地存儲的cookie if(!InitCurl(easy_handle,res,url,content)) { //釋放資源 curl_slist_free_all(headers); curl_easy_cleanup(easy_handle); return NULL; } //釋放資源 curl_slist_free_all(headers); curl_easy_cleanup(easy_handle); } curl_global_cleanup(); string tt; Utf8ToMb((char *)content.c_str(),content.length(),tt); return tt; }

獲取下載資源總頁數

static int GetTotalPageNum() { string url = "http://download.csdn.net/my/downloads/1"; string html = GetHtmlPage(url); int nPos = html.rfind("尾頁"); if (nPos == -1) return -1; nPos -= 2; int nStartPos = html.rfind("/",nPos); string strTotal = html.substr(nStartPos+1,nPos - nStartPos - 1); return atoi(strTotal.c_str()); }

獲取待評論的資源列表

static vector<DownResourceInfo> GetToCommentList(int pageNum) { vector<DownResourceInfo> vtDownload; char url[128] = {0}; sprintf(url,"http://download.csdn.net/my/downloads/%d",pageNum); string html = GetHtmlPage(url); int nPos = 0; int n = 0; int flag = 1; while((nPos = html.find("#comment",n)) != -1) { n = nPos+1; int nStartPos = html.rfind("/",nPos); string strUrl = html.substr(nStartPos+1,nPos - nStartPos -1); DownResourceInfo info; info.strResourceCurl = strUrl; //獲取資源的名字 nStartPos = html.find(strUrl,nPos+1); if(nStartPos == -1) return vtDownload; nStartPos += 2; nStartPos += strUrl.length(); int nEndPos = html.find("</a>",nStartPos); string ResourceName = html.substr(nStartPos,nEndPos - nStartPos); info.strResourceName = ResourceName; vtDownload.push_back(info); } return vtDownload; }

發表評論

static BOOL AddComment(string sourceId) { CURL *easy_handle; CURLcode res; string content; curl_global_init(CURL_GLOBAL_ALL); easy_handle = curl_easy_init(); if( easy_handle ) { //初始化cookie引擎 curl_easy_setopt(easy_handle, CURLOPT_COOKIEFILE,""); curl_easy_setopt(easy_handle,CURLOPT_FOLLOWLOCATION, 1L); string url = "http://download.csdn.net/index.php/comment/post_comment?jsonpcallback=jsonp1385304626524&sourceid="+sourceId+"&content=%E9%9D%9E%E5%B8%B8%E6%84%9F%E8%B0%A2%EF%BC%8C%E8%BF%99%E8%B5%84%E6%BA%90%E6%88%91%E6%89%BE%E4%BA%86%E5%A5%BD%E4%B9%85%E4%BA%86%EF%BC%81&rating=5&t=1385304679900"; string referer = "Referer: http://download.csdn.net/detail/wasdzxce/"+sourceId; //http請求頭 struct curl_slist *headers = NULL; headers = curl_slist_append(headers,"Host: download.csdn.net"); headers = curl_slist_append(headers,"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0"); headers = curl_slist_append(headers,"Accept: text/javascript, application/javascript, */*"); headers = curl_slist_append(headers,"Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3"); headers = curl_slist_append(headers,"Accept-Encoding: gzip, deflate"); headers = curl_slist_append(headers,"Content-Type: application/x-www-form-urlencoded"); headers = curl_slist_append(headers,"X-Requested-With: XMLHttpRequest"); headers = curl_slist_append(headers,referer.c_str()); headers = curl_slist_append(headers,"Connection: keep-alive"); curl_easy_setopt(easy_handle, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(easy_handle, CURLOPT_COOKIEFILE, "cookie.txt"); //讀取本地存儲的cookie if(!InitCurl(easy_handle,res,url,content)) { //釋放資源 curl_slist_free_all(headers); curl_easy_cleanup(easy_handle); curl_global_cleanup(); return FALSE; } //釋放資源 curl_slist_free_all(headers); curl_easy_cleanup(easy_handle); } curl_global_cleanup(); int pos = content.find("\"succ\":1"); if (pos>=0) return TRUE; else return FALSE; }
