手把手教你用C++ 寫ACM自動刷題神器(沖入HDU首頁)__C++

來源:互聯網
上載者:User
轉載註明原地址:http://blog.csdn.net/nk_test/article/details/49497017


少年,作為苦練ACM,通宵刷題的你 是不是想著有一天能夠榮登各大OJ榜首,俯瞰芸芸眾生,唔....要做到這件事情可是需要一定天賦的哦。

博主本身也搞過一段時間的acm,對刷題深有感觸,不信可以去看我部落格的acm題解(哈哈)。

不過,先給各位辛苦刷題的ACMer賠個不是,畢竟這是很投機的一種方式,僅供娛樂,還請各位見諒。

受學長的啟蒙,打算自己做一個使用C++語言完成的自動刷題神器,也可以叫自動AC機(什麼。ac自動機...嚇尿),先來看一下成果:

(註:這是第一次刷完後的排名,後來對代碼進行了很大的最佳化,但是由於時間關係,沒有再刷一遍,否則肯定進入前十。)


第17名是我,AC率還算不錯吧,但是我最佳化之後的肯定比這個高。

好了,扯淡完畢,下面進入本文,先來說一下整體思路


1)使用socket編程類比HTTP協議GET請求向伺服器發送頁面請求

2)藉助搜尋引擎找到相關題目的代碼(一般csdn的居多)

3)使用Regex解析HTML代碼擷取部落格串連,緊接著從部落格中解析出 題目的代碼

4)對代碼進行編碼轉換的處理,模仿HTTP協議的POST請求向伺服器提交代碼

5)解析提交後返回的State頁面,提取最終的結果(是否Accepted)、耗時和空間佔用。

6)將刷題過程儲存至SQL Server資料庫,供以後的資料分析。


是不是感覺很簡單的樣子,讓我們一步一步來。


(一)使用socket編程類比HTTP協議GET請求向伺服器發送頁面請求

我們在baidu中搜尋索引鍵,點擊按鈕,伺服器會返回我們一個頁面,這件事情使用程式該如何?呢。

答案就是我們使用Socket編程通過bind(),connect(),send(),recv()這些函數建立與伺服器的串連。這些知識就不再這裡展開了,讀者可以自行baidu或者參考我的Linux網路編程專欄。 接下來我們想:點擊按鈕的過程發生了什麼,我們使用send()需要將什麼資訊發送至伺服器,這裡就要涉及到HTTP協議的GET請求。

我們只需要實現GET的要求標頭即可(可以通過chrome按F12來查看),注意和本文之間有一個空行,即/r/n 

[cpp]  view plain  copy //向伺服器發送GET請求        string  reqInfo = "GET " + (string)othPath + " HTTP/1.1\r\nHost: " + (string)host + "\r\nConnection:Close\r\n\r\n";       if (SOCKET_ERROR == send(sock, reqInfo.c_str(), reqInfo.size(), 0))       {           cout << "send error! 錯誤碼: " << WSAGetLastError() << endl;           closesocket(sock);       }   (二)藉助搜尋引擎擷取csdn部落格連結

一開始的時候我想利用百度搜尋引擎,但是發現返回到HTML頁面中根本無法找出csdn部落格的連結特徵,後來發現,原來是baidu為了避免爬蟲爬取進行了加密處理,如下圖:

注意左下角是第一個csdn部落格的串連....坑了我一段時間。

後來發現360搜尋沒有加密,所以那就用360吧。。提取出來放入vector儲存,然後使用C++11的Regex解析出csdn部落格的地址。

[cpp]  view plain  copy void regexGetcom(string &allHtml) //提取網頁中的csdn部落格的url     {       blogUrl.clear();       smatch mat;       regex pattern("href=\"(http://blog.csdn[^\\s\"]+)\"");              string::const_iterator start = allHtml.begin();       string::const_iterator end = allHtml.end();       while (regex_search(start, end, mat, pattern))       {           string msg(mat[1].first, mat[1].second);           blogUrl.push_back(msg);           start = mat[0].second;       }   }  

(三)從HTML中解析出代碼


注意代碼一般由#include開始,結束的位置是</textarea>或者</pre>,我們利用這個特徵進行提取。

[cpp]  view plain  copy void GetCode(string &allHtml)   {       CodeHtml = "";       int pos = allHtml.find("#include");       if (pos != string::npos)       {           for (int i = pos; i < allHtml.length(); i++)           {                              if ((allHtml[i] == '<'&&allHtml[i + 1] == '/'&&allHtml[i + 2] == 't'&&allHtml[i + 3] == 'e'&&allHtml[i + 4] == 'x'&&allHtml[i + 5] == 't') || (allHtml[i] == 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.