如何用c++写一个dht爬虫

如何用c++写一个dht爬虫,第1张

要想爬,先读取HTTP

读取后 进行字符串分割 

Http访问有两种方式,GET和POST,就编程来说GET方式相对简单点,它不用向服务器提交数据,程序中使用POST方式,

提交数据并从服务器获取返回值。

为实现Http访问,微软提供了二套API:WinINet, WinHTTP。WinHTTP比WinINet更加安全和健壮,可以这么认为WinHTTP是WinINet的升级版本。

程序中,通过一个宏的设置来决定是使用WinHttp还是WinINet。

#define USE_WINHTTP      //Comment this line to user wininet.

下面来说说实现Http访问的流程(两套API都一样的流程):

1, 首先我们打开一个Session获得一个HINTERNET session句柄

2, 然后我们使用这个session句柄与服务器连接得到一个HINTERNET connect句柄;

3, 然后我们使用这个connect句柄来打开Http 请求得到一个HINTERNET request句柄;

4, 这时我们就可以使用这个request句柄来发送数据与读取从服务器返回的数据;

5, 最后依次关闭request,connect,session句柄。

 

/***********************定义HTTP发送所用方法***********************************/

HINTERNET OpenSession(LPCWSTR userAgent = 0)

{

#ifdef USE_WINHTTP

    return WinHttpOpen(userAgent, NULL, NULL, NULL, NULL)

#else

    return InternetOpen(userAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0)

#endif

}

HINTERNET Connect(HINTERNET hSession, LPCWSTR serverAddr, int portNo)

{

#ifdef USE_WINHTTP

    return WinHttpConnect(hSession, serverAddr, (INTERNET_PORT) portNo, 0)

#else

    return InternetConnect(hSession, serverAddr, portNo, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0)

#endif

}

HINTERNET OpenRequest(HINTERNET hConnect, LPCWSTR verb, LPCWSTR objectName, int scheme)

{

    DWORD flags = 0

#ifdef USE_WINHTTP

    if (scheme == INTERNET_SCHEME_HTTPS) {

        flags |= WINHTTP_FLAG_SECURE

    }

    return WinHttpOpenRequest(hConnect, verb, objectName, NULL, NULL, NULL, flags)

#else

    if (scheme == INTERNET_SCHEME_HTTPS) {

        flags |= INTERNET_FLAG_SECURE

    }

    return HttpOpenRequest(hConnect, verb, objectName, NULL, NULL, NULL, flags, 0)

#endif

}

BOOL AddRequestHeaders(HINTERNET hRequest, LPCWSTR header)

{

    SIZE_T len = lstrlenW(header)

#ifdef USE_WINHTTP

    return WinHttpAddRequestHeaders(hRequest, header, DWORD(len), WINHTTP_ADDREQ_FLAG_ADD)

#else

    return HttpAddRequestHeaders(hRequest, header, DWORD(len), HTTP_ADDREQ_FLAG_ADD)

#endif

}

BOOL SendRequest(HINTERNET hRequest, const void* body, DWORD size)

{

#ifdef USE_WINHTTP

    return WinHttpSendRequest(hRequest, 0, 0, const_cast<void*>(body), size, size, 0)

#else

    return HttpSendRequest(hRequest, 0, 0, const_cast<void*>(body), size)

#endif

}

BOOL EndRequest(HINTERNET hRequest)

{

#ifdef USE_WINHTTP

    return WinHttpReceiveResponse(hRequest, 0)

#else

    // if you use HttpSendRequestEx to send request then use HttpEndRequest in here!

    return TRUE

#endif

}

BOOL QueryInfo(HINTERNET hRequest, int queryId, char* szBuf, DWORD* pdwSize)

{

#ifdef USE_WINHTTP

    return WinHttpQueryHeaders(hRequest, (DWORD) queryId, 0, szBuf, pdwSize, 0)

#else

    return HttpQueryInfo(hRequest, queryId, szBuf, pdwSize, 0)

#endif

}

BOOL ReadData(HINTERNET hRequest, void* buffer, DWORD length, DWORD* cbRead)

{

#ifdef USE_WINHTTP

    return WinHttpReadData(hRequest, buffer, length, cbRead)

#else

    return InternetReadFile(hRequest, buffer, length, cbRead)

#endif

}

void CloseInternetHandle(HINTERNET hInternet)

{

    if (hInternet)

{

#ifdef USE_WINHTTP

        WinHttpCloseHandle(hInternet)

#else

        InternetCloseHandle(hInternet)

#endif

    }

}

/**********************************************************/

///通过Http方式发送短信

string SendSMS_HTTP(const long ececcid,const string & password ,const string & msisdn, const string &smsContent)

{

 string rtnStr ="-1"

    HINTERNET hSession = 0

    HINTERNET hConnect = 0

    HINTERNET hRequest = 0

    wstring strHeader(L"Content-type: application/x-www-form-urlencoded\r\n")

    // Test data

    CrackedUrl crackedUrl(L"http://pi.f3.cn/SendSMS.aspx")

 string StrPostData = "ececcid=600000&password="+password+"&msisdn="+msisdn+"&smscontent="+smsContent+"&msgtype=5&longcode="

 

 StrPostData = string_To_UTF8(StrPostData)

    // Open session.

    hSession = OpenSession(L"HttpPost by lyz_sea@163.com")

    if (hSession == NULL) {

        cout<<"Error:Open session!\n"

        return "-1"

    }

    // Connect.

    hConnect = Connect(hSession, crackedUrl.GetHostName(), crackedUrl.GetPort())

    if (hConnect == NULL) {

        cout<<"Error:Connect failed!\n"

        return "-1"

    }

    // Open request.

    hRequest = OpenRequest(hConnect, L"POST", crackedUrl.GetPath(), crackedUrl.GetScheme())

    if (hRequest == NULL) {

        cout<<"Error:OpenRequest failed!\n"

        return "-1"

   }

    // Add request header.

 if (!AddRequestHeaders(hRequest, strHeader.c_str())) {

        cout<<"Error:AddRequestHeaders failed!\n"

        return "-1"

    }

    // Send post data.

 if (!SendRequest(hRequest, StrPostData.c_str(), StrPostData.length())) {

        cout<<"Error:SendRequest failed!\n"

        return "-1"

    }

    // End request

    if (!EndRequest(hRequest)) {

        cout<<"Error:EndRequest failed!\n"

        return "-1"

    }

    char szBuf[BUF_SIZE]

    DWORD dwSize = 0

    szBuf[0] = 0

    // Query header info.

#ifdef USE_WINHTTP

    int contextLengthId = WINHTTP_QUERY_CONTENT_LENGTH

    int statusCodeId = WINHTTP_QUERY_STATUS_CODE

    int statusTextId = WINHTTP_QUERY_STATUS_TEXT

#else

    int contextLengthId = HTTP_QUERY_CONTENT_LENGTH

    int statusCodeId = HTTP_QUERY_STATUS_CODE

    int statusTextId = HTTP_QUERY_STATUS_TEXT

#endif

    dwSize = BUF_SIZE

    if (QueryInfo(hRequest, contextLengthId, szBuf, &dwSize)) {

        szBuf[dwSize] = 0

        cout<<"Content length: "<<szBuf<<endl

    }

    dwSize = BUF_SIZE

    if (QueryInfo(hRequest, statusCodeId, szBuf, &dwSize)) {

        szBuf[dwSize] = 0

        cout<<"Status code: "<< szBuf<<endl

    }

    dwSize = BUF_SIZE

    if (QueryInfo(hRequest, statusTextId, szBuf, &dwSize)) {

        szBuf[dwSize] = 0

        cout<<"Status text:"<<szBuf<<endl

    }

    // read data.

    for () {

        dwSize = BUF_SIZE

        if (ReadData(hRequest, szBuf, dwSize, &dwSize) == FALSE) {

           break

        }

        if (dwSize <= 0) {

            break

        }

        szBuf[dwSize] = 0

        

  rtnStr =::UTF8_To_string(string(szBuf))

  cout<<rtnStr<<endl//Output 返回值

   

    }

    CloseInternetHandle(hRequest)

    CloseInternetHandle(hConnect)

    CloseInternetHandle(hSession)

 return  rtnStr

}

 

 

以上方法中用到的CrackURL方法在以下CrackURL.h文件中:

#pragma once

//#include<iostream>

//using namespace std

#define USE_WINHTTP    //Comment this line to user wininet.

 #ifdef USE_WINHTTP

     #include <winhttp.h>

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

 #else

     #include <wininet.h>

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

 #endif

 // CrackedUrl

 class CrackedUrl {

     int m_scheme

     wstring m_host

     int m_port

     wstring m_path

 public:

     CrackedUrl(LPCWSTR url)

     {

         URL_COMPONENTS uc = { 0}

         uc.dwStructSize = sizeof(uc)

 

         const DWORD BUF_LEN = 256

 

         WCHAR host[BUF_LEN]

         uc.lpszHostName = host

         uc.dwHostNameLength = BUF_LEN

 

         WCHAR path[BUF_LEN]

         uc.lpszUrlPath = path

         uc.dwUrlPathLength = BUF_LEN

 

         WCHAR extra[BUF_LEN]

         uc.lpszExtraInfo = extra

         uc.dwExtraInfoLength = BUF_LEN

 

 #ifdef USE_WINHTTP

         if (!WinHttpCrackUrl(url, 0, ICU_ESCAPE, &uc)) {

             cout<<"Error:WinHttpCrackUrl failed!\n"

         }

 

 #else

         if (!InternetCrackUrl(url, 0, ICU_ESCAPE, &uc)) {

             printf("Error:InternetCrackUrl failed!\n")

         }

 #endif

         m_scheme = uc.nScheme

         m_host = host

         m_port = uc.nPort

         m_path = path

     }

 

     int GetScheme() const

     {

         return m_scheme

     }

 

     LPCWSTR GetHostName() const

     {

   return m_host.c_str()

    }

    int GetPort() const

     {

         return m_port

     }

 

     LPCWSTR GetPath() const

     {

   return m_path.c_str()

     }

 

     static string UrlEncode(const char* p)

     {

         if (p == 0) {

             return string()

         }

 

         string buf

 

        for () {

             int ch = (BYTE) (*(p++))

             if (ch == '\0') {

                 break

             }

 

             if (isalnum(ch) || ch == '_' || ch == '-' || ch == '.') {

                 buf += (char)ch

            }

            else if (ch == ' ') {

                buf += '+'

            }

            else {

                char c[16]

                wsprintfA(c, "%%%02X", ch)

                buf += c

            }

        }

        return buf

    }

}

python中没有三目运算,但是有点类似三目运算:

result if True / False else fresult if为真时候结果为result,为假的时候结果为fresult

例子:

result = 'test' if True else 'not test' # result = 'test'

result = 'test' if False else 'not test' # result = 'not test'


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11225503.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-14
下一篇 2023-05-14

发表评论

登录后才能评论

评论列表(0条)

保存