久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

web信息的搜集---Url.h+Url.cpp

 閑來看看 2013-01-18

web信息的搜集---Url.h+Url.cpp

/*

 * Url.h

 * Created on: 2011-10-6

 *      Author: qiuxiong

 * CUrl類的作用:

 * 解析URL,,構(gòu)造HTTP請求報文,發(fā)送給目標服務(wù)器.

 * URL的通用形式是:

 * scheme://hostname[:port][/path][;params][?query][#fragment]

 * scheme 表示協(xié)議名稱,,例如http,ftp,mailto等等

 * hostname 表示主機號,,其實就是該主機對應(yīng)的因特網(wǎng)域名

 * port 表示端口號

 * path 表示URL路徑

 * params 表示對象參數(shù)

 * query 表示查詢信息,也經(jīng)常記為request

 * fragment 表示片段標識

 */

#ifndef URL_H_

#define URL_H_

#include<string>

using namespace std;

const unsigned int URL_LEN=256;//URL最大長度

const unsigned int HOST_LEN=256;//主機號的最大長度

const int DEFAULT_HTTP_PORT=80;//HTTP默認的端口號為80

const int DEFAULT_FTP_PORT=21;//FTP默認的端口號為21

//自定義的枚舉類型:表示協(xié)議類型,有HTTP協(xié)議,,F(xiàn)TP協(xié)議,,其他的無效協(xié)議

enum url_scheme{SCHEME_HTTP,SCHEME_FTP,SCHEME_INVALID};

class CUrl

{

public:

string m_sUrl;//URL字符串

enum url_scheme m_eScheme;//URL解析出的協(xié)議類型

string m_sHost;//URL解析出的主機號

int m_nPort;//URL解析出的端口號

string m_sPath;//URL解析出的請求資源

public:

CUrl();

~CUrl();

bool ParseUrlEx(string strUrl);//解析是不是HTTP協(xié)議的URL,不是返回FALSE,,否則進一步解析URL對應(yīng)的協(xié)議名稱,,主機號,端口號,,請求資源賦值給成員變量,,最后返回TRUE

//真正的解析URL的函數(shù)

void ParseUrlEx(const char *url,char *protocol,int lprotocol,char *host,int lhost,char *request,int lrequest,int *port);

char *GetIpByHost(const char *host);//通過主機號得到IP字符串

bool IsValidHost(const char *host);//判斷該主機號是不是有效的主機號

bool IsForeignHost(string host);//判斷該主機號是否為外國主機號

bool IsImageUrl(string url);//判斷該URL是否為圖片鏈接

bool IsValidIp(const char *ip);//判斷該IP字符串是否有效

bool IsVisitedUrl(const char *url);//判斷該URL是否訪問過

bool IsUnReachedUrl(const char *url);//----沒有實現(xiàn)---------

bool IsValidHostChar(char ch);//判斷該字符是否為構(gòu)成主機號的字符

private:

void ParseScheme(const char *url);//解析出URL所以對應(yīng)的協(xié)類型

};

#endif /* URL_H_ */

/*

 *Url.cpp

 * Created on: 2011-10-6

 *      Author: qiuxiong

 * 有了URL搜集系統(tǒng)就可以根據(jù)URL的標識抓取其對應(yīng)的網(wǎng)頁

 */

#include<iostream>

#include<string>

#include<sys/socket.h>

#include<netdb.h>

#include "Http.h"

#include "Tse.h"

#include "Url.h"

#include "Md5.h"

#include "StrFun.h"

//DNS緩存:我們不能每次解析出了一個主機號就交給DNS server來得到IP,建立一個DNS緩存,,防止出現(xiàn)類似于拒絕訪問攻擊的作用

map<string,string>mapCacheHostLookup;

//這個set容器保存的是已經(jīng)訪問過的URL對應(yīng)的MD5值

extern set<string>setVisitedUrlMD5;//

extern map<unsigned long ,unsigned long>mapIpBlock;//

typedef map<string,string>::value_type valTypeCHL;

pthread_mutex_t mutexCacheHost=PTHREAD_MUTEX_INITIALIZER;//線程的互斥變量初始化

//自定義協(xié)議類-端口-可以訪問,,例如 "http://" 80 1

struct scheme_data

{

char *leading_string;

int default_port;

int enabled;

};

static struct scheme_data supported_schemes[]=

{

{"http://",DEFAULT_HTTP_PORT,1},

{"ftp://",DEFAULT_FTP_PORT,1},

{NULL,-1,0}

};

//解析出URL所以對應(yīng)的協(xié)議類型,然后將協(xié)議類型賦值給成員變量m_eScheme

void CUrl::ParseScheme(const char *url)

{

int i;

for(i=0;supported_schemes[i].leading_string;i++)

if(strncasecmp(url,supported_schemes[i].leading_string,strlen(supported_schemes[i].leading_string))==0)

{

if(supported_schemes[i].enabled)

{

this->m_eScheme=(enum url_scheme)i;//強制轉(zhuǎn)化為枚舉類型

return;

}

else

{

this->m_eScheme=SCHEME_INVALID;

return;

}

}

this->m_eScheme=SCHEME_INVALID;

return;

}

//解析是不是HTTP協(xié)議的URL,不是返回FALSE,,否則進一步解析URL對應(yīng)的協(xié)議名稱,,主機號,端口號,,請求資源賦值給成員變量,,最后返回TRUE

bool CUrl::ParseUrlEx(string strUrl)

{

char protocol[10];

char host[HOST_LEN];

char request[256];

int  port=-1;

memset(protocol,0,sizeof(protocol));

memset(host,0,sizeof(host));

memset(request,0,sizeof(request));

this->ParseScheme(strUrl.c_str());//得到協(xié)議類型

if(this->m_eScheme!=SCHEME_HTTP)//我們只抓取所有協(xié)議名為HTTP的WEB網(wǎng)頁

return false;

ParseUrlEx(strUrl.c_str(),protocol,sizeof(protocol),host,sizeof(host),request,sizeof(request),&port);

m_sUrl=strUrl;

m_sHost=host;

m_sPath=request;

if(port>0)

m_nPort=port;

return true;

}

//真正的解析URL的函數(shù)

void CUrl::ParseUrlEx(const char *url,char *protocol,int lprotocol,char *host,int lhost,char *request,int lrequest,int *port)

{

char *ptr,*ptr2,*work;

*protocol=*host=*request=0;

*port=DEFAULT_HTTP_PORT;

int len=strlen(url);

work=new char[len+1];

memset(work,0,len+1);

strncpy(work,url,len);

ptr=strchr(work,':');//查找work字符串中首次出現(xiàn)':'的位置指針

//得到協(xié)議名稱

if(ptr!=NULL)

{

*(ptr++)=0;

strncpy(protocol,work,lprotocol);

}

else

{

strncpy(protocol,"HTTP",lprotocol);

ptr=work;

}

//跳過"http://"字符

if((*ptr=='/')&&(*(ptr+1)=='/'))

ptr+=2;

ptr2=ptr;

while(IsValidHostChar(*ptr2)&&*ptr2)

ptr2++;

*ptr2=0;

//得到主機號

strncpy(host,ptr,lhost);

int offset=ptr2-work;

const char *pStr=url+offset;

//得到請求資源

strncpy(request,pStr,lrequest);

ptr=strchr(host,':');

//得到端口號

if(ptr!=NULL)

{

*ptr=0;//不能小看這個地方,很有用,,將主機號+端口號相分離

*port=atoi(ptr+1);

}

delete []work;

work=NULL;

}

//無參構(gòu)造函數(shù)

CUrl::CUrl()

{

this->m_sUrl="";

this->m_eScheme=SCHEME_INVALID;

this->m_sHost="";

this->m_sPath="";

this->m_nPort=DEFAULT_HTTP_PORT;

}

//析構(gòu)函數(shù)

CUrl::~CUrl()

{

}

//通過主機號得到IP字符串

char *CUrl::GetIpByHost(const char *host)

{

if(!host)

return NULL;

if(!IsValidHost(host))

return NULL;

unsigned long inaddr=0;

int len=0;

char *result=NULL;

inaddr=(unsigned long)inet_addr(host);//將字符串IP轉(zhuǎn)化為32二進制的網(wǎng)絡(luò)字節(jié)序

if(inaddr!=INADDR_NONE)//表示該主機號就是用IP地址表示的

{

len=strlen(host);

result=new char[len+1];

memset(result,0,len+1);

memcpy(result,host,len);

return result;

}

else//否則,,我在DNS緩存中看能否查找該主機號對應(yīng)的IP字符串

{

map<string,string>::iterator it=mapCacheHostLookup.find(host);

if(it!=mapCacheHostLookup.end())//在DNS緩存中查找到了

{

const char *strHostIp;

strHostIp=(*it).second.c_str();

inaddr=(unsigned long)inet_addr(strHostIp);

if(inaddr!=INADDR_NONE)

{

len=strlen(strHostIp);

result=new char[len+1];

memset(result,0,len+1);

memcpy(result,strHostIp,len);

return result;

}//end if

}//end if

}//end else

//通過上面的方法我們都沒有查找,這個時候我們只能通過DNS server查找了,,這種帶寬的消耗是必要的,!

struct hostent*hp;

hp=gethostbyname(host);//通過主機號或者說是域名得到hostent結(jié)構(gòu),這個結(jié)構(gòu)包含主機號或者說域名的很多信息,,例如我們要找的IP字符串就在其中

if(hp==NULL)

{

cout<<"url.cpp:   gethostbyname()函數(shù)出錯!"<<endl;

return NULL;

}

struct in_addr in;

bcopy(*(hp->h_addr_list),(caddr_t)&in,hp->h_length);

char abuf[INET_ADDRSTRLEN];

//inet_ntop()將32位的二進制網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)化為IP字符串

if(inet_ntop(AF_INET,(void*)&in,abuf,sizeof(abuf))==NULL)

{

cout<<"url.cpp:   inet_ntop()函數(shù)出錯!"<<endl;

return NULL;

}

else

{

pthread_mutex_lock(&mutexCacheHost);//互斥的鎖定函數(shù)

if(mapCacheHostLookup.find(host)==mapCacheHostLookup.end())

mapCacheHostLookup.insert(valTypeCHL(host,abuf));//將新得到的主機號<-->IP字符串插入DNS緩存中

pthread_mutex_unlock(&mutexCacheHost);//互斥的解鎖函數(shù)

}

    len=strlen(abuf);

    result=new char[len+1];

    memset(result,0,len+1);

    memcpy(result,abuf,len);

    return result;

}

//判斷該字符是否為構(gòu)成主機號的字符

bool CUrl::IsValidHostChar(char ch)

{//主機號只能是由26個大小寫字符,,所10個阿拉伯數(shù)字,以及. : - _構(gòu)造而成

return (isalpha(ch)||isdigit(ch)||ch=='.'||ch==':'||ch=='_'||ch=='-');

}

//判斷該主機號是不是有效的主機號

bool CUrl::IsValidHost(const char *host)

{

if(!host)//空的主機號,,我們認為是無效的主機號

return false;

if(strlen(host)<6)//主機號長度小于6,,我們認為ieshi無效的主機號

return false;

unsigned int i;

for(i=0;i<strlen(host);i++)

if(!IsValidHostChar(host[i]))

return false;

return true;

}

//判斷該URL是否訪問過

bool CUrl::IsVisitedUrl(const char *url)

{

if(!url)

return true;

CMD5 iMD5;

iMD5.GenerateMD5((unsigned char*)url,strlen(url));

string strDigest=iMD5.ToString();

if(setVisitedUrlMD5.find(strDigest)!=setVisitedUrlMD5.end())

return true;

return false;

}

//判斷該IP字符串是否有效

bool CUrl::IsValidIp(const char *ip)

{

if(ip==NULL)

return false;

unsigned long inaddr=(unsigned long)inet_addr(ip);

if(inaddr==INADDR_NONE)//顯然該IP參數(shù)不是正確的字符串IP

return false;

if(mapIpBlock.size()>0)

{

map<unsigned long,unsigned long>::iterator pos;

for(pos=mapIpBlock.begin();pos!=mapIpBlock.end();pos++)

{

unsigned long ret;

ret=inaddr&~((*pos).second);

if(ret==(*pos).first)

return true;

}//end for

return false;

}//end if

return true;

}

//判斷該主機號是否為外國主機號

bool CUrl::IsForeignHost(string host)

{

if(host.empty())

return true;

if(host.size()>HOST_LEN)

return true;

unsigned long inaddr=0;

inaddr=(unsigned long)inet_addr(host.c_str());

if(inaddr!=INADDR_NONE)//顯然該HOST是用IP字符串表示的,我們認為它不是外國主機號

return false;//目前無法通過字符串IP判斷是不是外國主機號,所以一律當作國內(nèi)主機號

string::size_type idx=host.rfind('.');

string tmp;//tmp得到的是主機號中的頂級域名

if(idx!=string::npos)

tmp=host.substr(idx+1);

CStrFun::Str2Lower(tmp,tmp.size());

//下面10個頂級域名是我們能訪問的頂級域名,,其他都視為不能訪問的

const char *home_host[]={"cn","com","net","org","info","biz","tv","cc","hk","tw"};

int home_host_num=10;

for(int i=0;i<home_host_num;i++)

if(tmp==home_host[i])

return false;

return true;

}

//判斷該URL是否為圖片鏈接

bool CUrl::IsImageUrl(string url)

{

if(url.empty())

return false;

if(url.size()>URL_LEN)

return false;

string::size_type idx=url.rfind('.');

string tmp;

if(idx!=string::npos)

tmp=url.substr(idx+1);

CStrFun::Str2Lower(tmp,tmp.size());

const char *image_type[]={"jpg","bmp","gif","jpeg","png","tif","psd"};

int image_type_num=7;

for(int i=0;i<image_type_num;i++)

if(tmp==image_type[i])

return true;

return false;

}

//目前不知道系統(tǒng)設(shè)計這個函數(shù)的作用----我在這里讓它一律返回false

bool CUrl::IsUnReachedUrl(const char *url)

{

return false;

}

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多